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 |