In the command-line client, forbid
[svn.git] / subversion / libsvn_ra_serf / propfind_buckets.c
blob9581829dc41ca8372c7a48ad2209b3c0c5d89962
1 /*
2 * propfind_buckets.c : serf bucket for a PROPFIND request
4 * ====================================================================
5 * Copyright (c) 2006-2007 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
21 #include <stdlib.h>
23 #include <apr_pools.h>
24 #include <apr_strings.h>
25 #include <apr_uri.h>
27 #include <serf.h>
28 #include <serf_bucket_util.h>
30 #include "private/svn_dep_compat.h"
32 #include "ra_serf.h"
34 typedef struct {
35 svn_ra_serf__connection_t *conn;
36 const char *path;
37 const char *label;
38 const char *depth;
39 const svn_ra_serf__dav_props_t *find_props;
40 serf_bucket_t *request;
41 } prop_context_t;
43 const serf_bucket_type_t serf_bucket_type_propfind;
45 #define PROPFIND_HEADER "<?xml version=\"1.0\" encoding=\"utf-8\"?><propfind xmlns=\"DAV:\">"
46 #define PROPFIND_TRAILER "</propfind>"
48 serf_bucket_t * svn_ra_serf__bucket_propfind_create(
49 svn_ra_serf__connection_t *conn,
50 const char *path,
51 const char *label,
52 const char *depth,
53 const svn_ra_serf__dav_props_t *find_props,
54 serf_bucket_alloc_t *allocator)
56 prop_context_t *ctx;
58 ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx));
59 ctx->conn = conn;
60 ctx->path = path;
61 ctx->label = label;
62 ctx->depth = depth;
63 ctx->find_props = find_props;
65 return serf_bucket_create(&serf_bucket_type_propfind, allocator, ctx);
68 static serf_bucket_t *create_propfind_body(serf_bucket_t *bucket)
70 prop_context_t *ctx = bucket->data;
71 serf_bucket_alloc_t *alloc = bucket->allocator;
72 serf_bucket_t *body_bkt, *tmp;
73 const svn_ra_serf__dav_props_t *prop;
74 svn_boolean_t requested_allprop = FALSE;
76 body_bkt = serf_bucket_aggregate_create(alloc);
78 prop = ctx->find_props;
79 while (prop && prop->namespace)
81 /* special case the allprop case. */
82 if (strcmp(prop->name, "allprop") == 0)
84 requested_allprop = TRUE;
87 /* <*propname* xmlns="*propns*" /> */
88 tmp = SERF_BUCKET_SIMPLE_STRING_LEN("<", 1, alloc);
89 serf_bucket_aggregate_append(body_bkt, tmp);
91 tmp = SERF_BUCKET_SIMPLE_STRING(prop->name, alloc);
92 serf_bucket_aggregate_append(body_bkt, tmp);
94 tmp = SERF_BUCKET_SIMPLE_STRING_LEN(" xmlns=\"",
95 sizeof(" xmlns=\"")-1,
96 alloc);
97 serf_bucket_aggregate_append(body_bkt, tmp);
99 tmp = SERF_BUCKET_SIMPLE_STRING(prop->namespace, alloc);
100 serf_bucket_aggregate_append(body_bkt, tmp);
102 tmp = SERF_BUCKET_SIMPLE_STRING_LEN("\"/>", sizeof("\"/>")-1,
103 alloc);
104 serf_bucket_aggregate_append(body_bkt, tmp);
106 prop++;
109 /* If we're not doing an allprop, add <prop> tags. */
110 if (requested_allprop == FALSE)
112 tmp = SERF_BUCKET_SIMPLE_STRING_LEN("<prop>",
113 sizeof("<prop>")-1,
114 alloc);
115 serf_bucket_aggregate_prepend(body_bkt, tmp);
118 tmp = SERF_BUCKET_SIMPLE_STRING_LEN(PROPFIND_HEADER,
119 sizeof(PROPFIND_HEADER)-1,
120 alloc);
122 serf_bucket_aggregate_prepend(body_bkt, tmp);
124 if (requested_allprop == FALSE)
126 tmp = SERF_BUCKET_SIMPLE_STRING_LEN("</prop>",
127 sizeof("</prop>")-1,
128 alloc);
129 serf_bucket_aggregate_append(body_bkt, tmp);
132 tmp = SERF_BUCKET_SIMPLE_STRING_LEN(PROPFIND_TRAILER,
133 sizeof(PROPFIND_TRAILER)-1,
134 alloc);
135 serf_bucket_aggregate_append(body_bkt, tmp);
137 return body_bkt;
140 static void become_request(serf_bucket_t *bucket)
142 prop_context_t *ctx = bucket->data;
143 serf_bucket_t *hdrs_bkt, *body_bkt;
145 body_bkt = create_propfind_body(bucket);
147 serf_bucket_request_become(bucket, "PROPFIND", ctx->path, body_bkt);
148 #if SERF_VERSION_AT_LEAST(0,1,3)
149 if (ctx->conn->session->using_proxy)
151 char *url = apr_uri_unparse(ctx->conn->session->pool,
152 &ctx->conn->session->repos_url,
153 APR_URI_UNP_OMITPATHINFO);
154 serf_bucket_request_set_root(bucket, url);
156 #endif
158 hdrs_bkt = serf_bucket_request_get_headers(bucket);
160 serf_bucket_headers_setn(hdrs_bkt, "Host", ctx->conn->hostinfo);
161 serf_bucket_headers_setn(hdrs_bkt, "User-Agent", USER_AGENT);
162 if (ctx->conn->using_compression == TRUE)
164 serf_bucket_headers_setn(hdrs_bkt, "Accept-Encoding", "gzip");
166 serf_bucket_headers_setn(hdrs_bkt, "Content-Type", "text/xml");
167 serf_bucket_headers_setn(hdrs_bkt, "Depth", ctx->depth);
169 if (ctx->label)
171 serf_bucket_headers_setn(hdrs_bkt, "Label", ctx->label);
174 /* Setup server authorization headers */
175 if (ctx->conn->session->auth_protocol)
176 ctx->conn->session->auth_protocol->setup_request_func(ctx->conn, hdrs_bkt);
178 /* Setup proxy authorization headers */
179 if (ctx->conn->session->proxy_auth_protocol)
180 ctx->conn->session->proxy_auth_protocol->setup_request_func(ctx->conn,
181 hdrs_bkt);
183 serf_bucket_mem_free(bucket->allocator, ctx);
186 static apr_status_t serf_propfind_read(serf_bucket_t *bucket,
187 apr_size_t requested,
188 const char **data, apr_size_t *len)
190 become_request(bucket);
192 /* Delegate to the "new" request bucket to do the readline. */
193 return serf_bucket_read(bucket, requested, data, len);
196 static apr_status_t serf_propfind_readline(serf_bucket_t *bucket,
197 int acceptable, int *found,
198 const char **data, apr_size_t *len)
200 become_request(bucket);
202 /* Delegate to the "new" request bucket to do the readline. */
203 return serf_bucket_readline(bucket, acceptable, found, data, len);
206 static apr_status_t serf_propfind_read_iovec(serf_bucket_t *bucket,
207 apr_size_t requested,
208 int vecs_size,
209 struct iovec *vecs,
210 int *vecs_used)
212 become_request(bucket);
214 /* Delegate to the "new" request bucket to do the peek. */
215 return serf_bucket_read_iovec(bucket, requested, vecs_size, vecs, vecs_used);
218 static apr_status_t serf_propfind_peek(serf_bucket_t *bucket,
219 const char **data,
220 apr_size_t *len)
222 become_request(bucket);
224 /* Delegate to the "new" request bucket to do the peek. */
225 return serf_bucket_peek(bucket, data, len);
228 SERF_DECLARE_DATA const serf_bucket_type_t serf_bucket_type_propfind = {
229 "PROPFIND",
230 serf_propfind_read,
231 serf_propfind_readline,
232 serf_propfind_read_iovec,
233 serf_default_read_for_sendfile,
234 serf_default_read_bucket,
235 serf_propfind_peek,
236 serf_default_destroy_and_data,