diff --git a/ngx_http_dav_ext_module.c b/ngx_http_dav_ext_module.c
index 6e518cf..f3d9e63 100644
--- a/ngx_http_dav_ext_module.c
+++ b/ngx_http_dav_ext_module.c
@@ -14,24 +14,23 @@
#define NGX_HTTP_DAV_EXT_PREALLOCATE 50
-#define NGX_HTTP_DAV_EXT_NODE_PROPFIND 0x001
-#define NGX_HTTP_DAV_EXT_NODE_PROP 0x002
-#define NGX_HTTP_DAV_EXT_NODE_PROPNAME 0x004
-#define NGX_HTTP_DAV_EXT_NODE_ALLPROP 0x008
+#define NGX_HTTP_DAV_EXT_NODE_PROPFIND 0x01
+#define NGX_HTTP_DAV_EXT_NODE_PROP 0x02
+#define NGX_HTTP_DAV_EXT_NODE_PROPNAME 0x04
+#define NGX_HTTP_DAV_EXT_NODE_ALLPROP 0x08
-#define NGX_HTTP_DAV_EXT_PROP_DISPLAYNAME 0x001
-#define NGX_HTTP_DAV_EXT_PROP_GETCONTENTLENGTH 0x002
-#define NGX_HTTP_DAV_EXT_PROP_GETLASTMODIFIED 0x004
-#define NGX_HTTP_DAV_EXT_PROP_RESOURCETYPE 0x008
-#define NGX_HTTP_DAV_EXT_PROP_LOCKDISCOVERY 0x010
-#define NGX_HTTP_DAV_EXT_PROP_SUPPORTEDLOCK 0x020
+#define NGX_HTTP_DAV_EXT_PROP_DISPLAYNAME 0x01
+#define NGX_HTTP_DAV_EXT_PROP_GETCONTENTLENGTH 0x02
+#define NGX_HTTP_DAV_EXT_PROP_GETLASTMODIFIED 0x04
+#define NGX_HTTP_DAV_EXT_PROP_RESOURCETYPE 0x08
+#define NGX_HTTP_DAV_EXT_PROP_LOCKDISCOVERY 0x10
+#define NGX_HTTP_DAV_EXT_PROP_SUPPORTEDLOCK 0x20
-#define NGX_HTTP_DAV_EXT_PROP_ALL 0x7ff
-#define NGX_HTTP_DAV_EXT_PROP_NAMES 0x800
+#define NGX_HTTP_DAV_EXT_PROP_ALL 0x7f
+#define NGX_HTTP_DAV_EXT_PROP_NAMES 0x80
typedef struct {
- ngx_uint_t status;
ngx_str_t uri;
ngx_str_t name;
ngx_uint_t dir; /* unsigned dir:1; */
@@ -134,15 +133,12 @@ ngx_http_dav_ext_handler(ngx_http_request_t *r)
return NGX_DECLINED;
}
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http dav_ext handler");
-
switch (r->method) {
case NGX_HTTP_PROPFIND:
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "dav_ext propfind");
+ "http dav_ext propfind");
rc = ngx_http_read_client_request_body(r,
ngx_http_dav_ext_propfind_handler);
@@ -155,7 +151,13 @@ ngx_http_dav_ext_handler(ngx_http_request_t *r)
case NGX_HTTP_OPTIONS:
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "dav_ext options");
+ "http dav_ext options");
+
+ rc = ngx_http_discard_request_body(r);
+
+ if (rc != NGX_OK) {
+ return rc;
+ }
h = ngx_list_push(&r->headers_out.headers);
if (h == NULL) {
@@ -235,7 +237,7 @@ ngx_http_dav_ext_propfind_handler(ngx_http_request_t *r)
XML_ParserFree(parser);
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "DAV client body in file, "
+ "PROPFIND client body is in file, "
"you may want to increase client_body_buffer_size");
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
@@ -260,6 +262,11 @@ ngx_http_dav_ext_propfind_handler(ngx_http_request_t *r)
XML_ParserFree(parser);
if (len == 0) {
+ /*
+ * For easier debugging treat bodiless requests
+ * as if they expect all properties.
+ */
+
ctx->props = NGX_HTTP_DAV_EXT_PROP_ALL;
}
@@ -354,10 +361,11 @@ ngx_http_dav_ext_propfind(ngx_http_request_t *r)
size_t root, allocated;
u_char *p, *last, *filename;
uintptr_t escape;
- ngx_int_t depth, rc;
+ ngx_int_t rc;
ngx_err_t err;
ngx_str_t path, name, uri;
ngx_dir_t dir;
+ ngx_uint_t depth;
ngx_array_t entries;
ngx_file_info_t fi;
ngx_http_dav_ext_entry_t *entry;
@@ -386,10 +394,12 @@ ngx_http_dav_ext_propfind(ngx_http_request_t *r)
if (path.len > 1 && path.data[path.len - 1] == '/') {
path.len--;
- last--;
+
+ } else {
+ last++;
}
- *last = '\0';
+ path.data[path.len] = '\0';
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http dav_ext propfind path: \"%s\"", path.data);
@@ -398,8 +408,6 @@ ngx_http_dav_ext_propfind(ngx_http_request_t *r)
return NGX_HTTP_NOT_FOUND;
}
- *last++ = '/';
-
if (r->uri.len < 2) {
name = r->uri;
@@ -451,7 +459,6 @@ ngx_http_dav_ext_propfind(ngx_http_request_t *r)
ngx_memzero(entry, sizeof(ngx_http_dav_ext_entry_t));
entry->uri = uri;
- entry->status = NGX_HTTP_OK;
entry->name = name;
entry->dir = ngx_is_dir(&fi);
entry->mtime = ngx_file_mtime(&fi);
@@ -470,6 +477,7 @@ ngx_http_dav_ext_propfind(ngx_http_request_t *r)
rc = NGX_OK;
filename = path.data;
+ filename[path.len] = '/';
for ( ;; ) {
ngx_set_errno(0);
@@ -524,9 +532,8 @@ ngx_http_dav_ext_propfind(ngx_http_request_t *r)
if (ngx_de_info(filename, &dir) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
ngx_de_info_n " \"%s\" failed", filename);
-
- entry->status = NGX_HTTP_FORBIDDEN;
- continue;
+ rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ break;
}
}
@@ -567,10 +574,10 @@ ngx_http_dav_ext_propfind(ngx_http_request_t *r)
}
ngx_memcpy(p, name.data, name.len);
+
entry->name.data = p;
entry->name.len = name.len;
- entry->status = NGX_HTTP_OK;
entry->dir = ngx_de_is_dir(&dir);
entry->mtime = ngx_de_mtime(&dir);
entry->size = ngx_de_size(&dir);
@@ -597,9 +604,9 @@ ngx_http_dav_ext_depth(ngx_http_request_t *r)
/*
* We do not support infinity depth as allowed by RFC4918:
*
- * In practice, support for infinite-depth requests
- * MAY be disabled, due to the performance and security
- * concerns associated with this behavior.
+ * In practice, support for infinite-depth requests
+ * MAY be disabled, due to the performance and security
+ * concerns associated with this behavior.
*/
depth = r->headers_in.depth;
@@ -624,7 +631,8 @@ ngx_http_dav_ext_depth(ngx_http_request_t *r)
&& ngx_strcmp(depth->value.data, "infinity") == 0)
{
/*
- * RFC4918:
+ * RFC4918 allows us to return 403 error in this case.
+ * However we do not return the precondition code.
*
* 403 Forbidden - A server MAY reject PROPFIND requests on
* collections with depth header of "Infinity", in which case
@@ -699,7 +707,7 @@ ngx_http_dav_ext_propfind_send_response(ngx_http_request_t *r,
ngx_str_set(&r->headers_out.content_type, "text/xml");
r->headers_out.content_type_lowcase = NULL;
- ngx_str_set(&r->headers_out.charset, "utf-8"); /* XXX */
+ ngx_str_set(&r->headers_out.charset, "utf-8");
rc = ngx_http_send_header(r);
@@ -716,7 +724,6 @@ ngx_http_dav_ext_format_entry(ngx_http_request_t *r, u_char *dst,
ngx_http_dav_ext_entry_t *entry)
{
size_t len;
- ngx_str_t status_line;
ngx_http_dav_ext_ctx_t *ctx;
static u_char head[] =
@@ -732,14 +739,9 @@ ngx_http_dav_ext_format_entry(ngx_http_request_t *r, u_char *dst,
/* properties */
- static u_char status[] =
- "\n"
- "HTTP/";
-
- /* major.minor status_line */
-
static u_char tail[] =
- "\n"
+ "\n"
+ "HTTP/1.1 200 OK\n"
"\n"
"\n";
@@ -753,30 +755,14 @@ ngx_http_dav_ext_format_entry(ngx_http_request_t *r, u_char *dst,
ctx = ngx_http_get_module_ctx(r, ngx_http_dav_ext_module);
- switch (entry->status) {
- case NGX_HTTP_OK:
- ngx_str_set(&status_line, "200 OK");
- break;
-
- case NGX_HTTP_FORBIDDEN:
- ngx_str_set(&status_line, "403 Forbidden");
- break;
-
- default:
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
if (dst == NULL) {
len = sizeof(head) - 1
+ sizeof(prop) - 1
- + sizeof(status) - 1
+ sizeof(tail) - 1;
len += entry->uri.len + ngx_escape_html(NULL, entry->uri.data,
entry->uri.len);
- len += sizeof("65536") + sizeof("65536") + status_line.len;
-
if (ctx->props & NGX_HTTP_DAV_EXT_PROP_NAMES) {
len += sizeof(names) - 1;
@@ -863,9 +849,6 @@ ngx_http_dav_ext_format_entry(ngx_http_request_t *r, u_char *dst,
}
}
- dst = ngx_cpymem(dst, status, sizeof(status) - 1);
- dst = ngx_sprintf(dst, "%d.%d %V", r->http_major, r->http_major,
- &status_line);
dst = ngx_cpymem(dst, tail, sizeof(tail) - 1);
return (uintptr_t) dst;