src/server/webdav/webdav.c

branch
webdav
changeset 213
4a6be4f10d5f
parent 212
d7e7ea9c6bc6
child 214
4d7ac67a1c14
equal deleted inserted replaced
212:d7e7ea9c6bc6 213:4a6be4f10d5f
197 rq->davCollection ? rq->davCollection : &default_backend; 197 rq->davCollection ? rq->davCollection : &default_backend;
198 198
199 // requested uri path 199 // requested uri path
200 char *path = pblock_findkeyval(pb_key_path, rq->vars); 200 char *path = pblock_findkeyval(pb_key_path, rq->vars);
201 201
202 // Initialize WebDAV Backend Chain 202 // VFS settings are only taken from the first backend
203 // 203 uint32_t settings = dav->settings;
204 // Call propfind_init of each Backend 204
205 // list of individual WebdavPropfindRequest objects for each Backend
206 UcxList *requestObjects = NULL;
207
208 // Initialize all Webdav Backends
209 if(webdav_propfind_init(dav, propfind, path, &requestObjects)) {
210 return REQ_ABORTED;
211 }
212
213 // some Backends can list all children by themselves, but some
214 // require the VFS for this
215 WSBool usevfs = (settings & WS_PROPFIND_NO_VFS) != WS_PROPFIND_NO_VFS;
216 struct stat s;
217 struct stat *statptr = NULL;
218
219 VFSContext *vfs = NULL;
220 if(usevfs) {
221 vfs = vfs_request_context(sn, rq);
222
223 if(vfs_stat(vfs, path, &s)) {
224 protocol_status(sn, rq, util_errno2status(vfs->vfs_errno), NULL);
225 return REQ_ABORTED;
226 }
227 statptr = &s;
228 if(!S_ISDIR(s.st_mode)) {
229 // the file is not a directory, therefore we don't need the VFS
230 usevfs = FALSE;
231 }
232 }
233 if(propfind->depth == 0) {
234 usevfs = FALSE;
235 }
236
237 int ret = REQ_ABORTED;
238 if(!webdav_propfind_do(dav, requestObjects, response, NULL, path, statptr)) {
239 // propfind for the requested resource was successful
240
241 // usevfsdir is TRUE if
242 // the webdav backend has not disabled vfs usage
243 // the file is a directory
244 // depth is not 0
245 // in this case we need to execute propfind_do for all children
246 if(usevfs && !propfind_children(dav, requestObjects, response, vfs, path)) {
247 ret = REQ_PROCEED;
248 }
249 }
250
251 // finish the propfind request
252 // this function should cleanup all resources, therefore we execute it
253 // even if a previous function failed
254 if(dav->propfind_finish(propfind)) {
255 ret = REQ_ABORTED;
256 }
257
258 return ret;
259 }
260
261 /*
262 * Initializes Backend Chain
263 *
264 * Calls propfind_init of each Backend and generates a list of custom
265 * WebdavPropfindRequest objects for each backend
266 */
267 int webdav_propfind_init(
268 WebdavBackend *dav,
269 WebdavPropfindRequest *propfind,
270 const char *path,
271 UcxList **out_req)
272 {
273 pool_handle_t *pool = propfind->sn->pool;
274 UcxAllocator *a = session_get_allocator(propfind->sn);
275
276 // list of individual WebdavPropfindRequest objects for each Backend
277 UcxList *requestObjects = NULL;
278
279 // new properties after init, start with clone of original plist
280 WebdavPList *newProp = webdav_plist_clone(pool, propfind->properties);
281 size_t newPropCount = propfind->propcount;
282
283 // Call propfind_init for each Backend
205 // propfind_init can return a new property list, which 284 // propfind_init can return a new property list, which
206 // will be passed to the next backend 285 // will be passed to the next backend
207 // 286
208 // VFS settings are only taken from the first backend
209 uint32_t settings = dav->settings;
210
211 // list of individual WebdavPropfindRequest objects for each Backend
212 UcxList *backendPropfind = NULL;
213
214 // new properties after init, start with clone of original plist
215 WebdavPList *newProp = webdav_plist_clone(sn->pool, propfind->properties);
216 size_t newPropCount = propfind->propcount;
217
218 WebdavBackend *davList = dav; 287 WebdavBackend *davList = dav;
219 while(davList) { 288 while(davList) {
220 // create WebdavPropfindRequest copy 289 // create WebdavPropfindRequest copy
221 WebdavPropfindRequest *pReq = pool_malloc( 290 WebdavPropfindRequest *pReq = pool_malloc(
222 sn->pool, 291 pool,
223 sizeof(WebdavPropfindRequest)); 292 sizeof(WebdavPropfindRequest));
224 memcpy(propfind, pReq, sizeof(WebdavPropfindRequest)); 293 memcpy(propfind, pReq, sizeof(WebdavPropfindRequest));
225 // use new plist after previous init (or orig. plist in the first run) 294 // use new plist after previous init (or orig. plist in the first run)
226 pReq->properties = newProp; 295 pReq->properties = newProp;
227 pReq->propcount = newPropCount; 296 pReq->propcount = newPropCount;
228 297
229 // add new WebdavPropfindRequest object to list for later use 298 // add new WebdavPropfindRequest object to list for later use
230 backendPropfind = ucx_list_append_a(a, backendPropfind, pReq); 299 requestObjects = ucx_list_append_a(a, requestObjects, pReq);
231 if(!backendPropfind) { 300 if(!requestObjects) {
232 return REQ_ABORTED; // OOM 301 return REQ_ABORTED; // OOM
233 } 302 }
234 303
235 // create plist copy as out-plist for init 304 // create plist copy as out-plist for init
236 newProp = webdav_plist_clone(sn->pool, newProp); 305 newProp = webdav_plist_clone(pool, newProp);
237 306
238 // run init: this can generate a new properties list (newProp) 307 // run init: this can generate a new properties list (newProp)
239 // which will be passed to the next backend 308 // which will be passed to the next backend
240 if(dav->propfind_init(pReq, path, &newProp)) { 309 if(dav->propfind_init(pReq, path, &newProp)) {
241 return REQ_ABORTED; 310 return REQ_ABORTED;
244 newPropCount = webdav_plist_count(newProp); 313 newPropCount = webdav_plist_count(newProp);
245 314
246 davList = davList->next; 315 davList = davList->next;
247 } 316 }
248 317
249 // some Backends can list all children by themselves, but some 318 *out_req = requestObjects;
250 // require the VFS for this 319 return REQ_PROCEED;
251 WSBool usevfs = (settings & WS_PROPFIND_NO_VFS) != WS_PROPFIND_NO_VFS; 320 }
252 struct stat s; 321
253 struct stat *statptr = NULL;
254
255 VFSContext *vfs = NULL;
256 if(usevfs) {
257 vfs = vfs_request_context(sn, rq);
258
259 if(vfs_stat(vfs, path, &s)) {
260 protocol_status(sn, rq, util_errno2status(vfs->vfs_errno), NULL);
261 return REQ_ABORTED;
262 }
263 statptr = &s;
264 if(!S_ISDIR(s.st_mode)) {
265 // the file is not a directory, therefore we don't need the VFS
266 usevfs = FALSE;
267 }
268 }
269 if(propfind->depth == 0) {
270 usevfs = FALSE;
271 }
272
273 int ret = REQ_ABORTED;
274 if(!webdav_propfind_do(dav, backendPropfind, response, NULL, path, statptr)) {
275 // propfind for the requested resource was successful
276
277 // usevfsdir is TRUE if
278 // the webdav backend has not disabled vfs usage
279 // the file is a directory
280 // depth is not 0
281 // in this case we need to execute propfind_do for all children
282 if(usevfs && !propfind_children(dav, backendPropfind, response, vfs, path)) {
283 ret = REQ_PROCEED;
284 }
285 }
286
287 // finish the propfind request
288 // this function should cleanup all resources, therefore we execute it
289 // even if a previous function failed
290 if(dav->propfind_finish(propfind)) {
291 ret = REQ_ABORTED;
292 }
293
294 return ret;
295 }
296 322
297 /* 323 /*
298 * Executes propfind_do for each Backend 324 * Executes propfind_do for each Backend
299 * The list requests must contain all WebdavPropfindRequest objects 325 * The list requests must contain all WebdavPropfindRequest objects
300 * of all backends 326 * of all backends

mercurial