Skip to content

Conversation

@leo9800
Copy link

@leo9800 leo9800 commented Sep 4, 2025

WebDAV RFCs did not specify a standard approach to set modification time for files or directory on the server, this feature enables better presevation of file metadata when uploading.

as a compensation, OwnCloud (now known as NextCloud) proposed a X-OC-Mtime header which contains UNIX timestamp of mtime with file-modifying methods (e.g. PUT) which implements the feature above as a extension to the standard.

this patch allows apache to optionally honor the X-OC-Mtime header and set mtime accordingly if DavHonorMtimeHeader On is set.

@leo9800 leo9800 marked this pull request as ready for review September 6, 2025 19:56
Copy link
Collaborator

@notroj notroj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an interesting feature. Are you aware of any standardisation effort for that header?

status = apr_file_mtime_set(resource->info->pathname, mtime, pool);

if (status != APR_SUCCESS) {
return dav_new_error(pool, HTTP_BAD_REQUEST, 0, status, "Could not set mtime.");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we get this far this is likely not a client error so this should be mapped to something appropriate rather than a 400. Or default to 500?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually i was a bit unsure whether 4xx or 5xx should be returned in such case. despite most invalid patterns has already being sanitized in dav_parse_mtime, including:

  • non-digits, e.g. nonsense bytes
  • negatives, e.g. -123123123
  • non-decimal, e.g. 0xa0b1
  • empty strings
  • overflowing

while apr_file_mtime_set may still fail, in most cases it is clear that a 500 should be returned, e.g. kernel VFS failed to respond utime syscall. but i was wondering if there is any possibility that an invalid user input fails apr_file_mtime_set where 400 should be returned.

as of now I would return a 500 in such cases instead of 400.

@leo9800
Copy link
Author

leo9800 commented Sep 9, 2025

This is an interesting feature. Are you aware of any standardisation effort for that header?

seems there is not much such efforts (i.e. RFC drafts) from what i know.

it is an approach OwnCloud (predecessor of NextCloud) adopts to enable mtime presevation when uploading file via WebDAV as RFCs of WebDAV does not define a standard way to do so.

this feature is also implemented by rclone's rclone serve webdav WebDAV server command: https://github.com/rclone/rclone/blob/3f0e9f5fca8080f87094341f8ac5027091cc7601/cmd/serve/webdav/webdav.go#L339

given that this is a non-standard, i would implement it but keep it disabled by default to avoid any non-standard breaking change. users who prefer to use this feature should have it opted in manually with DAVHonorMtimeHeader On.

@leo9800 leo9800 requested a review from notroj September 9, 2025 02:32
Copy link
Collaborator

@notroj notroj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update, looking good. One minor style nit:

} else {

should be written as

}
else {

}

/**
* @return 1 if valid x-oc-mtime,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer this with an apr_status_t return value, though it's a minor question of style

Copy link
Author

@leo9800 leo9800 Sep 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i am not sure if apr_status_t is proper for this case personally.

since 0 is defined as APR_SUCCESS, while for the returning value of this function both 1 and 0 are considered success, and -1 stands for a failure.

actually i was imitating static int dav_parse_range(request_rec *r, apr_off_t *range_start, apr_off_t *range_end) in mod_dav.c

leo9800 added a commit to leo9800/httpd that referenced this pull request Sep 23, 2025
@leo9800
Copy link
Author

leo9800 commented Sep 23, 2025

@notroj

i am still a bit confused on how should APLOGNO() being handled with APLOG_DEBUG leveled logs.

there are 3 possible handlings:

  1. ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO() "PLACEHOLDER MSG");: do not assign tags, let apache maintainers to invoke docs/log-message-tags/update-log-msg-tags
  2. ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01234) "PLACEHOLDER MSG");: assign tags, by invoking docs/log-message-tags/update-log-msg-tags
  3. ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "PLACEHOLDER MSG");: do not include APLOGNO() at all

the comment

as above don't use APLOGNO() for DEBUG-level logging

suggests approach 3, but by invoking git grep -F APLOG_DEBUG on the repo huge amount of modules included APLOGNO(), which suggests approach 1 or 2.

modules/aaa/mod_auth_digest.c:        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, APLOGNO(01757)
modules/aaa/mod_auth_digest.c:    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, APLOGNO(01763)
modules/aaa/mod_auth_digest.c:        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01764)
modules/aaa/mod_auth_digest.c:        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01765)
modules/aaa/mod_auth_digest.c:    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01768)
modules/aaa/mod_auth_form.c:        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02982)
modules/aaa/mod_auth_form.c:        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02983)
modules/aaa/mod_auth_form.c:        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01812)
modules/aaa/mod_authn_socache.c:        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(01679)
modules/aaa/mod_authn_socache.c:        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01681)
modules/aaa/mod_authn_socache.c:        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01684)
modules/aaa/mod_authn_socache.c:        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01685)
modules/aaa/mod_authn_socache.c:        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01687)
modules/aaa/mod_authn_socache.c:        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01688)
# truncated git grep output ...

@notroj
Copy link
Collaborator

notroj commented Sep 30, 2025

(3). For DEBUG-level or TRACE-level , omit the APLOGNO() entirely. This was the consensus on the dev@ list, possibly isn't documented anywhere.

@leo9800
Copy link
Author

leo9800 commented Sep 30, 2025

@notroj gotcha

@leo9800
Copy link
Author

leo9800 commented Sep 30, 2025

should i also rebase this patch to current trunk?

i noticed a merge conflict related to log-number, (APLOGNO) probably caused by another patch submitted later than this introducing some new log messages.

@notroj
Copy link
Collaborator

notroj commented Oct 2, 2025

Don't worry about APLOGNO() conflicts, leave that to a committer to fix up. I did a CI run - one issue here: https://github.com/notroj/httpd/actions/runs/18156145629/job/51676367710
move the apr_size_t to the top of the function.

@leo9800
Copy link
Author

leo9800 commented Oct 2, 2025

@notroj gotcha

seems we need to ensure conformity with C89/C90

@leo9800 leo9800 requested a review from notroj October 2, 2025 14:49
@notroj
Copy link
Collaborator

notroj commented Oct 2, 2025

Some more failures now https://github.com/notroj/httpd/actions/runs/18197214275/job/51806547259#logs

and probably best to rebase onto the trunk again because the trunk tests are failing without 60ad836

leo9800 added a commit to leo9800/httpd that referenced this pull request Oct 2, 2025
leo9800 added 14 commits October 3, 2025 00:53
…av_hooks_repository`

modules/dav/fs/repos.c: implement `dav_fs_set_mtime`

Signed-off-by: Leo <[email protected]>
…mtime when `conf->honor_mtime_header == DAV_ENABLED_ON`,

                            check `set_mtime` callback is available before invoking, log debug-level messages
docs/log-message-tags: bumped with `docs/log-message-tags/update-log-msg-tags`

Signed-off-by: Leo <[email protected]>
…e_set` fails, emit error-level log message also

docs/log-message-tags: bumped with `docs/log-message-tags/update-log-msg-tags`

Signed-off-by: Leo <[email protected]>
…y beginning of `dav_method_put()`, this avoids access of uninitialized structure

Signed-off-by: Leo <[email protected]>
…cation times for directory (MKCOL)

Signed-off-by: Leo <[email protected]>
 - remove unnecessary variable declarations: `mtime_aware`, `err3`
 - always initialize `mtime_ret` to `0`
 - simplify mtime-setting procedures

Signed-off-by: Leo <[email protected]>
@notroj
Copy link
Collaborator

notroj commented Oct 6, 2025

https://github.com/notroj/httpd/actions/runs/18216313264

🎉 I'll try to get it merged this week, thanks for your persistence!

@leo9800
Copy link
Author

leo9800 commented Oct 7, 2025

@notroj thanks for reviewing, cheers🎉

also, kindly asking, could you please review another patch initiated by me at #558? (probably try with CI builds, etc)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants