ASF Bugzilla – Attachment 32560 Details for
Bug 27578
made getlastmodified a writable property
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Updated patch against trunk
setlastmodified.patch (text/plain), 14.79 KB, created by
Wim Lewis
on 2015-03-11 23:48:29 UTC
(
hide
)
Description:
Updated patch against trunk
Filename:
MIME Type:
Creator:
Wim Lewis
Created:
2015-03-11 23:48:29 UTC
Size:
14.79 KB
patch
obsolete
>Index: modules/dav/fs/mod_dav_fs.c >=================================================================== >--- modules/dav/fs/mod_dav_fs.c (revision 1666037) >+++ modules/dav/fs/mod_dav_fs.c (working copy) >@@ -24,9 +24,13 @@ > /* per-server configuration */ > typedef struct { > const char *lockdb_path; >- > } dav_fs_server_conf; > >+/* per-context configuration */ >+typedef struct { >+ int allow_set_mtime; >+} dav_fs_context_conf; >+ > extern module AP_MODULE_DECLARE_DATA dav_fs_module; > > const char *dav_get_lockdb_path(const request_rec *r) >@@ -37,6 +41,14 @@ > return conf->lockdb_path; > } > >+int dav_get_allow_set_mtime(const request_rec *r) >+{ >+ dav_fs_context_conf *conf; >+ >+ conf = ap_get_module_config(r->per_dir_config, &dav_fs_module); >+ return conf->allow_set_mtime; >+} >+ > static void *dav_fs_create_server_config(apr_pool_t *p, server_rec *s) > { > return apr_pcalloc(p, sizeof(dav_fs_server_conf)); >@@ -57,7 +69,23 @@ > return newconf; > } > >+static void *dav_fs_create_dir_config(apr_pool_t *pool, char *context) >+{ >+ dav_fs_context_conf *cfg; >+ cfg = apr_palloc(pool, sizeof(*cfg)); >+ >+ /* Set the default values */ >+ cfg->allow_set_mtime = 0; /* Disabled by default, for back compat */ >+ >+ return cfg; >+} >+ > /* >+ * We don't have a dav_fs_merge_dir_config() because the default >+ * behavior of simply replacing the entire config is correct for us. >+ */ >+ >+/* > * Command handler for the DAVLockDB directive, which is TAKE1 > */ > static const char *dav_fs_cmd_davlockdb(cmd_parms *cmd, void *config, >@@ -76,12 +104,28 @@ > return NULL; > } > >+/* >+ * Command handler for the DAVPropsetModTime directive, which takes a FLAG >+ */ >+static const char *dav_fs_cmd_allowmtime(cmd_parms *cmd, void *config, >+ int enable) >+{ >+ dav_fs_context_conf *conf = config; >+ conf->allow_set_mtime = enable? 1 : 0; >+ return NULL; >+} >+ > static const command_rec dav_fs_cmds[] = > { > /* per server */ > AP_INIT_TAKE1("DAVLockDB", dav_fs_cmd_davlockdb, NULL, RSRC_CONF, > "specify a lock database"), > >+ /* can vary by location */ >+ AP_INIT_FLAG("DAVAllowSetModTime", dav_fs_cmd_allowmtime, NULL, >+ RSRC_CONF | ACCESS_CONF | OR_OPTIONS, >+ "allow PROPPATCH to change a resource's modification time"), >+ > { NULL } > }; > >@@ -99,10 +143,11 @@ > AP_DECLARE_MODULE(dav_fs) = > { > STANDARD20_MODULE_STUFF, >- NULL, /* dir config creater */ >+ dav_fs_create_dir_config, /* dir config creater */ > NULL, /* dir merger --- default is to override */ > dav_fs_create_server_config, /* server config */ > dav_fs_merge_server_config, /* merge server config */ > dav_fs_cmds, /* command table */ > register_hooks, /* register hooks */ > }; >+ >Index: modules/dav/fs/repos.c >=================================================================== >--- modules/dav/fs/repos.c (revision 1666037) >+++ modules/dav/fs/repos.c (working copy) >@@ -22,6 +22,7 @@ > #include "apr_file_io.h" > #include "apr_strings.h" > #include "apr_buckets.h" >+#include "apr_date.h" > > #if APR_HAVE_UNISTD_H > #include <unistd.h> /* for getpid() */ >@@ -170,7 +171,7 @@ > DAV_FS_URI_DAV, > "getlastmodified", > DAV_PROPID_getlastmodified, >- 0 >+ 0 /* handled specially in dav_fs_is_writable */ > }, > > /* our custom properties */ >@@ -2024,73 +2025,83 @@ > return 1; > #endif > >+ if (propid == DAV_PROPID_getlastmodified) { >+ if(!resource->exists) >+ return 0; >+ return dav_get_allow_set_mtime(dav_fs_get_request_rec(resource)); >+ } >+ > (void) dav_get_liveprop_info(propid, &dav_fs_liveprop_group, &info); > return info->is_writable; > } > >+struct dav_fs_patch_context { >+ int propid; >+ union rollback >+ { >+ apr_time_t mtime; >+ apr_fileperms_t perms; >+ } oldvalue; >+ union context >+ { >+ apr_time_t mtime; >+ int executable; >+ } newvalue; >+}; >+ > static dav_error *dav_fs_patch_validate(const dav_resource *resource, > const apr_xml_elem *elem, > int operation, > void **context, > int *defer_to_dead) > { >- const apr_text *cdata; >- const apr_text *f_cdata; >- char value; >+ const char *cdata; > dav_elem_private *priv = elem->priv; >+ int propid = priv->propid; >+ struct dav_fs_patch_context *fscontext; > >- if (priv->propid != DAV_PROPID_FS_executable) { >+ if (propid != DAV_PROPID_FS_executable && >+ propid != DAV_PROPID_getlastmodified) { > *defer_to_dead = 1; > return NULL; > } > >- if (operation == DAV_PROP_OP_DELETE) { >+ if (operation != DAV_PROP_OP_SET) { >+ const char *msg = apr_psprintf(resource->info->pool, >+ "The '%s' property cannot be removed.", >+ elem->name); > return dav_new_error(resource->info->pool, HTTP_CONFLICT, 0, 0, >- "The 'executable' property cannot be removed."); >+ msg); > } > >- cdata = elem->first_cdata.first; >+ cdata = dav_xml_get_cdata(elem, resource->info->pool, 0); > >- /* ### hmm. this isn't actually looking at all the possible text items */ >- f_cdata = elem->first_child == NULL >- ? NULL >- : elem->first_child->following_cdata.first; >- >- /* DBG3("name=%s cdata=%s f_cdata=%s",elem->name,cdata ? cdata->text : "[null]",f_cdata ? f_cdata->text : "[null]"); */ >- >- if (cdata == NULL) { >- if (f_cdata == NULL) { >+ fscontext = apr_pcalloc(resource->info->pool, sizeof(*fscontext)); >+ fscontext->propid = propid; >+ >+ if (propid == DAV_PROPID_FS_executable) { >+ if (cdata == NULL || >+ strlen(cdata) != 1 || >+ (cdata[0] != 'T' && cdata[0] != 'F')) { > return dav_new_error(resource->info->pool, HTTP_CONFLICT, 0, 0, > "The 'executable' property expects a single " >- "character, valued 'T' or 'F'. There was no " >- "value submitted."); >+ "character, valued 'T' or 'F'."); > } >- cdata = f_cdata; >- } >- else if (f_cdata != NULL) >- goto too_long; > >- if (cdata->next != NULL || strlen(cdata->text) != 1) >- goto too_long; >+ fscontext->newvalue.executable = (cdata[0] == 'T'); >+ } else if (propid == DAV_PROPID_getlastmodified) { >+ apr_time_t new_mtime = apr_date_parse_http(cdata); >+ if (new_mtime == APR_DATE_BAD) { >+ return dav_new_error(resource->info->pool, HTTP_CONFLICT, 0, 0, >+ "The 'getlastmodified' property must " >+ "be an HTTP date string."); >+ } > >- value = cdata->text[0]; >- if (value != 'T' && value != 'F') { >- return dav_new_error(resource->info->pool, HTTP_CONFLICT, 0, 0, >- "The 'executable' property expects a single " >- "character, valued 'T' or 'F'. The value " >- "submitted is invalid."); >+ fscontext->newvalue.mtime = new_mtime; > } > >- *context = (void *)((long)(value == 'T')); >- >+ *context = fscontext; > return NULL; >- >- too_long: >- return dav_new_error(resource->info->pool, HTTP_CONFLICT, 0, 0, >- "The 'executable' property expects a single " >- "character, valued 'T' or 'F'. The value submitted " >- "has too many characters."); >- > } > > static dav_error *dav_fs_patch_exec(const dav_resource *resource, >@@ -2099,35 +2110,72 @@ > void *context, > dav_liveprop_rollback **rollback_ctx) > { >- long value = context != NULL; >- apr_fileperms_t perms = resource->info->finfo.protection; >- apr_status_t status; >- long old_value = (perms & APR_UEXECUTE) != 0; >+ struct dav_fs_patch_context *fscontext = context; > >- /* assert: prop == executable. operation == SET. */ >+ if (operation != DAV_PROP_OP_SET) { >+ ap_log_assert("operation == SET", __FILE__, __LINE__); >+ return dav_new_error(resource->info->pool, >+ HTTP_INTERNAL_SERVER_ERROR, 0, 0, NULL); >+ } >+ >+ if (fscontext->propid == DAV_PROPID_FS_executable) { >+ apr_fileperms_t perms = resource->info->finfo.protection; >+ apr_status_t status; >+ struct dav_error *err; >+ >+ fscontext->oldvalue.perms = perms; > >- /* don't do anything if there is no change. no rollback info either. */ >- /* DBG2("new value=%d (old=%d)", value, old_value); */ >- if (value == old_value) >- return NULL; >+ perms &= ~(APR_UEXECUTE); >+ if (fscontext->newvalue.executable) >+ perms |= APR_UEXECUTE; >+ >+ /* don't do anything if there is no change. no rollback info either. */ >+ if (perms == resource->info->finfo.protection) >+ return NULL; >+ >+ status = apr_file_perms_set(resource->info->pathname, perms); > >- perms &= ~APR_UEXECUTE; >- if (value) >- perms |= APR_UEXECUTE; >+ if (status == APR_SUCCESS) { >+ /* update the resource and set up the rollback context */ >+ resource->info->finfo.protection = perms; >+ *rollback_ctx = (dav_liveprop_rollback *)fscontext; >+ return NULL; >+ } > >- if ((status = apr_file_perms_set(resource->info->pathname, perms)) >- != APR_SUCCESS) { >+ err = dav_new_error(resource->info->pool, >+ HTTP_INTERNAL_SERVER_ERROR, 0, status, >+ "Could not set the executable flag of the " >+ "target resource."); >+ if (APR_STATUS_IS_EACCES(status)) >+ err->status = HTTP_FORBIDDEN; >+ return err; >+ } else if (fscontext->propid == DAV_PROPID_getlastmodified) { >+ apr_status_t status; >+ struct dav_error *err; >+ >+ fscontext->oldvalue.mtime = resource->info->finfo.mtime; >+ >+ status = apr_file_mtime_set(resource->info->pathname, fscontext->newvalue.mtime, resource->info->pool); >+ >+ if (status == APR_SUCCESS) { >+ /* update the resource and set up the rollback context */ >+ resource->info->finfo.mtime = fscontext->newvalue.mtime; >+ *rollback_ctx = (dav_liveprop_rollback *)fscontext; >+ return NULL; >+ } >+ >+ err = dav_new_error(resource->info->pool, >+ HTTP_INTERNAL_SERVER_ERROR, 0, status, >+ "Could not set the last-modified-time of the " >+ "target resource."); >+ if (APR_STATUS_IS_EACCES(status)) >+ err->status = HTTP_FORBIDDEN; >+ return err; >+ } else { >+ ap_log_assert("unknown propid", __FILE__, __LINE__); > return dav_new_error(resource->info->pool, >- HTTP_INTERNAL_SERVER_ERROR, 0, status, >- "Could not set the executable flag of the " >- "target resource."); >+ HTTP_INTERNAL_SERVER_ERROR, 0, 0, NULL); > } >- >- /* update the resource and set up the rollback context */ >- resource->info->finfo.protection = perms; >- *rollback_ctx = (dav_liveprop_rollback *)old_value; >- >- return NULL; > } > > static void dav_fs_patch_commit(const dav_resource *resource, >@@ -2143,27 +2191,53 @@ > void *context, > dav_liveprop_rollback *rollback_ctx) > { >- apr_fileperms_t perms = resource->info->finfo.protection & ~APR_UEXECUTE; > apr_status_t status; >- int value = rollback_ctx != NULL; >+ struct dav_fs_patch_context *fscontext; > >- /* assert: prop == executable. operation == SET. */ >+ /* ### The rollback hook is called for all liveprops whose >+ validate hook was called, even if they didn't get an exec >+ because an earlier exec failed or if their validate hook >+ failed. So we need to know not to undo anything we didn't >+ do. We signal this by not setting the rollback ctx unless >+ we want to roll something back. */ >+ if (!rollback_ctx) >+ return NULL; > >- /* restore the executable bit */ >- if (value) >- perms |= APR_UEXECUTE; >+ fscontext = (void *)rollback_ctx; >+ >+ /* assert: operation == SET. */ > >- if ((status = apr_file_perms_set(resource->info->pathname, perms)) >- != APR_SUCCESS) { >- return dav_new_error(resource->info->pool, >- HTTP_INTERNAL_SERVER_ERROR, 0, status, >- "After a failure occurred, the resource's " >- "executable flag could not be restored."); >+ switch(fscontext->propid) { >+ case DAV_PROPID_FS_executable: >+ status = apr_file_perms_set(resource->info->pathname, >+ fscontext->oldvalue.mtime); >+ if (status != APR_SUCCESS) { >+ return dav_new_error(resource->info->pool, >+ HTTP_INTERNAL_SERVER_ERROR, 0, status, >+ "After a failure occurred, the resource's " >+ "executable flag could not be restored."); >+ } >+ >+ resource->info->finfo.protection = fscontext->oldvalue.mtime; >+ >+ break; >+ >+ case DAV_PROPID_getlastmodified: >+ status = apr_file_mtime_set(resource->info->pathname, >+ fscontext->oldvalue.mtime, >+ resource->info->pool); >+ if (status != APR_SUCCESS) { >+ return dav_new_error(resource->info->pool, >+ HTTP_INTERNAL_SERVER_ERROR, 0, status, >+ "After a failure occurred, the resource's " >+ "modification date could not be restored."); >+ } >+ >+ resource->info->finfo.mtime = fscontext->oldvalue.mtime; >+ >+ break; > } > >- /* restore the resource's state */ >- resource->info->finfo.protection = perms; >- > return NULL; > } > >Index: modules/dav/fs/repos.h >=================================================================== >--- modules/dav/fs/repos.h (revision 1666037) >+++ modules/dav/fs/repos.h (working copy) >@@ -67,6 +67,9 @@ > /* where is the lock database located? */ > const char *dav_get_lockdb_path(const request_rec *r); > >+/* can PROPPATCH write the getlastmodified property? */ >+int dav_get_allow_set_mtime(const request_rec *r); >+ > const dav_hooks_locks *dav_fs_get_lock_hooks(request_rec *r); > const dav_hooks_propdb *dav_fs_get_propdb_hooks(request_rec *r); >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 27578
: 32560