]> granicus.if.org Git - apache/commitdiff
first round whack at cleaning up the walker interface
authorGreg Stein <gstein@apache.org>
Thu, 9 Nov 2000 11:23:39 +0000 (11:23 +0000)
committerGreg Stein <gstein@apache.org>
Thu, 9 Nov 2000 11:23:39 +0000 (11:23 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86884 13f79535-47bb-0310-9956-ffa450edef68

modules/dav/fs/repos.c
modules/dav/main/mod_dav.c
modules/dav/main/mod_dav.h
modules/dav/main/util.c
modules/dav/main/util_lock.c

index 8b8606a441a24ae63b573b4ba7e78087060be8e9..ac9de839256f74241b7705de9f1a0b78d556f4e7 100644 (file)
@@ -83,7 +83,11 @@ struct dav_resource_private {
 
 /* private context for doing a filesystem walk */
 typedef struct {
-    dav_walker_ctx *wctx;
+    /* the input walk parameters */
+    const dav_walk_params *params;
+
+    /* reused as we walk */
+    dav_walk_resource wres;
 
     dav_resource res1;
     dav_resource res2;
@@ -92,6 +96,8 @@ typedef struct {
     dav_buffer path1;
     dav_buffer path2;
 
+    dav_buffer uri_buf; /* URI for res1 */
+
     dav_buffer locknull_buf;
 
 } dav_fs_walker_context;
@@ -907,13 +913,15 @@ static dav_error * dav_fs_create_collection(dav_resource *resource)
     return NULL;
 }
 
-static dav_error * dav_fs_copymove_walker(dav_walker_ctx *ctx, int calltype)
+static dav_error * dav_fs_copymove_walker(dav_walk_resource *wres,
+                                          int calltype)
 {
-    dav_resource_private *srcinfo = ctx->resource->info;
-    dav_resource_private *dstinfo = ctx->res2->info;
+    dav_walker_ctx *ctx = wres->walk_ctx;
+    dav_resource_private *srcinfo = wres->resource->info;
+    dav_resource_private *dstinfo = wres->res_dst->info;
     dav_error *err = NULL;
 
-    if (ctx->resource->collection) {
+    if (wres->resource->collection) {
        if (calltype == DAV_CALLTYPE_POSTFIX) {
            /* Postfix call for MOVE. delete the source dir.
             * Note: when copying, we do not enable the postfix-traversal.
@@ -923,16 +931,16 @@ static dav_error * dav_fs_copymove_walker(dav_walker_ctx *ctx, int calltype)
        }
         else {
            /* copy/move of a collection. Create the new, target collection */
-            if (apr_make_dir(dstinfo->pathname, APR_OS_DEFAULT, ctx->pool) 
-               != APR_SUCCESS) {
+            if (apr_make_dir(dstinfo->pathname, APR_OS_DEFAULT,
+                             ctx->w.pool) != APR_SUCCESS) {
                /* ### assume it was a permissions problem */
                /* ### need a description here */
-                err = dav_new_error(ctx->pool, HTTP_FORBIDDEN, 0, NULL);
+                err = dav_new_error(ctx->w.pool, HTTP_FORBIDDEN, 0, NULL);
             }
        }
     }
     else {
-       err = dav_fs_copymove_file(ctx->is_move, ctx->pool, 
+       err = dav_fs_copymove_file(ctx->is_move, ctx->w.pool, 
                                   srcinfo->pathname, dstinfo->pathname, 
                                   &ctx->work_buf);
        /* ### push a higher-level description? */
@@ -953,9 +961,9 @@ static dav_error * dav_fs_copymove_walker(dav_walker_ctx *ctx, int calltype)
     if (err != NULL
         && !ap_is_HTTP_SERVER_ERROR(err->status)
        && (ctx->is_move
-            || !dav_fs_is_same_resource(ctx->resource, ctx->root))) {
+            || !dav_fs_is_same_resource(wres->resource, ctx->w.root))) {
        /* ### use errno to generate DAV:responsedescription? */
-       dav_add_response(ctx, ctx->resource->uri, err->status, NULL);
+       dav_add_response(wres, err->status, NULL);
 
         /* the error is in the multistatus now. do not stop the traversal. */
         return NULL;
@@ -980,18 +988,20 @@ static dav_error *dav_fs_copymove_resource(
      * including the state dirs
      */
     if (src->collection) {
-       dav_walker_ctx ctx = { 0 };
+       dav_walker_ctx ctx = { { 0 } };
+
+       ctx.w.walk_type = DAV_WALKTYPE_ALL | DAV_WALKTYPE_HIDDEN;
+       ctx.w.func = dav_fs_copymove_walker;
+        ctx.w.walk_ctx = &ctx;
+       ctx.w.pool = src->info->pool;
+       ctx.w.root = src;
+       ctx.w.root_dst = dst;
 
-       ctx.walk_type = DAV_WALKTYPE_ALL | DAV_WALKTYPE_HIDDEN;
-       ctx.func = dav_fs_copymove_walker;
-       ctx.pool = src->info->pool;
-       ctx.resource = src;
-       ctx.res2 = dst;
        ctx.is_move = is_move;
-       ctx.postfix = is_move;  /* needed for MOVE to delete source dirs */
 
-       /* copy over the source URI */
-       dav_buffer_init(ctx.pool, &ctx.uri, src->uri);
+       /* postfix is needed for MOVE to delete source dirs */
+        if (is_move)
+            ctx.w.walk_type |= DAV_WALKTYPE_POSTFIX;
 
        if ((err = dav_fs_walk(&ctx, depth)) != NULL) {
             /* on a "real" error, then just punt. nothing else to do. */
@@ -1167,19 +1177,19 @@ static dav_error * dav_fs_move_resource(
                          err);
 }
 
-static dav_error * dav_fs_delete_walker(dav_walker_ctx *ctx, int calltype)
+static dav_error * dav_fs_delete_walker(dav_walk_resource *wres, int calltype)
 {
-    dav_resource_private *info = ctx->resource->info;
+    dav_resource_private *info = wres->resource->info;
 
     /* do not attempt to remove a null resource,
      * or a collection with children
      */
-    if (ctx->resource->exists &&
-        (!ctx->resource->collection || calltype == DAV_CALLTYPE_POSTFIX)) {
+    if (wres->resource->exists &&
+        (!wres->resource->collection || calltype == DAV_CALLTYPE_POSTFIX)) {
        /* try to remove the resource */
        int result;
 
-       result = ctx->resource->collection
+       result = wres->resource->collection
            ? rmdir(info->pathname)
            : remove(info->pathname);
 
@@ -1194,7 +1204,7 @@ static dav_error * dav_fs_delete_walker(dav_walker_ctx *ctx, int calltype)
             /* ### assume there is a permissions problem */
 
             /* ### use errno to generate DAV:responsedescription? */
-            dav_add_response(ctx, ctx->resource->uri, HTTP_FORBIDDEN, NULL);
+            dav_add_response(wres, HTTP_FORBIDDEN, NULL);
        }
     }
 
@@ -1212,16 +1222,16 @@ static dav_error * dav_fs_remove_resource(dav_resource *resource,
      * including the state dirs
      */
     if (resource->collection) {
-       dav_walker_ctx ctx = { 0 };
+       dav_walker_ctx ctx = { { 0 } };
        dav_error *err = NULL;
 
-       ctx.walk_type = DAV_WALKTYPE_ALL | DAV_WALKTYPE_HIDDEN;
-       ctx.postfix = 1;
-       ctx.func = dav_fs_delete_walker;
-       ctx.pool = info->pool;
-       ctx.resource = resource;
-
-       dav_buffer_init(info->pool, &ctx.uri, resource->uri);
+       ctx.w.walk_type = (DAV_WALKTYPE_ALL
+                           | DAV_WALKTYPE_HIDDEN
+                           | DAV_WALKTYPE_POSTFIX);
+       ctx.w.func = dav_fs_delete_walker;
+        ctx.w.walk_ctx = &ctx;
+       ctx.w.pool = info->pool;
+       ctx.w.root = resource;
 
        if ((err = dav_fs_walk(&ctx, DAV_INFINITY)) != NULL) {
             /* on a "real" error, then just punt. nothing else to do. */
@@ -1261,16 +1271,17 @@ static dav_error * dav_fs_remove_resource(dav_resource *resource,
  * including lock-null resources as we go.    */
 static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
 {
+    const dav_walk_params *params = fsctx->params;
+    apr_pool_t *pool = params->pool;
     dav_error *err = NULL;
-    dav_walker_ctx *wctx = fsctx->wctx;
-    int isdir = wctx->resource->collection;
+    int isdir = fsctx->res1.collection;
     apr_dir_t *dirp;
 
     /* ensure the context is prepared properly, then call the func */
-    err = (*wctx->func)(wctx,
-                       isdir
-                       ? DAV_CALLTYPE_COLLECTION
-                       : DAV_CALLTYPE_MEMBER);
+    err = (*params->func)(&fsctx->wres,
+                          isdir
+                          ? DAV_CALLTYPE_COLLECTION
+                          : DAV_CALLTYPE_MEMBER);
     if (err != NULL) {
        return err;
     }
@@ -1281,13 +1292,13 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
 
     /* put a trailing slash onto the directory, in preparation for appending
      * files to it as we discovery them within the directory */
-    dav_check_bufsize(wctx->pool, &fsctx->path1, DAV_BUFFER_PAD);
+    dav_check_bufsize(pool, &fsctx->path1, DAV_BUFFER_PAD);
     fsctx->path1.buf[fsctx->path1.cur_len++] = '/';
     fsctx->path1.buf[fsctx->path1.cur_len] = '\0';     /* in pad area */
 
     /* if a secondary path is present, then do that, too */
     if (fsctx->path2.buf != NULL) {
-       dav_check_bufsize(wctx->pool, &fsctx->path2, DAV_BUFFER_PAD);
+       dav_check_bufsize(pool, &fsctx->path2, DAV_BUFFER_PAD);
        fsctx->path2.buf[fsctx->path2.cur_len++] = '/';
        fsctx->path2.buf[fsctx->path2.cur_len] = '\0';  /* in pad area */
     }
@@ -1302,9 +1313,9 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
     fsctx->res2.collection = 0;
 
     /* open and scan the directory */
-    if ((apr_opendir(&dirp, fsctx->path1.buf, wctx->pool)) != APR_SUCCESS) {
+    if ((apr_opendir(&dirp, fsctx->path1.buf, pool)) != APR_SUCCESS) {
        /* ### need a better error */
-       return dav_new_error(wctx->pool, HTTP_NOT_FOUND, 0, NULL);
+       return dav_new_error(pool, HTTP_NOT_FOUND, 0, NULL);
     }
     while ((apr_readdir(dirp)) == APR_SUCCESS) {
        char *name;
@@ -1318,7 +1329,7 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
            continue;
        }
 
-       if (wctx->walk_type & DAV_WALKTYPE_AUTH) {
+       if (params->walk_type & DAV_WALKTYPE_AUTH) {
            /* ### need to authorize each file */
            /* ### example: .htaccess is normally configured to fail auth */
 
@@ -1328,28 +1339,28 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
            }
        }
        /* skip the state dir unless a HIDDEN is performed */
-       if (!(wctx->walk_type & DAV_WALKTYPE_HIDDEN)
+       if (!(params->walk_type & DAV_WALKTYPE_HIDDEN)
            && !strcmp(name, DAV_FS_STATE_DIR)) {
            continue;
        }
 
        /* append this file onto the path buffer (copy null term) */
-       dav_buffer_place_mem(wctx->pool, &fsctx->path1, name, len + 1, 0);
+       dav_buffer_place_mem(pool, &fsctx->path1, name, len + 1, 0);
 
-       if (apr_lstat(&fsctx->info1.finfo, fsctx->path1.buf, wctx->pool) != 0) {
+       if (apr_lstat(&fsctx->info1.finfo, fsctx->path1.buf, pool) != 0) {
            /* woah! where'd it go? */
            /* ### should have a better error here */
-           err = dav_new_error(wctx->pool, HTTP_NOT_FOUND, 0, NULL);
+           err = dav_new_error(pool, HTTP_NOT_FOUND, 0, NULL);
            break;
        }
 
        /* copy the file to the URI, too. NOTE: we will pad an extra byte
           for the trailing slash later. */
-       dav_buffer_place_mem(wctx->pool, &wctx->uri, name, len + 1, 1);
+       dav_buffer_place_mem(pool, &fsctx->uri_buf, name, len + 1, 1);
 
        /* if there is a secondary path, then do that, too */
        if (fsctx->path2.buf != NULL) {
-           dav_buffer_place_mem(wctx->pool, &fsctx->path2, name, len + 1, 0);
+           dav_buffer_place_mem(pool, &fsctx->path2, name, len + 1, 0);
        }
 
        /* set up the (internal) pathnames for the two resources */
@@ -1357,19 +1368,20 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
        fsctx->info2.pathname = fsctx->path2.buf;
 
        /* set up the URI for the current resource */
-       fsctx->res1.uri = wctx->uri.buf;
+       fsctx->res1.uri = fsctx->uri_buf.buf;
 
        /* ### for now, only process regular files (e.g. skip symlinks) */
        if (fsctx->info1.finfo.filetype == APR_REG) {
            /* call the function for the specified dir + file */
-           if ((err = (*wctx->func)(wctx, DAV_CALLTYPE_MEMBER)) != NULL) {
+           if ((err = (*params->func)(&fsctx->wres,
+                                       DAV_CALLTYPE_MEMBER)) != NULL) {
                /* ### maybe add a higher-level description? */
                break;
            }
        }
        else if (fsctx->info1.finfo.filetype == APR_DIR) {
            size_t save_path_len = fsctx->path1.cur_len;
-           size_t save_uri_len = wctx->uri.cur_len;
+           size_t save_uri_len = fsctx->uri_buf.cur_len;
            size_t save_path2_len = fsctx->path2.cur_len;
 
            /* adjust length to incorporate the subdir name */
@@ -1377,9 +1389,9 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
            fsctx->path2.cur_len += len;
 
            /* adjust URI length to incorporate subdir and a slash */
-           wctx->uri.cur_len += len + 1;
-           wctx->uri.buf[wctx->uri.cur_len - 1] = '/';
-           wctx->uri.buf[wctx->uri.cur_len] = '\0';
+           fsctx->uri_buf.cur_len += len + 1;
+           fsctx->uri_buf.buf[fsctx->uri_buf.cur_len - 1] = '/';
+           fsctx->uri_buf.buf[fsctx->uri_buf.cur_len] = '\0';
 
            /* switch over to a collection */
            fsctx->res1.collection = 1;
@@ -1395,7 +1407,7 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
            /* put the various information back */
            fsctx->path1.cur_len = save_path_len;
            fsctx->path2.cur_len = save_path2_len;
-           wctx->uri.cur_len = save_uri_len;
+           fsctx->uri_buf.cur_len = save_uri_len;
 
            fsctx->res1.collection = 0;
            fsctx->res2.collection = 0;
@@ -1410,7 +1422,7 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
     if (err != NULL)
        return err;
 
-    if (wctx->walk_type & DAV_WALKTYPE_LOCKNULL) {
+    if (params->walk_type & DAV_WALKTYPE_LOCKNULL) {
        size_t offset = 0;
 
        /* null terminate the directory name */
@@ -1441,12 +1453,12 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
            ** we don't have to pad the URI for a slash since a locknull
            ** resource is not a collection.
            */
-           dav_buffer_place_mem(wctx->pool, &fsctx->path1,
+           dav_buffer_place_mem(pool, &fsctx->path1,
                                 fsctx->locknull_buf.buf + offset, len + 1, 0);
-           dav_buffer_place_mem(wctx->pool, &wctx->uri,
+           dav_buffer_place_mem(pool, &fsctx->uri_buf,
                                 fsctx->locknull_buf.buf + offset, len + 1, 0);
            if (fsctx->path2.buf != NULL) {
-               dav_buffer_place_mem(wctx->pool, &fsctx->path2,
+               dav_buffer_place_mem(pool, &fsctx->path2,
                                     fsctx->locknull_buf.buf + offset,
                                      len + 1, 0);
            }
@@ -1456,7 +1468,7 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
            fsctx->info2.pathname = fsctx->path2.buf;
 
            /* set up the URI for the current resource */
-           fsctx->res1.uri = wctx->uri.buf;
+           fsctx->res1.uri = fsctx->uri_buf.buf;
 
            /*
            ** To prevent a PROPFIND showing an expired locknull
@@ -1488,14 +1500,16 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
               ### even the resolve func would probably fail when it
               ### tried to find a timed-out direct lock).
            */
-           if ((err = dav_lock_query(wctx->lockdb, wctx->resource, &locks)) != NULL) {
+           if ((err = dav_lock_query(params->lockdb, &fsctx->res1,
+                                      &locks)) != NULL) {
                /* ### maybe add a higher-level description? */
                return err;
            }
 
            /* call the function for the specified dir + file */
            if (locks != NULL &&
-               (err = (*wctx->func)(wctx, DAV_CALLTYPE_LOCKNULL)) != NULL) {
+               (err = (*params->func)(&fsctx->wres,
+                                       DAV_CALLTYPE_LOCKNULL)) != NULL) {
                /* ### maybe add a higher-level description? */
                return err;
            }
@@ -1507,10 +1521,10 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
        fsctx->res1.exists = 1;
     }
 
-    if (wctx->postfix) {
+    if (params->walk_type & DAV_WALKTYPE_POSTFIX) {
        /* replace the dirs' trailing slashes with null terms */
        fsctx->path1.buf[--fsctx->path1.cur_len] = '\0';
-       wctx->uri.buf[--wctx->uri.cur_len] = '\0';
+       fsctx->uri_buf.buf[--fsctx->uri_buf.cur_len] = '\0';
        if (fsctx->path2.buf != NULL) {
            fsctx->path2.buf[--fsctx->path2.cur_len] = '\0';
        }
@@ -1518,7 +1532,7 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
        /* this is a collection which exists */
        fsctx->res1.collection = 1;
 
-       return (*wctx->func)(wctx, DAV_CALLTYPE_POSTFIX);
+       return (*params->func)(&fsctx->wres, DAV_CALLTYPE_POSTFIX);
     }
 
     return NULL;
@@ -1526,60 +1540,57 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
 
 static dav_error * dav_fs_walk(dav_walker_ctx *wctx, int depth)
 {
+    const dav_walk_params *params = &wctx->w;
     dav_fs_walker_context fsctx = { 0 };
+    dav_error *err;
 
 #if DAV_DEBUG
-    if ((wctx->walk_type & DAV_WALKTYPE_LOCKNULL) != 0
-       && wctx->lockdb == NULL) {
-       return dav_new_error(wctx->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
+    if ((params->walk_type & DAV_WALKTYPE_LOCKNULL) != 0
+       && params->lockdb == NULL) {
+       return dav_new_error(params->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
                             "DESIGN ERROR: walker called to walk locknull "
                             "resources, but a lockdb was not provided.");
     }
-
-    /* ### an assertion that we have space for a trailing slash */
-    if (wctx->uri.cur_len + 1 > wctx->uri.alloc_len) {
-       return dav_new_error(wctx->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
-                            "DESIGN ERROR: walker should have been called "
-                            "with padding in the URI buffer.");
-    }
 #endif
 
-    fsctx.wctx = wctx;
-
-    wctx->root = wctx->resource;
+    fsctx.params = params;
+    fsctx.wres.walk_ctx = params->walk_ctx;
 
     /* ### zero out versioned, working, baselined? */
 
-    fsctx.res1 = *wctx->resource;
+    fsctx.res1 = *params->root;
 
     fsctx.res1.info = &fsctx.info1;
-    fsctx.info1 = *wctx->resource->info;
+    fsctx.info1 = *params->root->info;
 
-    dav_buffer_init(wctx->pool, &fsctx.path1, fsctx.info1.pathname);
+    dav_buffer_init(params->pool, &fsctx.path1, fsctx.info1.pathname);
     fsctx.info1.pathname = fsctx.path1.buf;
 
-    if (wctx->res2 != NULL) {
-       fsctx.res2 = *wctx->res2;
+    if (params->root_dst != NULL) {
+       fsctx.res2 = *params->root_dst;
        fsctx.res2.exists = 0;
        fsctx.res2.collection = 0;
 
        fsctx.res2.info = &fsctx.info2;
-       fsctx.info2 = *wctx->res2->info;
+       fsctx.info2 = *params->root_dst->info;
 
        /* res2 does not exist -- clear its finfo structure */
        memset(&fsctx.info2.finfo, 0, sizeof(fsctx.info2.finfo));
 
-       dav_buffer_init(wctx->pool, &fsctx.path2, fsctx.info2.pathname);
+       dav_buffer_init(params->pool, &fsctx.path2, fsctx.info2.pathname);
        fsctx.info2.pathname = fsctx.path2.buf;
     }
 
+    /* prep the URI buffer */
+    dav_buffer_init(params->pool, &fsctx.uri_buf, params->root->uri);
+
     /* if we have a directory, then ensure the URI has a trailing "/" */
     if (fsctx.res1.collection
-       && wctx->uri.buf[wctx->uri.cur_len - 1] != '/') {
+       && fsctx.uri_buf.buf[fsctx.uri_buf.cur_len - 1] != '/') {
 
        /* this will fall into the pad area */
-       wctx->uri.buf[wctx->uri.cur_len++] = '/';
-       wctx->uri.buf[wctx->uri.cur_len] = '\0';
+       fsctx.uri_buf.buf[fsctx.uri_buf.cur_len++] = '/';
+       fsctx.uri_buf.buf[fsctx.uri_buf.cur_len] = '\0';
     }
 
     /*
@@ -1587,14 +1598,16 @@ static dav_error * dav_fs_walk(dav_walker_ctx *wctx, int depth)
     ** to fetch it from res2. We will ensure that res1 and uri will remain
     ** synchronized.
     */
-    fsctx.res1.uri = wctx->uri.buf;
+    fsctx.res1.uri = fsctx.uri_buf.buf;
     fsctx.res2.uri = NULL;
 
     /* use our resource structures */
-    wctx->resource = &fsctx.res1;
-    wctx->res2 = &fsctx.res2;
+    fsctx.wres.resource = &fsctx.res1;
+    fsctx.wres.res_dst = &fsctx.res2;
 
-    return dav_fs_walker(&fsctx, depth);
+    err = dav_fs_walker(&fsctx, depth);
+    wctx->response = fsctx.wres.response;
+    return err;
 }
 
 /* dav_fs_etag:  Stolen from ap_make_etag.  Creates a strong etag
index f01399a9a75e7fe4b09dfd6a548e22cdb691a603..703036d5d9b644bcaa768971ec51e79d1687a893 100644 (file)
@@ -1174,21 +1174,22 @@ static int dav_method_put(request_rec *r)
 }
 
 /* ### move this to dav_util? */
-DAV_DECLARE(void) dav_add_response(dav_walker_ctx *ctx, const char *href, 
+DAV_DECLARE(void) dav_add_response(dav_walk_resource *wres,
                                    int status, dav_get_props_result *propstats)
 {
+    dav_walker_ctx *ctx = wres->walk_ctx;
     dav_response *resp;
 
     /* just drop some data into an dav_response */
-    resp = apr_pcalloc(ctx->pool, sizeof(*resp));
-    resp->href = apr_pstrdup(ctx->pool, href);
+    resp = apr_pcalloc(ctx->w.pool, sizeof(*resp));
+    resp->href = apr_pstrdup(ctx->w.pool, wres->resource->uri);
     resp->status = status;
     if (propstats) {
        resp->propresult = *propstats;
     }
-    resp->next = ctx->response;
 
-    ctx->response = resp;
+    resp->next = wres->response;
+    wres->response = resp;
 }
 
 /* handle the DELETE method */
@@ -1451,16 +1452,17 @@ static void dav_cache_badprops(dav_walker_ctx *ctx)
        return;
     }
 
-    ap_text_append(ctx->pool, &hdr,
+    ap_text_append(ctx->w.pool, &hdr,
                   "<D:propstat>" DEBUG_CR
                   "<D:prop>" DEBUG_CR);
 
     elem = dav_find_child(ctx->doc->root, "prop");
     for (elem = elem->first_child; elem; elem = elem->next) {
-       ap_text_append(ctx->pool, &hdr, ap_xml_empty_elem(ctx->pool, elem));
+       ap_text_append(ctx->w.pool, &hdr,
+                       ap_xml_empty_elem(ctx->w.pool, elem));
     }
 
-    ap_text_append(ctx->pool, &hdr,
+    ap_text_append(ctx->w.pool, &hdr,
                   "</D:prop>" DEBUG_CR
                   "<D:status>HTTP/1.1 404 Not Found</D:status>" DEBUG_CR
                   "</D:propstat>" DEBUG_CR);
@@ -1468,8 +1470,9 @@ static void dav_cache_badprops(dav_walker_ctx *ctx)
     ctx->propstat_404 = hdr.first;
 }
 
-static dav_error * dav_propfind_walker(dav_walker_ctx *ctx, int calltype)
+static dav_error * dav_propfind_walker(dav_walk_resource *wres, int calltype)
 {
+    dav_walker_ctx *ctx = wres->walk_ctx;
     dav_error *err;
     dav_propdb *propdb;
     dav_get_props_result propstats = { 0 };
@@ -1482,8 +1485,8 @@ static dav_error * dav_propfind_walker(dav_walker_ctx *ctx, int calltype)
     ** Note: we cast to lose the "const". The propdb won't try to change
     ** the resource, however, since we are opening readonly.
     */
-    err = dav_open_propdb(ctx->r, ctx->lockdb,
-                         (dav_resource *)ctx->resource, 1,
+    err = dav_open_propdb(ctx->r, ctx->w.lockdb,
+                         (dav_resource *)wres->resource, 1,
                          ctx->doc ? ctx->doc->namespaces : NULL, &propdb);
     if (err != NULL) {
        /* ### do something with err! */
@@ -1494,11 +1497,11 @@ static dav_error * dav_propfind_walker(dav_walker_ctx *ctx, int calltype)
            /* some props were expected on this collection/resource */
            dav_cache_badprops(ctx);
            badprops.propstats = ctx->propstat_404;
-           dav_add_response(ctx, ctx->uri.buf, 0, &badprops);
+           dav_add_response(wres, 0, &badprops);
        }
        else {
            /* no props on this collection/resource */
-           dav_add_response(ctx, ctx->uri.buf, HTTP_OK, NULL);
+           dav_add_response(wres, HTTP_OK, NULL);
        }
        return NULL;
     }
@@ -1513,7 +1516,7 @@ static dav_error * dav_propfind_walker(dav_walker_ctx *ctx, int calltype)
     }
     dav_close_propdb(propdb);
 
-    dav_add_response(ctx, ctx->uri.buf, 0, &propstats);
+    dav_add_response(wres, 0, &propstats);
 
     return NULL;
 }
@@ -1527,7 +1530,7 @@ static int dav_method_propfind(request_rec *r)
     int result;
     ap_xml_doc *doc;
     const ap_xml_elem *child;
-    dav_walker_ctx ctx = { 0 };
+    dav_walker_ctx ctx = { { 0 } };
 
     /* Ask repository module to resolve the resource */
     result = dav_get_resource(r, 1 /*target_allowed*/, NULL, &resource);
@@ -1596,17 +1599,17 @@ static int dav_method_propfind(request_rec *r)
        return HTTP_BAD_REQUEST;
     }
 
-    ctx.walk_type = DAV_WALKTYPE_ALL | DAV_WALKTYPE_AUTH;
-    ctx.func = dav_propfind_walker;
-    ctx.pool = r->pool;
+    ctx.w.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_AUTH;
+    ctx.w.func = dav_propfind_walker;
+    ctx.w.walk_ctx = &ctx;
+    ctx.w.pool = r->pool;
+    ctx.w.root = resource;
+
     ctx.doc = doc;
     ctx.r = r;
-    ctx.resource = resource;
-
-    dav_buffer_init(r->pool, &ctx.uri, r->uri);
 
     /* ### should open read-only */
-    if ((err = dav_open_lockdb(r, 0, &ctx.lockdb)) != NULL) {
+    if ((err = dav_open_lockdb(r, 0, &ctx.w.lockdb)) != NULL) {
        err = dav_push_error(r->pool, err->status, 0,
                             "The lock database could not be opened, "
                             "preventing access to the various lock "
@@ -1614,15 +1617,15 @@ static int dav_method_propfind(request_rec *r)
                             err);
        return dav_handle_err(r, err, NULL);
     }
-    if (ctx.lockdb != NULL) {
+    if (ctx.w.lockdb != NULL) {
        /* if we have a lock database, then we can walk locknull resources */
-       ctx.walk_type |= DAV_WALKTYPE_LOCKNULL;
+       ctx.w.walk_type |= DAV_WALKTYPE_LOCKNULL;
     }
 
     err = (*resource->hooks->walk)(&ctx, depth);
 
-    if (ctx.lockdb != NULL) {
-       (*ctx.lockdb->hooks->close_lockdb)(ctx.lockdb);
+    if (ctx.w.lockdb != NULL) {
+       (*ctx.w.lockdb->hooks->close_lockdb)(ctx.w.lockdb);
     }
 
     if (err != NULL) {
index ea65bd5cc8af6ac1fe63b201695f9593d1139499..daf2b5fd0bb016eab98ae504d179d6692dfdac2c 100644 (file)
@@ -1220,38 +1220,72 @@ void dav_prop_rollback(dav_prop_ctx *ctx);
 ** WALKER STRUCTURE
 */
 
-/* private, opaque info structure for repository walking context */
-typedef struct dav_walker_private dav_walker_private;
+enum {
+    DAV_CALLTYPE_MEMBER = 1,   /* called for a member resource */
+    DAV_CALLTYPE_COLLECTION,   /* called for a collection */
+    DAV_CALLTYPE_LOCKNULL,     /* called for a locknull resource */
+    DAV_CALLTYPE_POSTFIX       /* postfix call for a collection */
+};
 
-/* directory tree walking context */
-typedef struct dav_walker_ctx
+typedef struct
+{
+    /* the client-provided context */
+    void *walk_ctx;
+
+    /* the current resource */
+    const dav_resource *resource;
+
+    /* the current secondary/tracking resource */
+    const dav_resource *res_dst;
+
+    /* OUTPUT: add responses to this */
+    dav_response *response;
+
+} dav_walk_resource;
+
+typedef struct
 {
     int walk_type;
-#define DAV_WALKTYPE_AUTH      1       /* limit to authorized files */
-#define DAV_WALKTYPE_ALL       2       /* walk normal files */
-#define DAV_WALKTYPE_HIDDEN    4       /* walk hidden files */
-#define DAV_WALKTYPE_LOCKNULL  8       /* walk locknull resources */
+#define DAV_WALKTYPE_AUTH      0x0001  /* limit to authorized files */
+#define DAV_WALKTYPE_NORMAL    0x0002  /* walk normal files */
+#define DAV_WALKTYPE_LOCKNULL  0x0004  /* walk locknull resources */
+
+#define DAV_WALKTYPE_POSTFIX    0x0100  /* do postfix call for collections */
 
-    int postfix;               /* call func for dirs after files */
+#define DAV_WALKTYPE_ALL       DAV_WALKTYPE_NORMAL     /* ### compat */
+#define DAV_WALKTYPE_HIDDEN    0x1000  /* walk hidden files */
 
-    dav_error * (*func)(struct dav_walker_ctx *ctx, int calltype);
-#define DAV_CALLTYPE_MEMBER    1       /* called for a member resource */
-#define DAV_CALLTYPE_COLLECTION        2       /* called for a collection */
-#define DAV_CALLTYPE_LOCKNULL  3       /* called for a locknull resource */
-#define DAV_CALLTYPE_POSTFIX   4       /* postfix call for a collection */
+    /* callback function and a client context for the walk */
+    dav_error * (*func)(dav_walk_resource *wres, int calltype);
+    void *walk_ctx;
 
+    /* what pool to use for allocations needed by walk logic */
     apr_pool_t *pool;
 
-    request_rec *r;                    /* original request */
-    dav_buffer uri;                    /* current URI */
-    const dav_resource *resource;      /* current resource */
-    const dav_resource *res2;          /* optional secondary resource */
+    /* beginning root of the walk */
+    const dav_resource *root;
 
-    const dav_resource *root;          /* RO: root resource of the walk */
+    /* secondary, tracking resource */
+    const dav_resource *root_dst;
 
+    /* lock database to enable walking LOCKNULL resources */
     dav_lockdb *lockdb;
 
-    dav_response *response;            /* OUT: multistatus responses */
+} dav_walk_params;
+
+/* directory tree walking context */
+typedef struct dav_walker_ctx
+{
+    /* input: */
+    dav_walk_params w;
+
+    /* output: */
+    dav_response *response;
+
+
+    /* ### private data... phasing out this big glom */
+
+    request_rec *r;                    /* original request */
 
     /* for PROPFIND operations */
     ap_xml_doc *doc;
@@ -1273,12 +1307,11 @@ typedef struct dav_walker_ctx
 
     int flags;
 
-    dav_walker_private *info;           /* for use by repository manager */
-
 } dav_walker_ctx;
 
-DAV_DECLARE(void) dav_add_response(dav_walker_ctx *ctx, const char *href, 
-                               int status, dav_get_props_result *propstats);
+DAV_DECLARE(void) dav_add_response(dav_walk_resource *wres,
+                                   int status,
+                                   dav_get_props_result *propstats);
 
 
 /* --------------------------------------------------------------------
index 4ea01abfc9897fe07a26e814d9148bbd99b24074..00c0a0e63e68dc5865c82e8259c4d46970f9b4ad 100644 (file)
@@ -1184,12 +1184,13 @@ static dav_error * dav_validate_resource_state(apr_pool_t *p,
 }
 
 /* dav_validate_walker:  Walker callback function to validate resource state */
-static dav_error * dav_validate_walker(dav_walker_ctx *ctx, int calltype)
+static dav_error * dav_validate_walker(dav_walk_resource *wres, int calltype)
 {
+    dav_walker_ctx *ctx = wres->walk_ctx;
     dav_error *err;
 
-    if ((err = dav_validate_resource_state(ctx->pool, ctx->resource,
-                                          ctx->lockdb,
+    if ((err = dav_validate_resource_state(ctx->w.pool, wres->resource,
+                                          ctx->w.lockdb,
                                           ctx->if_header, ctx->flags,
                                           &ctx->work_buf, ctx->r)) == NULL) {
        /* There was no error, so just bug out. */
@@ -1201,14 +1202,14 @@ static dav_error * dav_validate_walker(dav_walker_ctx *ctx, int calltype)
     ** then just return error (not a multistatus).
     */
     if (ap_is_HTTP_SERVER_ERROR(err->status)
-        || (*ctx->resource->hooks->is_same_resource)(ctx->resource,
-                                                     ctx->root)) {
+        || (*wres->resource->hooks->is_same_resource)(wres->resource,
+                                                      ctx->w.root)) {
        /* ### maybe push a higher-level description? */
        return err;
     }
 
     /* associate the error with the current URI */
-    dav_add_response(ctx, ctx->uri.buf, err->status, NULL);
+    dav_add_response(wres, err->status, NULL);
 
     return NULL;
 }
@@ -1312,24 +1313,23 @@ dav_error * dav_validate_request(request_rec *r, dav_resource *resource,
 
     /* (1) Validate the specified resource, at the specified depth */
     if (resource->exists && depth > 0) {
-       dav_walker_ctx ctx = { 0 };
+        dav_walker_ctx ctx = { { 0 } };
+
+       ctx.w.walk_type = DAV_WALKTYPE_NORMAL;
+       ctx.w.func = dav_validate_walker;
+        ctx.w.walk_ctx = &ctx;
+       ctx.w.pool = r->pool;
+        ctx.w.root = resource;
 
-       ctx.walk_type = DAV_WALKTYPE_ALL;
-       ctx.postfix = 0;
-       ctx.func = dav_validate_walker;
-       ctx.pool = r->pool;
        ctx.if_header = if_header;
        ctx.r = r;
         ctx.flags = flags;
-        ctx.resource = resource;
 
        if (lockdb != NULL) {
-           ctx.lockdb = lockdb;
-           ctx.walk_type |= DAV_WALKTYPE_LOCKNULL;
+           ctx.w.lockdb = lockdb;
+           ctx.w.walk_type |= DAV_WALKTYPE_LOCKNULL;
        }
 
-       dav_buffer_init(r->pool, &ctx.uri, resource->uri);
-
        err = (*repos_hooks->walk)(&ctx, DAV_INFINITY);
        if (err == NULL) {
             *response = ctx.response;
index bdc1ab66c19c62328e4557b667af5a8f0352b7eb..71c2ddf8ed211fdbb0828b7441d7ed4564e866a6 100644 (file)
@@ -282,24 +282,26 @@ dav_error * dav_lock_parse_lockinfo(request_rec *r,
 */
 
 /* dav_lock_walker:  Walker callback function to record indirect locks */
-static dav_error * dav_lock_walker(dav_walker_ctx *ctx, int calltype)
+static dav_error * dav_lock_walker(dav_walk_resource *wres, int calltype)
 {
+    dav_walker_ctx *ctx = wres->walk_ctx;
     dav_error *err;
 
     /* We don't want to set indirects on the target */
-    if ((*ctx->resource->hooks->is_same_resource)(ctx->resource, ctx->root))
+    if ((*wres->resource->hooks->is_same_resource)(wres->resource,
+                                                   ctx->w.root))
        return NULL;
 
-    if ((err = (*ctx->lockdb->hooks->append_locks)(ctx->lockdb, ctx->resource,
-                                                  1,
-                                                  ctx->lock)) != NULL) {
+    if ((err = (*ctx->w.lockdb->hooks->append_locks)(ctx->w.lockdb,
+                                                     wres->resource, 1,
+                                                     ctx->lock)) != NULL) {
        if (ap_is_HTTP_SERVER_ERROR(err->status)) {
            /* ### add a higher-level description? */
            return err;
        }
 
        /* add to the multistatus response */
-       dav_add_response(ctx, ctx->resource->uri, err->status, NULL);
+       dav_add_response(wres, err->status, NULL);
 
        /*
        ** ### actually, this is probably wrong: we want to fail the whole
@@ -353,19 +355,18 @@ dav_error * dav_add_lock(request_rec *r, const dav_resource *resource,
 
     if (depth > 0) {
        /* Walk existing collection and set indirect locks */
-       dav_walker_ctx ctx = { 0 };
+        dav_walker_ctx ctx = { { 0 } };
+
+       ctx.w.walk_type = DAV_WALKTYPE_ALL | DAV_WALKTYPE_AUTH;
+       ctx.w.func = dav_lock_walker;
+        ctx.w.walk_ctx = &ctx;
+       ctx.w.pool = r->pool;
+        ctx.w.root = resource;
+       ctx.w.lockdb = lockdb;
 
-       ctx.walk_type = DAV_WALKTYPE_ALL | DAV_WALKTYPE_AUTH;
-       ctx.postfix = 0;
-       ctx.func = dav_lock_walker;
-       ctx.pool = r->pool;
        ctx.r = r;
-        ctx.resource = resource;
-       ctx.lockdb = lockdb;
        ctx.lock = lock;
 
-       dav_buffer_init(r->pool, &ctx.uri, resource->uri);
-
        err = (*resource->hooks->walk)(&ctx, DAV_INFINITY);
        if (err != NULL) {
            /* implies a 5xx status code occurred. screw the multistatus */
@@ -405,12 +406,14 @@ DAV_DECLARE(dav_error*) dav_lock_query(dav_lockdb *lockdb,
 }
 
 /* dav_unlock_walker:  Walker callback function to remove indirect locks */
-static dav_error * dav_unlock_walker(dav_walker_ctx *ctx, int calltype)
+static dav_error * dav_unlock_walker(dav_walk_resource *wres, int calltype)
 {
+    dav_walker_ctx *ctx = wres->walk_ctx;
     dav_error *err;
 
-    if ((err = (*ctx->lockdb->hooks->remove_lock)(ctx->lockdb, ctx->resource,
-                                                 ctx->locktoken)) != NULL) {
+    if ((err = (*ctx->w.lockdb->hooks->remove_lock)(ctx->w.lockdb,
+                                                    wres->resource,
+                                                    ctx->locktoken)) != NULL) {
        /* ### should we stop or return a multistatus? looks like STOP */
        /* ### add a higher-level description? */
        return err;
@@ -552,19 +555,18 @@ int dav_unlock(request_rec *r, const dav_resource *resource,
     }
 
     if (lock_resource->collection) {
-       dav_walker_ctx ctx = { 0 };
+        dav_walker_ctx ctx = { { 0 } };
+
+       ctx.w.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_LOCKNULL;
+       ctx.w.func = dav_unlock_walker;
+        ctx.w.walk_ctx = &ctx;
+       ctx.w.pool = r->pool;
+        ctx.w.root = lock_resource;
+       ctx.w.lockdb = lockdb;
 
-       ctx.walk_type = DAV_WALKTYPE_ALL | DAV_WALKTYPE_LOCKNULL;
-       ctx.postfix = 0;
-       ctx.func = dav_unlock_walker;
-       ctx.pool = r->pool;
-        ctx.resource = lock_resource;
        ctx.r = r;
-       ctx.lockdb = lockdb;
        ctx.locktoken = locktoken;
 
-       dav_buffer_init(r->pool, &ctx.uri, lock_resource->uri);
-
        err = (*repos_hooks->walk)(&ctx, DAV_INFINITY);
 
        /* ### fix this! */
@@ -579,17 +581,20 @@ int dav_unlock(request_rec *r, const dav_resource *resource,
 }
 
 /* dav_inherit_walker:  Walker callback function to inherit locks */
-static dav_error * dav_inherit_walker(dav_walker_ctx *ctx, int calltype)
+static dav_error * dav_inherit_walker(dav_walk_resource *wres, int calltype)
 {
+    dav_walker_ctx *ctx = wres->walk_ctx;
+
     if (ctx->skip_root
-       && (*ctx->resource->hooks->is_same_resource)(ctx->resource,
-                                                    ctx->root)) {
+       && (*wres->resource->hooks->is_same_resource)(wres->resource,
+                                                      ctx->w.root)) {
        return NULL;
     }
 
     /* ### maybe add a higher-level desc */
-    return (*ctx->lockdb->hooks->append_locks)(ctx->lockdb, ctx->resource, 1,
-                                              ctx->lock);
+    return (*ctx->w.lockdb->hooks->append_locks)(ctx->w.lockdb,
+                                                 wres->resource, 1,
+                                                 ctx->lock);
 }
 
 /*
@@ -607,7 +612,7 @@ static dav_error * dav_inherit_locks(request_rec *r, dav_lockdb *lockdb,
     dav_lock *locks;
     dav_lock *scan;
     dav_lock *prev;
-    dav_walker_ctx ctx = { 0 };
+    dav_walker_ctx ctx = { { 0 } };
     const dav_hooks_repository *repos_hooks = resource->hooks;
 
     if (use_parent) {
@@ -661,18 +666,17 @@ static dav_error * dav_inherit_locks(request_rec *r, dav_lockdb *lockdb,
 
     /* <locks> has all our new locks.  Walk down and propagate them. */
 
-    ctx.walk_type = DAV_WALKTYPE_ALL | DAV_WALKTYPE_LOCKNULL;
-    ctx.postfix = 0;
-    ctx.func = dav_inherit_walker;
-    ctx.pool = r->pool;
-    ctx.resource = resource;
+    ctx.w.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_LOCKNULL;
+    ctx.w.func = dav_inherit_walker;
+    ctx.w.walk_ctx = &ctx;
+    ctx.w.pool = r->pool;
+    ctx.w.root = resource;
+    ctx.w.lockdb = lockdb;
+
     ctx.r = r;
-    ctx.lockdb = lockdb;
     ctx.lock = locks;
     ctx.skip_root = !use_parent;
 
-    dav_buffer_init(r->pool, &ctx.uri, resource->uri);
-
     return (*repos_hooks->walk)(&ctx, DAV_INFINITY);
 }