1251881Speter/* 2251881Speter * getlocations.c : entry point for get_locations RA functions for ra_serf 3251881Speter * 4251881Speter * ==================================================================== 5251881Speter * Licensed to the Apache Software Foundation (ASF) under one 6251881Speter * or more contributor license agreements. See the NOTICE file 7251881Speter * distributed with this work for additional information 8251881Speter * regarding copyright ownership. The ASF licenses this file 9251881Speter * to you under the Apache License, Version 2.0 (the 10251881Speter * "License"); you may not use this file except in compliance 11251881Speter * with the License. You may obtain a copy of the License at 12251881Speter * 13251881Speter * http://www.apache.org/licenses/LICENSE-2.0 14251881Speter * 15251881Speter * Unless required by applicable law or agreed to in writing, 16251881Speter * software distributed under the License is distributed on an 17251881Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18251881Speter * KIND, either express or implied. See the License for the 19251881Speter * specific language governing permissions and limitations 20251881Speter * under the License. 21251881Speter * ==================================================================== 22251881Speter */ 23251881Speter 24251881Speter 25251881Speter 26251881Speter#include <apr_uri.h> 27251881Speter 28251881Speter#include <serf.h> 29251881Speter 30251881Speter#include "svn_hash.h" 31251881Speter#include "svn_path.h" 32251881Speter#include "svn_pools.h" 33251881Speter#include "svn_ra.h" 34251881Speter#include "svn_xml.h" 35251881Speter#include "svn_private_config.h" 36251881Speter 37251881Speter#include "../libsvn_ra/ra_loader.h" 38251881Speter 39251881Speter#include "ra_serf.h" 40251881Speter 41251881Speter 42251881Speter/* 43251881Speter * This enum represents the current state of our XML parsing for a REPORT. 44251881Speter */ 45251881Speterenum loc_state_e { 46299742Sdim INITIAL = XML_STATE_INITIAL, 47251881Speter REPORT, 48251881Speter LOCATION 49251881Speter}; 50251881Speter 51251881Spetertypedef struct loc_context_t { 52251881Speter /* pool to allocate memory from */ 53251881Speter apr_pool_t *pool; 54251881Speter 55251881Speter /* parameters set by our caller */ 56251881Speter const char *path; 57251881Speter const apr_array_header_t *location_revisions; 58251881Speter svn_revnum_t peg_revision; 59251881Speter 60251881Speter /* Returned location hash */ 61251881Speter apr_hash_t *paths; 62251881Speter 63251881Speter} loc_context_t; 64251881Speter 65251881Speter#define D_ "DAV:" 66251881Speter#define S_ SVN_XML_NAMESPACE 67251881Speterstatic const svn_ra_serf__xml_transition_t getloc_ttable[] = { 68251881Speter { INITIAL, S_, "get-locations-report", REPORT, 69251881Speter FALSE, { NULL }, FALSE }, 70251881Speter 71251881Speter { REPORT, S_, "location", LOCATION, 72251881Speter FALSE, { "?rev", "?path", NULL }, TRUE }, 73251881Speter 74251881Speter { 0 } 75251881Speter}; 76251881Speter 77251881Speter 78251881Speter/* Conforms to svn_ra_serf__xml_closed_t */ 79251881Speterstatic svn_error_t * 80251881Spetergetloc_closed(svn_ra_serf__xml_estate_t *xes, 81251881Speter void *baton, 82251881Speter int leaving_state, 83251881Speter const svn_string_t *cdata, 84251881Speter apr_hash_t *attrs, 85251881Speter apr_pool_t *scratch_pool) 86251881Speter{ 87251881Speter loc_context_t *loc_ctx = baton; 88251881Speter const char *revstr; 89251881Speter const char *path; 90251881Speter 91251881Speter SVN_ERR_ASSERT(leaving_state == LOCATION); 92251881Speter 93251881Speter revstr = svn_hash_gets(attrs, "rev"); 94251881Speter path = svn_hash_gets(attrs, "path"); 95251881Speter if (revstr != NULL && path != NULL) 96251881Speter { 97299742Sdim apr_int64_t rev_val; 98299742Sdim svn_revnum_t rev; 99299742Sdim 100299742Sdim SVN_ERR(svn_cstring_atoi64(&rev_val, revstr)); 101299742Sdim rev = (svn_revnum_t)rev_val; 102299742Sdim 103251881Speter apr_hash_set(loc_ctx->paths, 104251881Speter apr_pmemdup(loc_ctx->pool, &rev, sizeof(rev)), sizeof(rev), 105251881Speter apr_pstrdup(loc_ctx->pool, path)); 106251881Speter } 107251881Speter 108251881Speter return SVN_NO_ERROR; 109251881Speter} 110251881Speter 111251881Speter 112251881Speter/* Implements svn_ra_serf__request_body_delegate_t */ 113251881Speterstatic svn_error_t * 114251881Spetercreate_get_locations_body(serf_bucket_t **body_bkt, 115251881Speter void *baton, 116251881Speter serf_bucket_alloc_t *alloc, 117299742Sdim apr_pool_t *pool /* request pool */, 118299742Sdim apr_pool_t *scratch_pool) 119251881Speter{ 120251881Speter serf_bucket_t *buckets; 121251881Speter loc_context_t *loc_ctx = baton; 122251881Speter int i; 123251881Speter 124251881Speter buckets = serf_bucket_aggregate_create(alloc); 125251881Speter 126251881Speter svn_ra_serf__add_open_tag_buckets(buckets, alloc, 127251881Speter "S:get-locations", 128251881Speter "xmlns:S", SVN_XML_NAMESPACE, 129251881Speter "xmlns:D", "DAV:", 130299742Sdim SVN_VA_NULL); 131251881Speter 132251881Speter svn_ra_serf__add_tag_buckets(buckets, 133251881Speter "S:path", loc_ctx->path, 134251881Speter alloc); 135251881Speter 136251881Speter svn_ra_serf__add_tag_buckets(buckets, 137251881Speter "S:peg-revision", apr_ltoa(pool, loc_ctx->peg_revision), 138251881Speter alloc); 139251881Speter 140251881Speter for (i = 0; i < loc_ctx->location_revisions->nelts; i++) 141251881Speter { 142251881Speter svn_revnum_t rev = APR_ARRAY_IDX(loc_ctx->location_revisions, i, svn_revnum_t); 143251881Speter svn_ra_serf__add_tag_buckets(buckets, 144251881Speter "S:location-revision", apr_ltoa(pool, rev), 145251881Speter alloc); 146251881Speter } 147251881Speter 148251881Speter svn_ra_serf__add_close_tag_buckets(buckets, alloc, 149251881Speter "S:get-locations"); 150251881Speter 151251881Speter *body_bkt = buckets; 152251881Speter return SVN_NO_ERROR; 153251881Speter} 154251881Speter 155251881Spetersvn_error_t * 156251881Spetersvn_ra_serf__get_locations(svn_ra_session_t *ra_session, 157251881Speter apr_hash_t **locations, 158251881Speter const char *path, 159251881Speter svn_revnum_t peg_revision, 160251881Speter const apr_array_header_t *location_revisions, 161251881Speter apr_pool_t *pool) 162251881Speter{ 163251881Speter loc_context_t *loc_ctx; 164251881Speter svn_ra_serf__session_t *session = ra_session->priv; 165251881Speter svn_ra_serf__handler_t *handler; 166251881Speter svn_ra_serf__xml_context_t *xmlctx; 167251881Speter const char *req_url; 168251881Speter 169251881Speter loc_ctx = apr_pcalloc(pool, sizeof(*loc_ctx)); 170251881Speter loc_ctx->pool = pool; 171251881Speter loc_ctx->path = path; 172251881Speter loc_ctx->peg_revision = peg_revision; 173251881Speter loc_ctx->location_revisions = location_revisions; 174251881Speter loc_ctx->paths = apr_hash_make(loc_ctx->pool); 175251881Speter 176251881Speter *locations = loc_ctx->paths; 177251881Speter 178251881Speter SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */, 179299742Sdim session, NULL /* url */, peg_revision, 180251881Speter pool, pool)); 181251881Speter 182251881Speter xmlctx = svn_ra_serf__xml_context_create(getloc_ttable, 183251881Speter NULL, getloc_closed, NULL, 184251881Speter loc_ctx, 185251881Speter pool); 186299742Sdim handler = svn_ra_serf__create_expat_handler(session, xmlctx, NULL, pool); 187251881Speter 188251881Speter handler->method = "REPORT"; 189251881Speter handler->path = req_url; 190251881Speter handler->body_delegate = create_get_locations_body; 191251881Speter handler->body_delegate_baton = loc_ctx; 192251881Speter handler->body_type = "text/xml"; 193251881Speter 194299742Sdim SVN_ERR(svn_ra_serf__context_run_one(handler, pool)); 195251881Speter 196299742Sdim SVN_ERR(svn_ra_serf__error_on_status(handler->sline, 197299742Sdim handler->path, 198299742Sdim handler->location)); 199251881Speter 200251881Speter return SVN_NO_ERROR; 201251881Speter} 202