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 * ====================================================================
23 #include <apr_pools.h>
24 #include <apr_strings.h>
28 #include <serf_bucket_util.h>
30 #include "private/svn_dep_compat.h"
35 svn_ra_serf__connection_t
*conn
;
39 const svn_ra_serf__dav_props_t
*find_props
;
40 serf_bucket_t
*request
;
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
,
53 const svn_ra_serf__dav_props_t
*find_props
,
54 serf_bucket_alloc_t
*allocator
)
58 ctx
= serf_bucket_mem_alloc(allocator
, sizeof(*ctx
));
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,
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,
104 serf_bucket_aggregate_append(body_bkt
, tmp
);
109 /* If we're not doing an allprop, add <prop> tags. */
110 if (requested_allprop
== FALSE
)
112 tmp
= SERF_BUCKET_SIMPLE_STRING_LEN("<prop>",
115 serf_bucket_aggregate_prepend(body_bkt
, tmp
);
118 tmp
= SERF_BUCKET_SIMPLE_STRING_LEN(PROPFIND_HEADER
,
119 sizeof(PROPFIND_HEADER
)-1,
122 serf_bucket_aggregate_prepend(body_bkt
, tmp
);
124 if (requested_allprop
== FALSE
)
126 tmp
= SERF_BUCKET_SIMPLE_STRING_LEN("</prop>",
129 serf_bucket_aggregate_append(body_bkt
, tmp
);
132 tmp
= SERF_BUCKET_SIMPLE_STRING_LEN(PROPFIND_TRAILER
,
133 sizeof(PROPFIND_TRAILER
)-1,
135 serf_bucket_aggregate_append(body_bkt
, tmp
);
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
);
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
);
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
,
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
,
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
,
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
= {
231 serf_propfind_readline
,
232 serf_propfind_read_iovec
,
233 serf_default_read_for_sendfile
,
234 serf_default_read_bucket
,
236 serf_default_destroy_and_data
,