1/* 2 * getdate.c : entry point for get_dated_revision for ra_serf 3 * 4 * ==================================================================== 5 * Licensed to the Apache Software Foundation (ASF) under one 6 * or more contributor license agreements. See the NOTICE file 7 * distributed with this work for additional information 8 * regarding copyright ownership. The ASF licenses this file 9 * to you under the Apache License, Version 2.0 (the 10 * "License"); you may not use this file except in compliance 11 * with the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, 16 * software distributed under the License is distributed on an 17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 * KIND, either express or implied. See the License for the 19 * specific language governing permissions and limitations 20 * under the License. 21 * ==================================================================== 22 */ 23 24 25 26#include <apr_uri.h> 27#include <serf.h> 28 29#include "svn_pools.h" 30#include "svn_ra.h" 31#include "svn_time.h" 32#include "svn_xml.h" 33 34#include "private/svn_dav_protocol.h" 35 36#include "svn_private_config.h" 37 38#include "../libsvn_ra/ra_loader.h" 39 40#include "ra_serf.h" 41 42 43/* 44 * This enum represents the current state of our XML parsing for a REPORT. 45 */ 46enum date_state_e { 47 INITIAL = XML_STATE_INITIAL, 48 REPORT, 49 VERSION_NAME 50}; 51 52 53typedef struct date_context_t { 54 /* The time asked about. */ 55 apr_time_t time; 56 57 /* What was the youngest revision at that time? */ 58 svn_revnum_t *revision; 59 60} date_context_t; 61 62#define D_ "DAV:" 63#define S_ SVN_XML_NAMESPACE 64static const svn_ra_serf__xml_transition_t date_ttable[] = { 65 { INITIAL, S_, "dated-rev-report", REPORT, 66 FALSE, { NULL }, FALSE }, 67 68 { REPORT, D_, SVN_DAV__VERSION_NAME, VERSION_NAME, 69 TRUE, { NULL }, TRUE }, 70 71 { 0 } 72}; 73 74 75/* Conforms to svn_ra_serf__xml_closed_t */ 76static svn_error_t * 77date_closed(svn_ra_serf__xml_estate_t *xes, 78 void *baton, 79 int leaving_state, 80 const svn_string_t *cdata, 81 apr_hash_t *attrs, 82 apr_pool_t *scratch_pool) 83{ 84 date_context_t *date_ctx = baton; 85 apr_int64_t rev; 86 87 SVN_ERR_ASSERT(leaving_state == VERSION_NAME); 88 SVN_ERR_ASSERT(cdata != NULL); 89 90 SVN_ERR(svn_cstring_atoi64(&rev, cdata->data)); 91 92 *date_ctx->revision = (svn_revnum_t)rev; 93 94 return SVN_NO_ERROR; 95} 96 97 98/* Implements svn_ra_serf__request_body_delegate_t */ 99static svn_error_t * 100create_getdate_body(serf_bucket_t **body_bkt, 101 void *baton, 102 serf_bucket_alloc_t *alloc, 103 apr_pool_t *pool /* request pool */, 104 apr_pool_t *scratch_pool) 105{ 106 serf_bucket_t *buckets; 107 date_context_t *date_ctx = baton; 108 109 buckets = serf_bucket_aggregate_create(alloc); 110 111 svn_ra_serf__add_open_tag_buckets(buckets, alloc, "S:dated-rev-report", 112 "xmlns:S", SVN_XML_NAMESPACE, 113 "xmlns:D", "DAV:", 114 SVN_VA_NULL); 115 116 svn_ra_serf__add_tag_buckets(buckets, 117 "D:" SVN_DAV__CREATIONDATE, 118 svn_time_to_cstring(date_ctx->time, pool), 119 alloc); 120 121 svn_ra_serf__add_close_tag_buckets(buckets, alloc, "S:dated-rev-report"); 122 123 *body_bkt = buckets; 124 return SVN_NO_ERROR; 125} 126 127svn_error_t * 128svn_ra_serf__get_dated_revision(svn_ra_session_t *ra_session, 129 svn_revnum_t *revision, 130 apr_time_t tm, 131 apr_pool_t *pool) 132{ 133 date_context_t *date_ctx; 134 svn_ra_serf__session_t *session = ra_session->priv; 135 svn_ra_serf__handler_t *handler; 136 svn_ra_serf__xml_context_t *xmlctx; 137 const char *report_target; 138 139 date_ctx = apr_palloc(pool, sizeof(*date_ctx)); 140 date_ctx->time = tm; 141 date_ctx->revision = revision; 142 143 SVN_ERR(svn_ra_serf__report_resource(&report_target, session, pool)); 144 145 xmlctx = svn_ra_serf__xml_context_create(date_ttable, 146 NULL, date_closed, NULL, 147 date_ctx, 148 pool); 149 handler = svn_ra_serf__create_expat_handler(session, xmlctx, NULL, pool); 150 151 handler->method = "REPORT"; 152 handler->path = report_target; 153 handler->body_type = "text/xml"; 154 155 handler->body_delegate = create_getdate_body; 156 handler->body_delegate_baton = date_ctx; 157 158 *date_ctx->revision = SVN_INVALID_REVNUM; 159 160 SVN_ERR(svn_ra_serf__context_run_one(handler, pool)); 161 162 if (handler->sline.code != 200) 163 return svn_error_trace(svn_ra_serf__unexpected_status(handler)); 164 165 if (!SVN_IS_VALID_REVNUM(*revision)) 166 return svn_error_create(SVN_ERR_RA_DAV_PROPS_NOT_FOUND, NULL, 167 _("The REPORT response did not include " 168 "the requested properties")); 169 170 return SVN_NO_ERROR; 171} 172