diff options
Diffstat (limited to 'modules/dav')
-rw-r--r-- | modules/dav/fs/repos.c | 29 | ||||
-rw-r--r-- | modules/dav/main/mod_dav.c | 23 | ||||
-rw-r--r-- | modules/dav/main/mod_dav.h | 5 | ||||
-rw-r--r-- | modules/dav/main/util.c | 7 |
4 files changed, 41 insertions, 23 deletions
diff --git a/modules/dav/fs/repos.c b/modules/dav/fs/repos.c index 6c4c44b1..ae6f5c0e 100644 --- a/modules/dav/fs/repos.c +++ b/modules/dav/fs/repos.c @@ -717,13 +717,13 @@ static dav_error * dav_fs_get_resource( resource->pool = r->pool; /* make sure the URI does not have a trailing "/" */ - len = strlen(r->uri); - if (len > 1 && r->uri[len - 1] == '/') { - s = apr_pstrmemdup(r->pool, r->uri, len-1); + len = strlen(r->unparsed_uri); + if (len > 1 && r->unparsed_uri[len - 1] == '/') { + s = apr_pstrmemdup(r->pool, r->unparsed_uri, len-1); resource->uri = s; } else { - resource->uri = r->uri; + resource->uri = r->unparsed_uri; } if (r->finfo.filetype != APR_NOFILE) { @@ -1482,6 +1482,18 @@ static dav_error * dav_fs_remove_resource(dav_resource *resource, return dav_fs_deleteset(info->pool, resource); } +/* Take an unescaped path component and escape it and append it onto a + * dav_buffer for a URI */ +static apr_size_t dav_fs_append_uri(apr_pool_t *p, dav_buffer *pbuf, + const char *path, apr_size_t pad) +{ + const char *epath = ap_escape_uri(p, path); + apr_size_t epath_len = strlen(epath); + + dav_buffer_place_mem(p, pbuf, epath, epath_len + 1, pad); + return epath_len; +} + /* ### move this to dav_util? */ /* Walk recursively down through directories, * * including lock-null resources as we go. */ @@ -1537,6 +1549,7 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth) } while ((apr_dir_read(&dirent, APR_FINFO_DIRENT, dirp)) == APR_SUCCESS) { apr_size_t len; + apr_size_t escaped_len; len = strlen(dirent.name); @@ -1579,7 +1592,7 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth) /* copy the file to the URI, too. NOTE: we will pad an extra byte for the trailing slash later. */ - dav_buffer_place_mem(pool, &fsctx->uri_buf, dirent.name, len + 1, 1); + escaped_len = dav_fs_append_uri(pool, &fsctx->uri_buf, dirent.name, 1); /* if there is a secondary path, then do that, too */ if (fsctx->path2.buf != NULL) { @@ -1612,7 +1625,7 @@ 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 */ - fsctx->uri_buf.cur_len += len + 1; + fsctx->uri_buf.cur_len += escaped_len + 1; fsctx->uri_buf.buf[fsctx->uri_buf.cur_len - 1] = '/'; fsctx->uri_buf.buf[fsctx->uri_buf.cur_len] = '\0'; @@ -1678,8 +1691,8 @@ static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth) */ dav_buffer_place_mem(pool, &fsctx->path1, fsctx->locknull_buf.buf + offset, len + 1, 0); - dav_buffer_place_mem(pool, &fsctx->uri_buf, - fsctx->locknull_buf.buf + offset, len + 1, 0); + dav_fs_append_uri(pool, &fsctx->uri_buf, + fsctx->locknull_buf.buf + offset, 0); if (fsctx->path2.buf != NULL) { dav_buffer_place_mem(pool, &fsctx->path2, fsctx->locknull_buf.buf + offset, diff --git a/modules/dav/main/mod_dav.c b/modules/dav/main/mod_dav.c index 9135cd96..f3c2958b 100644 --- a/modules/dav/main/mod_dav.c +++ b/modules/dav/main/mod_dav.c @@ -396,11 +396,9 @@ static int dav_error_response_tag(request_rec *r, */ static const char *dav_xml_escape_uri(apr_pool_t *p, const char *uri) { - const char *e_uri = ap_escape_uri(p, uri); - /* check the easy case... */ - if (ap_strchr_c(e_uri, '&') == NULL) - return e_uri; + if (ap_strchr_c(uri, '&') == NULL) + return uri; /* there was a '&', so more work is needed... sigh. */ @@ -408,7 +406,7 @@ static const char *dav_xml_escape_uri(apr_pool_t *p, const char *uri) * Note: this is a teeny bit of overkill since we know there are no * '<' or '>' characters, but who cares. */ - return apr_xml_quote_string(p, e_uri, 0); + return apr_xml_quote_string(p, uri, 0); } @@ -604,7 +602,8 @@ static int dav_handle_err(request_rec *r, dav_error *err, return DONE; } -/* handy function for return values of methods that (may) create things */ +/* handy function for return values of methods that (may) create things. + * locn if provided is assumed to be escaped. */ static int dav_created(request_rec *r, const char *locn, const char *what, int replaced) { @@ -612,8 +611,6 @@ static int dav_created(request_rec *r, const char *locn, const char *what, if (locn == NULL) { locn = r->unparsed_uri; - } else { - locn = ap_escape_uri(r->pool, locn); } /* did the target resource already exist? */ @@ -2756,7 +2753,7 @@ static int dav_method_copymove(request_rec *r, int is_move) * The multistatus responses will contain the information about any * resource that fails the validation. * - * We check the parent resource, too, since this is a MOVE. Moving the + * We check the parent resource, too, if this is a MOVE. Moving the * resource effectively removes it from the parent collection, so we * must ensure that we have met the appropriate conditions. * @@ -2765,7 +2762,9 @@ static int dav_method_copymove(request_rec *r, int is_move) */ if ((err = dav_validate_request(r, resource, depth, NULL, &multi_response, - DAV_VALIDATE_PARENT + (is_move ? DAV_VALIDATE_PARENT + : DAV_VALIDATE_RESOURCE + | DAV_VALIDATE_NO_MODIFY) | DAV_VALIDATE_USE_424, NULL)) != NULL) { err = dav_push_error(r->pool, err->status, 0, @@ -3002,7 +3001,7 @@ 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", + return dav_created(r, lookup.rnew->unparsed_uri, "Destination", resnew_state == DAV_RESOURCE_EXISTS); } @@ -4608,7 +4607,7 @@ static int dav_method_bind(request_rec *r) /* return an appropriate response (HTTP_CREATED) */ /* ### spec doesn't say what happens when destination was replaced */ - return dav_created(r, lookup.rnew->uri, "Binding", 0); + return dav_created(r, lookup.rnew->unparsed_uri, "Binding", 0); } diff --git a/modules/dav/main/mod_dav.h b/modules/dav/main/mod_dav.h index 7b91b63c..62c21f05 100644 --- a/modules/dav/main/mod_dav.h +++ b/modules/dav/main/mod_dav.h @@ -386,7 +386,7 @@ typedef struct dav_resource { * REGULAR and WORKSPACE resources, * and is always 1 for WORKING */ - const char *uri; /* the URI for this resource */ + const char *uri; /* the escaped URI for this resource */ dav_resource_private *info; /* the provider's private info */ @@ -1297,6 +1297,9 @@ DAV_DECLARE(dav_error *) dav_validate_request(request_rec *r, the 424 DAV:response */ #define DAV_VALIDATE_USE_424 0x0080 /* return 424 status, not 207 */ #define DAV_VALIDATE_IS_PARENT 0x0100 /* for internal use */ +#define DAV_VALIDATE_NO_MODIFY 0x0200 /* resource is not being modified + so allow even if lock token + is not provided */ /* Lock-null related public lock functions */ DAV_DECLARE(int) dav_get_resource_state(request_rec *r, diff --git a/modules/dav/main/util.c b/modules/dav/main/util.c index ab42af02..1f393401 100644 --- a/modules/dav/main/util.c +++ b/modules/dav/main/util.c @@ -954,13 +954,16 @@ static dav_error * dav_validate_resource_state(apr_pool_t *p, /* ** For methods other than LOCK: ** - ** If we have no locks, then <seen_locktoken> can be set to true -- + ** If we have no locks or if the resource is not being modified + ** (per RFC 4918 the lock token is not required on resources + ** we are not changing), then <seen_locktoken> can be set to true -- ** pretending that we've already met the requirement of seeing one ** of the resource's locks in the If: header. ** ** Otherwise, it must be cleared and we'll look for one. */ - seen_locktoken = (lock_list == NULL); + seen_locktoken = (lock_list == NULL + || flags & DAV_VALIDATE_NO_MODIFY); } /* |