Commit 6e30963b authored by Greg Stein's avatar Greg Stein
Browse files

Fix up the auto-versioning stuff. The new scheme more closely matches the

intent of DeltaV draft 14, simplifying some previous assumptions.

Includes some heavy fixes to MOVE/COPY in a versioning world.

Fix to CHECKOUT when a working resource is not created (checkout in place)

Submitted by: John Vasta <jvasta@rational.com>


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@88856 13f79535-47bb-0310-9956-ffa450edef68
parent 0f069a3b
Loading
Loading
Loading
Loading
+133 −78
Original line number Diff line number Diff line
@@ -1001,7 +1001,7 @@ static int dav_method_put(request_rec *r)
    }

    /* make sure the resource can be modified (if versioning repository) */
    if ((err = dav_ensure_resource_writable(r, resource,
    if ((err = dav_auto_checkout(r, resource,
				 0 /* not parent_only */,
				 &av_info)) != NULL) {
	/* ### add a higher-level description? */
@@ -1086,8 +1086,8 @@ static int dav_method_put(request_rec *r)
    }

    /* restore modifiability of resources back to what they were */
    err2 = dav_revert_resource_writability(r, resource, err != NULL /* undo if error */,
                                           &av_info);
    err2 = dav_auto_checkin(r, resource, err != NULL /* undo if error */,
                            0 /*unlock*/, &av_info);

    /* check for errors now */
    if (err != NULL) {
@@ -1097,7 +1097,7 @@ static int dav_method_put(request_rec *r)
	/* just log a warning */
	err2 = dav_push_error(r->pool, err->status, 0,
			      "The PUT was successful, but there "
			      "was a problem reverting the writability of "
			      "was a problem automatically checking in "
			      "the resource or its parent collection.",
			      err2);
	dav_log_err(r, err2, APLOG_WARNING);
@@ -1232,7 +1232,7 @@ static int dav_method_delete(request_rec *r)
    }

    /* if versioned resource, make sure parent is checked out */
    if ((err = dav_ensure_resource_writable(r, resource, 1 /* parent_only */,
    if ((err = dav_auto_checkout(r, resource, 1 /* parent_only */,
				 &av_info)) != NULL) {
	/* ### add a higher-level description? */
	return dav_handle_err(r, err, NULL);
@@ -1242,8 +1242,8 @@ static int dav_method_delete(request_rec *r)
    err = (*resource->hooks->remove_resource)(resource, &multi_response);

    /* restore writability of parent back to what it was */
    err2 = dav_revert_resource_writability(r, NULL, err != NULL /* undo if error */,
					   &av_info);
    err2 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
			    0 /*unlock*/, &av_info);

    /* check for errors now */
    if (err != NULL) {
@@ -1258,8 +1258,8 @@ static int dav_method_delete(request_rec *r)
	/* just log a warning */
	err = dav_push_error(r->pool, err2->status, 0,
			     "The DELETE was successful, but there "
			     "was a problem reverting the writability of "
			     "its parent collection.",
			     "was a problem automatically checking in "
			     "the parent collection.",
			     err2);
	dav_log_err(r, err, APLOG_WARNING);
    }
@@ -2146,6 +2146,7 @@ static int dav_method_proppatch(request_rec *r)
    ap_text *propstat_text;
    apr_array_header_t *ctx_list;
    dav_prop_ctx *ctx;
    dav_auto_version_info av_info;

    /* Ask repository module to resolve the resource */
    err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
@@ -2178,8 +2179,19 @@ static int dav_method_proppatch(request_rec *r)
	return dav_handle_err(r, err, NULL);
    }

    /* make sure the resource can be modified (if versioning repository) */
    if ((err = dav_auto_checkout(r, resource,
				 0 /* not parent_only */,
				 &av_info)) != NULL) {
	/* ### add a higher-level description? */
	return dav_handle_err(r, err, NULL);
    }

    if ((err = dav_open_propdb(r, NULL, resource, 0, doc->namespaces,
			       &propdb)) != NULL) {
        /* undo any auto-checkout */
        dav_auto_checkin(r, resource, 1 /*undo*/, 0 /*unlock*/, &av_info);

	err = dav_push_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
			     apr_psprintf(r->pool,
					 "Could not open the property "
@@ -2212,6 +2224,9 @@ static int dav_method_proppatch(request_rec *r)
	if ((prop_group = dav_find_child(child, "prop")) == NULL) {
	    dav_close_propdb(propdb);

            /* undo any auto-checkout */
            dav_auto_checkin(r, resource, 1 /*undo*/, 0 /*unlock*/, &av_info);

	    /* This supplies additional information for the default message. */
	    ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
			  "A \"prop\" element is missing inside "
@@ -2257,6 +2272,9 @@ static int dav_method_proppatch(request_rec *r)
    /* make sure this gets closed! */
    dav_close_propdb(propdb);

    /* complete any auto-versioning */
    dav_auto_checkin(r, resource, failure, 0 /*unlock*/, &av_info);

    /* log any errors that occurred */
    (void)dav_process_ctx_list(dav_prop_log_errors, ctx_list, 0, 0);

@@ -2384,7 +2402,7 @@ static int dav_method_mkcol(request_rec *r)
    }

    /* if versioned resource, make sure parent is checked out */
    if ((err = dav_ensure_resource_writable(r, resource, 1 /* parent_only */,
    if ((err = dav_auto_checkout(r, resource, 1 /* parent_only */,
				 &av_info)) != NULL) {
	/* ### add a higher-level description? */
	return dav_handle_err(r, err, NULL);
@@ -2395,8 +2413,8 @@ static int dav_method_mkcol(request_rec *r)
    err = (*resource->hooks->create_collection)(resource);

    /* restore modifiability of parent back to what it was */
    err2 = dav_revert_resource_writability(r, NULL, err != NULL /* undo if error */,
					   &av_info);
    err2 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
			    0 /*unlock*/, &av_info);

    /* check for errors now */
    if (err != NULL) {
@@ -2406,8 +2424,8 @@ static int dav_method_mkcol(request_rec *r)
	/* just log a warning */
	err = dav_push_error(r->pool, err->status, 0,
			     "The MKCOL was successful, but there "
			     "was a problem reverting the writability of "
			     "its parent collection.",
			     "was a problem automatically checking in "
			     "the parent collection.",
			     err2);
	dav_log_err(r, err, APLOG_WARNING);
    }
@@ -2450,9 +2468,9 @@ static int dav_method_mkcol(request_rec *r)
static int dav_method_copymove(request_rec *r, int is_move)
{
    dav_resource *resource;
    dav_auto_version_info src_av_info = { 0 };
    dav_resource *resnew;
    dav_auto_version_info dst_av_info;
    dav_auto_version_info src_av_info = { 0 };
    dav_auto_version_info dst_av_info = { 0 };
    const char *body;
    const char *dest;
    dav_error *err;
@@ -2465,8 +2483,8 @@ static int dav_method_copymove(request_rec *r, int is_move)
    int depth;
    int result;
    dav_lockdb *lockdb;
    int replaced;
    int resource_state;
    int replace_dest;
    int resnew_state;

    /* Ask repository module to resolve the resource */
    err = dav_get_resource(r, !is_move /* label_allowed */,
@@ -2479,6 +2497,7 @@ static int dav_method_copymove(request_rec *r, int is_move)
    }

    /* If not a file or collection resource, COPY/MOVE not allowed */
    /* ### allow COPY/MOVE of DeltaV resource types */
    if (resource->type != DAV_RESOURCE_TYPE_REGULAR) {
        body = apr_psprintf(r->pool,
                           "Cannot COPY/MOVE resource %s.",
@@ -2686,12 +2705,9 @@ static int dav_method_copymove(request_rec *r, int is_move)
	(void)dav_unlock(r, resource, NULL);
    }

    /* remember whether target resource existed */
    replaced = resnew->exists;

    /* if this is a move, then the source parent collection will be modified */
    if (is_move) {
        if ((err = dav_ensure_resource_writable(r, resource, 1 /* parent_only */,
        if ((err = dav_auto_checkout(r, resource, 1 /* parent_only */,
				     &src_av_info)) != NULL) {
	    if (lockdb != NULL)
		(*lockdb->hooks->close_lockdb)(lockdb);
@@ -2701,15 +2717,49 @@ static int dav_method_copymove(request_rec *r, int is_move)
        }
    }

    /* prepare the destination collection for modification */
    if ((err = dav_ensure_resource_writable(r, resnew, 1 /* parent_only */,
    /*
     * Remember the initial state of the destination, so the lock system
     * can be notified as to how it changed.
     */
    resnew_state = dav_get_resource_state(lookup.rnew, resnew);

    /* If destination does not exist, initialize resource object
     * to be same type as the source.
     */
    if (!resnew->exists) {
        resnew->type = resource->type;
        resnew->collection = resource->collection;
    }

    /* In a MOVE operation, the destination is replaced by the source.
     * In a COPY operation, if the destination exists, is under version
     * control, and is the same resource type as the source,
     * then it should not be replaced, but modified to be a copy of
     * the source.
     */
    if (!resnew->exists)
        replace_dest = 0;
    else if (is_move || !resource->versioned)
        replace_dest = 1;
    else if (resource->type != resnew->type)
        replace_dest = 1;
    else if ((resource->collection == 0) != (resnew->collection == 0))
        replace_dest = 1;
    else
        replace_dest = 0;

    /* If the destination must be created or replaced,
     * make sure the parent collection is writable
     */
    if (!resnew->exists || replace_dest) {
        if ((err = dav_auto_checkout(r, resnew, 1 /*parent_only*/,
				     &dst_av_info)) != NULL) {
            /* could not make destination writable:
	     * if move, restore state of source parent
	     */
            if (is_move) {
            (void) dav_revert_resource_writability(r, NULL, 1 /* undo */,
						   &src_av_info);
                (void) dav_auto_checkin(r, NULL, 1 /* undo */,
				        0 /*unlock*/, &src_av_info);
            }

	    if (lockdb != NULL)
@@ -2718,27 +2768,25 @@ static int dav_method_copymove(request_rec *r, int is_move)
	    /* ### add a higher-level description? */
	    return dav_handle_err(r, err, NULL);
        }
    }

    /* If source and destination parents are the same, then
     * use the same object, so status updates to one are reflected
     * in the other, when reverting their writable states.
     * use the same resource object, so status updates to one are reflected
     * in the other, when doing auto-versioning. Otherwise,
     * we may try to checkin the parent twice.
     */
    if (src_av_info.parent_resource != NULL
        && dst_av_info.parent_resource != NULL
        && (*src_av_info.parent_resource->hooks->is_same_resource)
            (src_av_info.parent_resource, dst_av_info.parent_resource)) {

        dst_av_info.parent_resource = src_av_info.parent_resource;
    }

    /* New resource will be same kind as source */
    resnew->collection = resource->collection;

    resource_state = dav_get_resource_state(lookup.rnew, resnew);

    /* If target exists, remove it first (we know Ovewrite must be TRUE).
     * Then try to copy/move the resource.
    /* If destination is being replaced, remove it first
     * (we know Ovewrite must be TRUE). Then try to copy/move the resource.
     */
    if (resnew->exists)
    if (replace_dest)
	err = (*resnew->hooks->remove_resource)(resnew, &multi_response);

    if (err == NULL) {
@@ -2750,13 +2798,13 @@ static int dav_method_copymove(request_rec *r, int is_move)
                                                    &multi_response);
    }

    /* restore parent collection states */
    err2 = dav_revert_resource_writability(r, NULL, err != NULL /* undo if error */,
					   &dst_av_info);
    /* perform any auto-versioning cleanup */
    err2 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
			    0 /*unlock*/, &dst_av_info);

    if (is_move) {
        err3 = dav_revert_resource_writability(r, NULL, err != NULL /* undo if error */,
					       &src_av_info);
        err3 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
				0 /*unlock*/, &src_av_info);
    }
    else
	err3 = NULL;
@@ -2774,12 +2822,12 @@ static int dav_method_copymove(request_rec *r, int is_move)
	return dav_handle_err(r, err, multi_response);
    }

    /* check for errors from reverting writability */
    /* check for errors from auto-versioning */
    if (err2 != NULL) {
	/* just log a warning */
	err = dav_push_error(r->pool, err2->status, 0,
			     "The MOVE/COPY was successful, but there was a "
			     "problem reverting the writability of the "
			     "problem automatically checking in the "
			     "source parent collection.",
			     err2);
	dav_log_err(r, err, APLOG_WARNING);
@@ -2788,8 +2836,8 @@ static int dav_method_copymove(request_rec *r, int is_move)
	/* just log a warning */
	err = dav_push_error(r->pool, err3->status, 0,
			     "The MOVE/COPY was successful, but there was a "
			     "problem reverting the writability of the "
			     "destination parent collection.",
			     "problem automatically checking in the "
			     "destination or its parent collection.",
			     err3);
	dav_log_err(r, err, APLOG_WARNING);
    }
@@ -2798,7 +2846,7 @@ static int dav_method_copymove(request_rec *r, int is_move)
    if (lockdb != NULL) {

	/* notify lock system that we have created/replaced a resource */
	err = dav_notify_created(r, lockdb, resnew, resource_state, depth);
	err = dav_notify_created(r, lockdb, resnew, resnew_state, depth);

	(*lockdb->hooks->close_lockdb)(lockdb);

@@ -2814,7 +2862,8 @@ static int dav_method_copymove(request_rec *r, int is_move)
    }

    /* return an appropriate response (HTTP_CREATED or HTTP_NO_CONTENT) */
    return dav_created(r, lookup.rnew->uri, "Destination", replaced);
    return dav_created(r, lookup.rnew->uri, "Destination",
                       resnew_state == DAV_RESOURCE_EXISTS);
}

/* dav_method_lock:  Handler to implement the DAV LOCK method
@@ -3193,14 +3242,14 @@ static int dav_method_vsn_control(request_rec *r)
    }

    /* if in versioned collection, make sure parent is checked out */
    if ((err = dav_ensure_resource_writable(r, resource, 1 /* parent_only */,
    if ((err = dav_auto_checkout(r, resource, 1 /* parent_only */,
				 &av_info)) != NULL) {
	return dav_handle_err(r, err, NULL);
    }

    /* attempt to version-control the resource */
    if ((err = (*vsn_hooks->vsn_control)(resource, target)) != NULL) {
        dav_revert_resource_writability(r, resource, 1 /*undo*/, &av_info);
        dav_auto_checkin(r, resource, 1 /*undo*/, 0 /*unlock*/, &av_info);
	err = dav_push_error(r->pool, HTTP_CONFLICT, 0,
			     apr_psprintf(r->pool,
					 "Could not VERSION-CONTROL resource %s.",
@@ -3210,12 +3259,12 @@ static int dav_method_vsn_control(request_rec *r)
    }

    /* revert writability of parent directory */
    err = dav_revert_resource_writability(r, resource, 0 /*undo*/, &av_info);
    err = dav_auto_checkin(r, resource, 0 /*undo*/, 0 /*unlock*/, &av_info);
    if (err != NULL) {
        /* just log a warning */
	err = dav_push_error(r->pool, err->status, 0,
			     "The VERSION-CONTROL was successful, but there "
			     "was a problem reverting the writability of "
			     "was a problem automatically checking in "
			     "the parent collection.",
			     err);
        dav_log_err(r, err, APLOG_WARNING);
@@ -3375,7 +3424,8 @@ static int dav_method_checkout(request_rec *r)
    /* ### do lock checks, once behavior is defined */

    /* Do the checkout */
    if ((err = (*vsn_hooks->checkout)(resource, is_unreserved, is_fork_ok,
    if ((err = (*vsn_hooks->checkout)(resource, 0 /*auto_checkout*/,
                                      is_unreserved, is_fork_ok,
                                      create_activity, activities,
                                      &working_resource)) != NULL) {
	err = dav_push_error(r->pool, HTTP_CONFLICT, 0,
@@ -3389,9 +3439,14 @@ static int dav_method_checkout(request_rec *r)
    /* set the Cache-Control header, per the spec */
    apr_table_setn(r->headers_out, "Cache-Control", "no-cache");

    /* use appropriate URI for Location header */
    if (working_resource == NULL)
        working_resource = resource;
    /* if no working resource created, return OK,
     * else return CREATED with working resource URL in Location header
     */
    if (working_resource == NULL) {
        /* no body */
        ap_set_content_length(r, 0);
        return DONE;
    }

    return dav_created(r, working_resource->uri, "Checked-out resource", 0);
}
@@ -3894,7 +3949,7 @@ static int dav_method_report(request_rec *r)
     * First determine whether a Target-Selector header is allowed
     * for this report.
     */
    label_allowed = (*vsn_hooks->report_target_selector_allowed)(doc);
    label_allowed = (*vsn_hooks->report_label_header_allowed)(doc);
    err = dav_get_resource(r, label_allowed, 0 /* use_checked_in */,
                           &resource);
    if (err != NULL)
@@ -4331,7 +4386,7 @@ static int dav_method_bind(request_rec *r)
    }

    /* prepare the destination collection for modification */
    if ((err = dav_ensure_resource_writable(r, binding, 1 /* parent_only */,
    if ((err = dav_auto_checkout(r, binding, 1 /* parent_only */,
				 &av_info)) != NULL) {
        /* could not make destination writable */
	return dav_handle_err(r, err, NULL);
@@ -4348,9 +4403,9 @@ static int dav_method_bind(request_rec *r)
    }

    /* restore parent collection states */
    err2 = dav_revert_resource_writability(r, NULL,
    err2 = dav_auto_checkin(r, NULL,
			    err != NULL /* undo if error */,
					   &av_info);
			    0 /*unlock*/, &av_info);

    /* check for error from remove/bind operations */
    if (err != NULL) {
@@ -4367,7 +4422,7 @@ static int dav_method_bind(request_rec *r)
	/* just log a warning */
	err = dav_push_error(r->pool, err2->status, 0,
			     "The BIND was successful, but there was a "
			     "problem reverting the writability of the "
			     "problem automatically checking in the "
			     "source parent collection.",
			     err2);
	dav_log_err(r, err, APLOG_WARNING);
+83 −29
Original line number Diff line number Diff line
@@ -1737,8 +1737,12 @@ struct dav_hooks_repository
        dav_resource *resource
    );

    /* Copy one resource to another. The destination must not exist.
    /* Copy one resource to another. The destination may exist, if it is
     * versioned.
     * Handles both files and collections. Properties are copied as well.
     * If the destination exists and is versioned, the provider must update
     * the destination to have identical content to the source,
     * recursively for collections.
     * The depth argument is ignored for a file, and can be either 0 or
     * DAV_INFINITY for a collection.
     * If an error occurs in a child resource, then the return value is
@@ -1813,15 +1817,42 @@ void dav_add_vary_header(request_rec *in_req,
			 request_rec *out_req,
			 const dav_resource *resource);

/*
** Flags specifying auto-versioning behavior, returned by
** the auto_versionable hook. The value returned depends
** on both the state of the resource and the value of the
** DAV:auto-versioning property for the resource.
**
** If the resource does not exist (null or lock-null),
** DAV_AUTO_VERSION_ALWAYS causes creation of a new version-controlled resource
**
** If the resource is checked in,
** DAV_AUTO_VERSION_ALWAYS causes it to be checked out always,
** DAV_AUTO_VERSION_LOCKED causes it to be checked out only when locked
**
** If the resource is checked out,
** DAV_AUTO_VERSION_ALWAYS causes it to be checked in always,
** DAV_AUTO_VERSION_LOCKED causes it to be checked in when unlocked
** (note: a provider should allow auto-checkin only for resources which
** were automatically checked out)
**
** In all cases, DAV_AUTO_VERSION_NEVER results in no auto-versioning behavior.
*/
typedef enum {
    DAV_AUTO_VERSION_NEVER,
    DAV_AUTO_VERSION_ALWAYS,
    DAV_AUTO_VERSION_LOCKED
} dav_auto_version;

/*
** This structure is used to record what auto-versioning operations
** were done to make a resource writable, so that they can be undone
** at the end of a request.
*/
typedef struct {
    int resource_created;               /* 0 => resource existed previously */
    int resource_checkedout;            /* 0 => resource was checked out */
    int parent_checkedout;              /* 0 => parent was checked out */
    int resource_versioned;             /* 1 => resource was auto-version-controlled */
    int resource_checkedout;            /* 1 => resource was auto-checked-out */
    int parent_checkedout;              /* 1 => parent was auto-checked-out */
    dav_resource *parent_resource;      /* parent resource, if it was needed */
} dav_auto_version_info;

@@ -1836,11 +1867,15 @@ typedef struct {
 * child does not exist, then a new versioned resource is created and
 * checked out.
 *
 * If auto-versioning is not enabled for a versioned resource, then an error is
 * returned, since the resource cannot be modified.
 *
 * The dav_auto_version_info structure is filled in with enough information
 * to restore both parent and child resources to the state they were in
 * before the auto-versioning operations occurred.
 */
dav_error *dav_ensure_resource_writable(request_rec *r,
dav_error *dav_auto_checkout(
    request_rec *r,
    dav_resource *resource,
    int parent_only,
    dav_auto_version_info *av_info);
@@ -1851,15 +1886,21 @@ dav_error *dav_ensure_resource_writable(request_rec *r,
 * If undo != 0, then resource modifications are discarded
 * (i.e. they are unchecked out).
 *
 * Set the unlock flag to indicate that the resource is about
 * to be unlocked; it will be checked in if the resource
 * auto-versioning property indicates it should be. In this case,
 * av_info is ignored, so it can be NULL.
 *
 * The resource argument may be NULL if only the parent resource
 * was made writable (i.e. the parent_only was != 0 in the
 * dav_ensure_resource_writable call).
 * was checked out (i.e. the parent_only was != 0 in the
 * dav_auto_checkout call).
 */
dav_error *dav_revert_resource_writability(
dav_error *dav_auto_checkin(
    request_rec *r,
    dav_resource *resource,
    int undo,
    const dav_auto_version_info *av_info);
    int unlock,
    dav_auto_version_info *av_info);

/*
** This structure is used to describe available reports
@@ -1899,18 +1940,34 @@ struct dav_hooks_vsn
                              const ap_xml_elem *elem,
                              ap_text_header *option);

    /* Determine whether a non-versioned (or non-existent) resource
     * is versionable. Returns != 0 if resource can be versioned.
     */
    int (*versionable)(const dav_resource *resource);

    /* Determine whether auto-versioning is enabled for a resource
     * (which may not exist, or may not be versioned). If the resource
     * is a checked-out resource, the provider must only enable
     * auto-checkin if the resource was automatically checked out.
     *
     * The value returned depends on both the state of the resource
     * and the value of its DAV:auto-version property. See the description
     * of the dav_auto_version enumeration above for the details.
     */
    dav_auto_version (*auto_versionable)(const dav_resource *resource);

    /* Put a resource under version control. If the resource already
     * exists unversioned, then it becomes the initial version of the
     * new version history, and it is replaced by a version selector
     * which targets the new version.
     *
     * If the resource does not exist, then a new version selector
     * is created which either targets an existing version (if the
     * If the resource does not exist, then a new version-controlled
     * resource is created which either targets an existing version (if the
     * "target" argument is not NULL), or the initial, empty version
     * in a new history resource (if the "target" argument is NULL).
     *
     * If successful, the resource object state is updated appropriately
     * (that is, changed to refer to the new version selector resource).
     * (that is, changed to refer to the new version-controlled resource).
     */
    dav_error * (*vsn_control)(dav_resource *resource,
                               const char *target);
@@ -1918,6 +1975,13 @@ struct dav_hooks_vsn
    /* Checkout a resource. If successful, the resource
     * object state is updated appropriately.
     *
     * The auto_checkout flag will be set if this checkout is being
     * done automatically, as part of some method which modifies
     * the resource. The provider must remember that the resource
     * was automatically checked out, so it can determine whether it
     * can be automatically checked in. (Auto-checkin should only be
     * enabled for resources which were automatically checked out.)
     *
     * If the working resource has a different URL from the
     * target resource, a dav_resource descriptor is returned
     * for the new working resource. Otherwise, the original
@@ -1934,6 +1998,7 @@ struct dav_hooks_vsn
     * no DAV:activity-set was provided or when create_activity is set.
     */
    dav_error * (*checkout)(dav_resource *resource,
                            int auto_checkout,
                            int is_unreserved, int is_fork_ok,
                            int create_activity,
                            apr_array_header_t *activities,
@@ -1959,17 +2024,6 @@ struct dav_hooks_vsn
                           int keep_checked_out,
                           dav_resource **version_resource);

    /* Determine whether a non-versioned (or non-existent) resource
     * is versionable. Returns != 0 if resource can be versioned.
     */
    int (*versionable)(const dav_resource *resource);

    /* Determine whether auto-versioning is enabled for a resource
     * (which may not exist, or may not be versioned).
     * Returns != 0 if auto-versioning is enabled.
     */
    int (*auto_version_enabled)(const dav_resource *resource);

    /*
    ** Return the set of reports available at this resource.
    **
@@ -1982,12 +2036,12 @@ struct dav_hooks_vsn
                                 const dav_report_elem **reports);

    /*
    ** Determine whether a Target-Selector header can be used
    ** Determine whether a Label header can be used
    ** with a particular report. The dav_xml_doc structure
    ** contains the parsed report request body.
    ** Returns 0 if Target-Selector is not allowed.
    ** Returns 0 if the Label header is not allowed.
    */
    int (*report_target_selector_allowed)(const ap_xml_doc *doc);
    int (*report_label_header_allowed)(const ap_xml_doc *doc);

    /*
    ** Generate a report on a resource. Since a provider is free
+241 −111

File changed.

Preview size limit exceeded, changes collapsed.

+24 −26
Original line number Diff line number Diff line
@@ -417,6 +417,16 @@ static dav_error * dav_unlock_walker(dav_walk_resource *wres, int calltype)
    dav_walker_ctx *ctx = wres->walk_ctx;
    dav_error *err;

    /* Before removing the lock, do any auto-checkin required */
    if (wres->resource->working) {
        /* ### get rid of this typecast */
        if ((err = dav_auto_checkin(ctx->r, (dav_resource *) wres->resource,
                                    0 /*undo*/, 1 /*unlock*/, NULL))
            != NULL) {
            return err;
        }
    }

    if ((err = (*ctx->w.lockdb->hooks->remove_lock)(ctx->w.lockdb,
                                                    wres->resource,
                                                    ctx->locktoken)) != NULL) {
@@ -521,6 +531,8 @@ int dav_unlock(request_rec *r, const dav_resource *resource,
    const dav_resource *lock_resource = resource;
    const dav_hooks_locks *hooks = DAV_GET_HOOKS_LOCKS(r);
    const dav_hooks_repository *repos_hooks = resource->hooks;
    dav_walker_ctx ctx = { { 0 } };
    dav_response *multi_status;
    dav_error *err;

    /* If no locks provider, then there is nothing to unlock. */
@@ -558,17 +570,6 @@ int dav_unlock(request_rec *r, const dav_resource *resource,
    /* At this point, lock_resource/locktoken refers to a direct lock (key), ie
     * the root of a depth > 0 lock, or locktoken is null.
     */
    if ((err = (*hooks->remove_lock)(lockdb, lock_resource,
				     locktoken)) != NULL) {
	/* ### add a higher-level desc? */
	/* ### return err! */
	return HTTP_INTERNAL_SERVER_ERROR;
    }

    if (lock_resource->collection) {
        dav_walker_ctx ctx = { { 0 } };
        dav_response *multi_status;

    ctx.w.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_LOCKNULL;
    ctx.w.func = dav_unlock_walker;
    ctx.w.walk_ctx = &ctx;
@@ -584,9 +585,6 @@ int dav_unlock(request_rec *r, const dav_resource *resource,
    /* ### fix this! */
    /* ### do something with multi_status */
    result = err == NULL ? OK : err->status;
    }
    else
	result = OK;

    (*hooks->close_lockdb)(lockdb);