summaryrefslogtreecommitdiff
path: root/modules/dav
diff options
context:
space:
mode:
Diffstat (limited to 'modules/dav')
-rw-r--r--modules/dav/fs/lock.c9
-rw-r--r--modules/dav/fs/repos.c12
-rw-r--r--modules/dav/lock/locks.c9
-rw-r--r--modules/dav/main/mod_dav.c2
-rw-r--r--modules/dav/main/util.c59
5 files changed, 71 insertions, 20 deletions
diff --git a/modules/dav/fs/lock.c b/modules/dav/fs/lock.c
index 61dd8553..32220a79 100644
--- a/modules/dav/fs/lock.c
+++ b/modules/dav/fs/lock.c
@@ -600,8 +600,7 @@ static dav_error * dav_fs_load_lock_record(dav_lockdb *lockdb, apr_datum_t key,
dp = apr_pcalloc(p, sizeof(*dp));
memcpy(dp, val.dptr + offset, sizeof(dp->f));
offset += sizeof(dp->f);
- dp->locktoken = apr_palloc(p, sizeof(*dp->locktoken));
- memcpy(dp->locktoken, val.dptr + offset, sizeof(*dp->locktoken));
+ dp->locktoken = apr_pmemdup(p, val.dptr + offset, sizeof(*dp->locktoken));
offset += sizeof(*dp->locktoken);
if (*(val.dptr + offset) == '\0') {
++offset;
@@ -648,15 +647,13 @@ static dav_error * dav_fs_load_lock_record(dav_lockdb *lockdb, apr_datum_t key,
/* Create and fill a dav_lock_indirect structure */
ip = apr_pcalloc(p, sizeof(*ip));
- ip->locktoken = apr_palloc(p, sizeof(*ip->locktoken));
- memcpy(ip->locktoken, val.dptr + offset, sizeof(*ip->locktoken));
+ ip->locktoken = apr_pmemdup(p, val.dptr + offset, sizeof(*ip->locktoken));
offset += sizeof(*ip->locktoken);
memcpy(&ip->timeout, val.dptr + offset, sizeof(ip->timeout));
offset += sizeof(ip->timeout);
memcpy(&ip->key.dsize, val.dptr + offset, sizeof(ip->key.dsize)); /* length of datum */
offset += sizeof(ip->key.dsize);
- ip->key.dptr = apr_palloc(p, ip->key.dsize);
- memcpy(ip->key.dptr, val.dptr + offset, ip->key.dsize);
+ ip->key.dptr = apr_pmemdup(p, val.dptr + offset, ip->key.dsize);
offset += ip->key.dsize;
if (!dav_fs_lock_expired(ip->timeout)) {
diff --git a/modules/dav/fs/repos.c b/modules/dav/fs/repos.c
index 8c28c076..a532e6e9 100644
--- a/modules/dav/fs/repos.c
+++ b/modules/dav/fs/repos.c
@@ -1777,13 +1777,15 @@ static const char *dav_fs_getetag(const dav_resource *resource)
return apr_pstrdup(ctx->pool, "");
if (ctx->finfo.filetype != 0) {
- return apr_psprintf(ctx->pool, "\"%lx-%lx-%lx\"",
- (unsigned long) ctx->finfo.inode,
- (unsigned long) ctx->finfo.size,
- (unsigned long) ctx->finfo.mtime);
+ return apr_psprintf(ctx->pool, "\"%" APR_UINT64_T_HEX_FMT "-%"
+ APR_UINT64_T_HEX_FMT "-%" APR_UINT64_T_HEX_FMT "\"",
+ (apr_uint64_t) ctx->finfo.inode,
+ (apr_uint64_t) ctx->finfo.size,
+ (apr_uint64_t) ctx->finfo.mtime);
}
- return apr_psprintf(ctx->pool, "\"%lx\"", (unsigned long) ctx->finfo.mtime);
+ return apr_psprintf(ctx->pool, "\"%" APR_UINT64_T_HEX_FMT "\"",
+ (apr_uint64_t) ctx->finfo.mtime);
}
static const dav_hooks_repository dav_hooks_repository_fs =
diff --git a/modules/dav/lock/locks.c b/modules/dav/lock/locks.c
index 2b297a8c..a4e0e214 100644
--- a/modules/dav/lock/locks.c
+++ b/modules/dav/lock/locks.c
@@ -603,8 +603,7 @@ static dav_error * dav_generic_load_lock_record(dav_lockdb *lockdb,
offset += sizeof(dp->f);
/* Copy the lock token. */
- dp->locktoken = apr_palloc(p, sizeof(*dp->locktoken));
- memcpy(dp->locktoken, val.dptr + offset, sizeof(*dp->locktoken));
+ dp->locktoken = apr_pmemdup(p, val.dptr + offset, sizeof(*dp->locktoken));
offset += sizeof(*dp->locktoken);
/* Do we have an owner field? */
@@ -639,16 +638,14 @@ static dav_error * dav_generic_load_lock_record(dav_lockdb *lockdb,
/* Create and fill a dav_lock_indirect structure */
ip = apr_pcalloc(p, sizeof(*ip));
- ip->locktoken = apr_palloc(p, sizeof(*ip->locktoken));
- memcpy(ip->locktoken, val.dptr + offset, sizeof(*ip->locktoken));
+ ip->locktoken = apr_pmemdup(p, val.dptr + offset, sizeof(*ip->locktoken));
offset += sizeof(*ip->locktoken);
memcpy(&ip->timeout, val.dptr + offset, sizeof(ip->timeout));
offset += sizeof(ip->timeout);
/* length of datum */
ip->key.dsize = *((int *) (val.dptr + offset));
offset += sizeof(ip->key.dsize);
- ip->key.dptr = apr_palloc(p, ip->key.dsize);
- memcpy(ip->key.dptr, val.dptr + offset, ip->key.dsize);
+ ip->key.dptr = apr_pmemdup(p, val.dptr + offset, ip->key.dsize);
offset += ip->key.dsize;
if (!dav_generic_lock_expired(ip->timeout)) {
diff --git a/modules/dav/main/mod_dav.c b/modules/dav/main/mod_dav.c
index 9033cad9..24699bc0 100644
--- a/modules/dav/main/mod_dav.c
+++ b/modules/dav/main/mod_dav.c
@@ -317,7 +317,7 @@ static int dav_error_response(request_rec *r, int status, const char *body)
/* ### I really don't think this is needed; gotta test */
r->status_line = ap_get_status_line(status);
- ap_set_content_type(r, "text/html");
+ ap_set_content_type(r, "text/html; charset=ISO-8859-1");
/* begin the response now... */
ap_rvputs(r,
diff --git a/modules/dav/main/util.c b/modules/dav/main/util.c
index 153f25d4..5297b908 100644
--- a/modules/dav/main/util.c
+++ b/modules/dav/main/util.c
@@ -1404,6 +1404,39 @@ static dav_error * dav_validate_walker(dav_walk_resource *wres, int calltype)
return NULL;
}
+/* If-* header checking */
+static int dav_meets_conditions(request_rec *r, int resource_state)
+{
+ const char *if_match, *if_none_match;
+ int retVal;
+
+ /* If-Match '*' fix. Resource existence not checked by ap_meets_conditions.
+ * If-Match '*' request should succeed only if the resource exists. */
+ if ((if_match = apr_table_get(r->headers_in, "If-Match")) != NULL) {
+ if (if_match[0] == '*' && resource_state != DAV_RESOURCE_EXISTS)
+ return HTTP_PRECONDITION_FAILED;
+ }
+
+ retVal = ap_meets_conditions(r);
+
+ /* If-None-Match '*' fix. If-None-Match '*' request should succeed
+ * if the resource does not exist. */
+ if (retVal == HTTP_PRECONDITION_FAILED) {
+ /* Note. If if_none_match != NULL, if_none_match is the culprit.
+ * Since, in presence of If-None-Match,
+ * other If-* headers are undefined. */
+ if ((if_none_match =
+ apr_table_get(r->headers_in, "If-None-Match")) != NULL) {
+ if (if_none_match[0] == '*'
+ && resource_state != DAV_RESOURCE_EXISTS) {
+ return OK;
+ }
+ }
+ }
+
+ return retVal;
+}
+
/*
** dav_validate_request: Validate if-headers (and check for locks) on:
** (1) r->filename @ depth;
@@ -1433,6 +1466,9 @@ DAV_DECLARE(dav_error *) dav_validate_request(request_rec *r,
const dav_hooks_repository *repos_hooks = resource->hooks;
dav_buffer work_buf = { 0 };
dav_response *new_response;
+ int resource_state;
+ const char *etag;
+ int set_etag = 0;
#if DAV_DEBUG
if (depth && response == NULL) {
@@ -1449,10 +1485,29 @@ DAV_DECLARE(dav_error *) dav_validate_request(request_rec *r,
if (response != NULL)
*response = NULL;
+ /* Set the ETag header required by dav_meets_conditions() */
+ etag = apr_table_get(r->headers_out, "ETag");
+ if (!etag) {
+ etag = (*resource->hooks->getetag)(resource);
+ if (etag && *etag) {
+ apr_table_set(r->headers_out, "ETag", etag);
+ set_etag = 1;
+ }
+ }
/* Do the standard checks for conditional requests using
* If-..-Since, If-Match etc */
- if ((result = ap_meets_conditions(r)) != OK) {
- /* ### fix this up... how? */
+ resource_state = dav_get_resource_state(r, resource);
+ result = dav_meets_conditions(r, resource_state);
+ if (set_etag) {
+ /*
+ * If we have set an ETag to headers out above for
+ * dav_meets_conditions() revert this here as we do not want to set
+ * the ETag in responses to requests with methods where this might not
+ * be desired.
+ */
+ apr_table_unset(r->headers_out, "ETag");
+ }
+ if (result != OK) {
return dav_new_error(r->pool, result, 0, NULL);
}