diff --git a/ngx_http_webdav_module.c b/ngx_http_webdav_module.c
index 257fbc8..3b8111f 100644
--- a/ngx_http_webdav_module.c
+++ b/ngx_http_webdav_module.c
@@ -310,8 +310,8 @@ static ngx_int_t ngx_http_dav_ext_content_handler(ngx_http_request_t *r) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http dav_ext propfind");
- rc =
- ngx_http_read_client_request_body(r, ngx_http_dav_ext_propfind_handler);
+ rc = ngx_http_read_client_request_body(r,
+ ngx_http_dav_ext_propfind_handler);
if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
return rc;
}
@@ -458,462 +458,473 @@ static ngx_int_t ngx_http_dav_ext_content_handler(ngx_http_request_t *r) {
return NGX_DECLINED;
}
+static void
+ngx_http_dav_ext_propfind_handler(ngx_http_request_t *r)
+{
+ off_t len;
+ ngx_buf_t *b;
+ ngx_chain_t *cl;
+ xmlSAXHandler sax;
+ xmlParserCtxtPtr pctx;
+ ngx_http_dav_ext_xml_ctx_t xctx;
-static void ngx_http_dav_ext_propfind_handler(ngx_http_request_t *r) {
- off_t len;
- ngx_buf_t *b;
- ngx_chain_t *cl;
- xmlSAXHandler sax;
- xmlParserCtxtPtr pctx;
- ngx_http_dav_ext_xml_ctx_t xctx;
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http dav_ext propfind handler");
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http dav_ext propfind handler");
+ ngx_memzero(&xctx, sizeof(ngx_http_dav_ext_xml_ctx_t));
+ ngx_memzero(&sax, sizeof(xmlSAXHandler));
- ngx_memzero(&xctx, sizeof(ngx_http_dav_ext_xml_ctx_t));
- ngx_memzero(&sax, sizeof(xmlSAXHandler));
+ sax.initialized = XML_SAX2_MAGIC;
+ sax.startElementNs = ngx_http_dav_ext_propfind_xml_start;
+ sax.endElementNs = ngx_http_dav_ext_propfind_xml_end;
- sax.initialized = XML_SAX2_MAGIC;
- sax.startElementNs = ngx_http_dav_ext_propfind_xml_start;
- sax.endElementNs = ngx_http_dav_ext_propfind_xml_end;
-
- pctx = xmlCreatePushParserCtxt(&sax, &xctx, NULL, 0, NULL);
- if (pctx == NULL) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "xmlCreatePushParserCtxt() failed");
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- len = 0;
-
- for (cl = r->request_body->bufs; cl; cl = cl->next) {
- b = cl->buf;
-
- if (b->in_file) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "PROPFIND client body is in file, "
- "you may want to increase client_body_buffer_size");
- xmlFreeParserCtxt(pctx);
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
+ pctx = xmlCreatePushParserCtxt(&sax, &xctx, NULL, 0, NULL);
+ if (pctx == NULL) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "xmlCreatePushParserCtxt() failed");
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
}
- if (ngx_buf_special(b)) {
- continue;
+ len = 0;
+
+ for (cl = r->request_body->bufs; cl; cl = cl->next) {
+ b = cl->buf;
+
+ if (b->in_file) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "PROPFIND client body is in file, "
+ "you may want to increase client_body_buffer_size");
+ xmlFreeParserCtxt(pctx);
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
+ }
+
+ if (ngx_buf_special(b)) {
+ continue;
+ }
+
+ len += b->last - b->pos;
+
+ if (xmlParseChunk(pctx, (const char *) b->pos, b->last - b->pos,
+ b->last_buf))
+ {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "xmlParseChunk() failed");
+ xmlFreeParserCtxt(pctx);
+ ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+ return;
+ }
}
- len += b->last - b->pos;
+ xmlFreeParserCtxt(pctx);
- if (xmlParseChunk(pctx, (const char *)b->pos, b->last - b->pos,
- b->last_buf)) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "xmlParseChunk() failed");
- xmlFreeParserCtxt(pctx);
- ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
- return;
+ if (len == 0) {
+
+ /*
+ * For easier debugging treat bodiless requests
+ * as if they expect all properties.
+ */
+
+ xctx.props = NGX_HTTP_DAV_EXT_PROP_ALL;
}
- }
- xmlFreeParserCtxt(pctx);
-
- if (len == 0) {
-
- /*
- * For easier debugging treat bodiless requests
- * as if they expect all properties.
- */
-
- xctx.props = NGX_HTTP_DAV_EXT_PROP_ALL;
- }
-
- ngx_http_finalize_request(r, ngx_http_dav_ext_propfind(r, xctx.props));
+ ngx_http_finalize_request(r, ngx_http_dav_ext_propfind(r, xctx.props));
}
-static void ngx_http_dav_ext_propfind_xml_start(
- void *data, const xmlChar *localname, const xmlChar *prefix,
- const xmlChar *uri, int nb_namespaces, const xmlChar **namespaces,
- int nb_attributes, int nb_defaulted, const xmlChar **attributes) {
- ngx_http_dav_ext_xml_ctx_t *xctx = data;
+static void
+ngx_http_dav_ext_propfind_xml_start(void *data, const xmlChar *localname,
+ const xmlChar *prefix, const xmlChar *uri, int nb_namespaces,
+ const xmlChar **namespaces, int nb_attributes, int nb_defaulted,
+ const xmlChar **attributes)
+{
+ ngx_http_dav_ext_xml_ctx_t *xctx = data;
- if (ngx_strcmp(localname, "propfind") == 0) {
- xctx->nodes ^= NGX_HTTP_DAV_EXT_NODE_PROPFIND;
- }
+ if (ngx_strcmp(localname, "propfind") == 0) {
+ xctx->nodes ^= NGX_HTTP_DAV_EXT_NODE_PROPFIND;
+ }
- if (ngx_strcmp(localname, "prop") == 0) {
- xctx->nodes ^= NGX_HTTP_DAV_EXT_NODE_PROP;
- }
+ if (ngx_strcmp(localname, "prop") == 0) {
+ xctx->nodes ^= NGX_HTTP_DAV_EXT_NODE_PROP;
+ }
- if (ngx_strcmp(localname, "propname") == 0) {
- xctx->nodes ^= NGX_HTTP_DAV_EXT_NODE_PROPNAME;
- }
+ if (ngx_strcmp(localname, "propname") == 0) {
+ xctx->nodes ^= NGX_HTTP_DAV_EXT_NODE_PROPNAME;
+ }
- if (ngx_strcmp(localname, "allprop") == 0) {
- xctx->nodes ^= NGX_HTTP_DAV_EXT_NODE_ALLPROP;
- }
+ if (ngx_strcmp(localname, "allprop") == 0) {
+ xctx->nodes ^= NGX_HTTP_DAV_EXT_NODE_ALLPROP;
+ }
}
-static void ngx_http_dav_ext_propfind_xml_end(void *data,
- const xmlChar *localname,
- const xmlChar *prefix,
- const xmlChar *uri) {
- ngx_http_dav_ext_xml_ctx_t *xctx = data;
- if (xctx->nodes & NGX_HTTP_DAV_EXT_NODE_PROPFIND) {
+static void
+ngx_http_dav_ext_propfind_xml_end(void *data, const xmlChar *localname,
+ const xmlChar *prefix, const xmlChar *uri)
+{
+ ngx_http_dav_ext_xml_ctx_t *xctx = data;
- if (xctx->nodes & NGX_HTTP_DAV_EXT_NODE_PROP) {
- if (ngx_strcmp(localname, "displayname") == 0) {
- xctx->props |= NGX_HTTP_DAV_EXT_PROP_DISPLAYNAME;
- }
+ if (xctx->nodes & NGX_HTTP_DAV_EXT_NODE_PROPFIND) {
- if (ngx_strcmp(localname, "getcontentlength") == 0) {
- xctx->props |= NGX_HTTP_DAV_EXT_PROP_GETCONTENTLENGTH;
- }
+ if (xctx->nodes & NGX_HTTP_DAV_EXT_NODE_PROP) {
+ if (ngx_strcmp(localname, "displayname") == 0) {
+ xctx->props |= NGX_HTTP_DAV_EXT_PROP_DISPLAYNAME;
+ }
- if (ngx_strcmp(localname, "getlastmodified") == 0) {
- xctx->props |= NGX_HTTP_DAV_EXT_PROP_GETLASTMODIFIED;
- }
+ if (ngx_strcmp(localname, "getcontentlength") == 0) {
+ xctx->props |= NGX_HTTP_DAV_EXT_PROP_GETCONTENTLENGTH;
+ }
- if (ngx_strcmp(localname, "resourcetype") == 0) {
- xctx->props |= NGX_HTTP_DAV_EXT_PROP_RESOURCETYPE;
- }
+ if (ngx_strcmp(localname, "getlastmodified") == 0) {
+ xctx->props |= NGX_HTTP_DAV_EXT_PROP_GETLASTMODIFIED;
+ }
- if (ngx_strcmp(localname, "lockdiscovery") == 0) {
- xctx->props |= NGX_HTTP_DAV_EXT_PROP_LOCKDISCOVERY;
- }
+ if (ngx_strcmp(localname, "resourcetype") == 0) {
+ xctx->props |= NGX_HTTP_DAV_EXT_PROP_RESOURCETYPE;
+ }
- if (ngx_strcmp(localname, "supportedlock") == 0) {
- xctx->props |= NGX_HTTP_DAV_EXT_PROP_SUPPORTEDLOCK;
- }
+ if (ngx_strcmp(localname, "lockdiscovery") == 0) {
+ xctx->props |= NGX_HTTP_DAV_EXT_PROP_LOCKDISCOVERY;
+ }
+
+ if (ngx_strcmp(localname, "supportedlock") == 0) {
+ xctx->props |= NGX_HTTP_DAV_EXT_PROP_SUPPORTEDLOCK;
+ }
+ }
+
+ if (xctx->nodes & NGX_HTTP_DAV_EXT_NODE_PROPNAME) {
+ xctx->props |= NGX_HTTP_DAV_EXT_PROP_NAMES;
+ }
+
+ if (xctx->nodes & NGX_HTTP_DAV_EXT_NODE_ALLPROP) {
+ xctx->props = NGX_HTTP_DAV_EXT_PROP_ALL;
+ }
}
- if (xctx->nodes & NGX_HTTP_DAV_EXT_NODE_PROPNAME) {
- xctx->props |= NGX_HTTP_DAV_EXT_PROP_NAMES;
- }
-
- if (xctx->nodes & NGX_HTTP_DAV_EXT_NODE_ALLPROP) {
- xctx->props = NGX_HTTP_DAV_EXT_PROP_ALL;
- }
- }
-
- ngx_http_dav_ext_propfind_xml_start(data, localname, prefix, uri, 0, NULL, 0,
- 0, NULL);
+ ngx_http_dav_ext_propfind_xml_start(data, localname, prefix, uri,
+ 0, NULL, 0, 0, NULL);
}
-static ngx_int_t ngx_http_dav_ext_propfind(ngx_http_request_t *r,
- ngx_uint_t props) {
- size_t root, allocated;
- u_char *p, *last, *filename;
- ngx_int_t rc;
- ngx_err_t err;
- ngx_str_t path, name;
- ngx_dir_t dir;
- ngx_uint_t depth;
- ngx_array_t entries;
- ngx_file_info_t fi;
- ngx_http_dav_ext_entry_t *entry;
- if (ngx_array_init(&entries, r->pool, 40, sizeof(ngx_http_dav_ext_entry_t)) !=
- NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
+static ngx_int_t
+ngx_http_dav_ext_propfind(ngx_http_request_t *r, ngx_uint_t props)
+{
+ size_t root, allocated;
+ u_char *p, *last, *filename;
+ ngx_int_t rc;
+ ngx_err_t err;
+ ngx_str_t path, name;
+ ngx_dir_t dir;
+ ngx_uint_t depth;
+ ngx_array_t entries;
+ ngx_file_info_t fi;
+ ngx_http_dav_ext_entry_t *entry;
- rc = ngx_http_dav_ext_depth(r, 0);
-
- if (rc == NGX_ERROR) {
- return NGX_HTTP_BAD_REQUEST;
- }
-
- if (rc == NGX_MAX_INT_T_VALUE) {
-
- /*
- * RFC4918:
- * 403 Forbidden - A server MAY reject PROPFIND requests on
- * collections with depth header of "Infinity", in which case
- * it SHOULD use this error with the precondition code
- * 'propfind-finite-depth' inside the error body.
- */
-
- return NGX_HTTP_FORBIDDEN;
- }
-
- depth = rc;
-
- last =
- ngx_http_map_uri_to_path(r, &path, &root, NGX_HTTP_DAV_EXT_PREALLOCATE);
- if (last == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- allocated = path.len;
- path.len = last - path.data;
-
- if (path.len > 1 && path.data[path.len - 1] == '/') {
- path.len--;
-
- } else {
- last++;
- }
-
- path.data[path.len] = '\0';
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http dav_ext propfind path: \"%s\"", path.data);
-
- if (ngx_file_info(path.data, &fi) == NGX_FILE_ERROR) {
- return NGX_HTTP_NOT_FOUND;
- }
-
- if (r->uri.len < 2) {
- name = r->uri;
-
- } else {
- name.data = &r->uri.data[r->uri.len - 1];
- name.len = (name.data[0] == '/') ? 0 : 1;
-
- while (name.data != r->uri.data) {
- p = name.data - 1;
- if (*p == '/') {
- break;
- }
-
- name.data--;
- name.len++;
- }
- }
-
- entry = ngx_array_push(&entries);
- if (entry == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_memzero(entry, sizeof(ngx_http_dav_ext_entry_t));
-
- entry->uri = r->uri;
- entry->name = name;
- entry->dir = ngx_is_dir(&fi);
- entry->mtime = ngx_file_mtime(&fi);
- entry->size = ngx_file_size(&fi);
-
- if (ngx_http_dav_ext_set_locks(r, entry) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http dav_ext propfind name:\"%V\", uri:\"%V\"", &entry->name,
- &entry->uri);
-
- if (depth == 0 || !entry->dir) {
- return ngx_http_dav_ext_propfind_response(r, &entries, props);
- }
-
- if (ngx_open_dir(&path, &dir) == NGX_ERROR) {
- ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
- ngx_open_dir_n " \"%s\" failed", path.data);
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- rc = NGX_OK;
-
- filename = path.data;
- filename[path.len] = '/';
-
- for (;;) {
- ngx_set_errno(0);
-
- if (ngx_read_dir(&dir) == NGX_ERROR) {
- err = ngx_errno;
-
- if (err != NGX_ENOMOREFILES) {
- ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
- ngx_read_dir_n " \"%V\" failed", &path);
- rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- break;
+ if (ngx_array_init(&entries, r->pool, 40, sizeof(ngx_http_dav_ext_entry_t))
+ != NGX_OK)
+ {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- name.len = ngx_de_namelen(&dir);
- name.data = ngx_de_name(&dir);
+ rc = ngx_http_dav_ext_depth(r, 0);
- if ((name.len == 1 && name.data[0] == '.') ||
- (name.len == 2 && name.data[0] == '.' && name.data[1] == '.')) {
- continue;
+ if (rc == NGX_ERROR) {
+ return NGX_HTTP_BAD_REQUEST;
}
+ if (rc == NGX_MAX_INT_T_VALUE) {
+
+ /*
+ * RFC4918:
+ * 403 Forbidden - A server MAY reject PROPFIND requests on
+ * collections with depth header of "Infinity", in which case
+ * it SHOULD use this error with the precondition code
+ * 'propfind-finite-depth' inside the error body.
+ */
+
+ return NGX_HTTP_FORBIDDEN;
+ }
+
+ depth = rc;
+
+ last = ngx_http_map_uri_to_path(r, &path, &root,
+ NGX_HTTP_DAV_EXT_PREALLOCATE);
+ if (last == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ allocated = path.len;
+ path.len = last - path.data;
+
+ if (path.len > 1 && path.data[path.len - 1] == '/') {
+ path.len--;
+
+ } else {
+ last++;
+ }
+
+ path.data[path.len] = '\0';
+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http dav_ext propfind child path: \"%s\"", name.data);
+ "http dav_ext propfind path: \"%s\"", path.data);
+
+ if (ngx_file_info(path.data, &fi) == NGX_FILE_ERROR) {
+ return NGX_HTTP_NOT_FOUND;
+ }
+
+ if (r->uri.len < 2) {
+ name = r->uri;
+
+ } else {
+ name.data = &r->uri.data[r->uri.len - 1];
+ name.len = (name.data[0] == '/') ? 0 : 1;
+
+ while (name.data != r->uri.data) {
+ p = name.data - 1;
+ if (*p == '/') {
+ break;
+ }
+
+ name.data--;
+ name.len++;
+ }
+ }
entry = ngx_array_push(&entries);
if (entry == NULL) {
- rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
- break;
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
ngx_memzero(entry, sizeof(ngx_http_dav_ext_entry_t));
- if (!dir.valid_info) {
-
- if (path.len + 1 + name.len + 1 > allocated) {
- allocated = path.len + 1 + name.len + 1 + NGX_HTTP_DAV_EXT_PREALLOCATE;
-
- filename = ngx_pnalloc(r->pool, allocated);
- if (filename == NULL) {
- rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
- break;
- }
-
- last = ngx_cpystrn(filename, path.data, path.len + 1);
- *last++ = '/';
- }
-
- ngx_cpystrn(last, name.data, name.len + 1);
-
- if (ngx_de_info(filename, &dir) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno,
- ngx_de_info_n " \"%s\" failed", filename);
- continue;
- }
- }
-
- p = ngx_pnalloc(r->pool, name.len);
- if (p == NULL) {
- rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
- break;
- }
-
- ngx_memcpy(p, name.data, name.len);
- entry->name.data = p;
- entry->name.len = name.len;
-
- p = ngx_pnalloc(r->pool, r->uri.len + 1 + name.len + 1);
- if (p == NULL) {
- rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
- break;
- }
-
- entry->uri.data = p;
-
- p = ngx_cpymem(p, r->uri.data, r->uri.len);
- if (r->uri.len && r->uri.data[r->uri.len - 1] != '/') {
- *p++ = '/';
- }
-
- p = ngx_cpymem(p, name.data, name.len);
- if (ngx_de_is_dir(&dir)) {
- *p++ = '/';
- }
-
- entry->uri.len = p - entry->uri.data;
- entry->dir = ngx_de_is_dir(&dir);
- entry->mtime = ngx_de_mtime(&dir);
- entry->size = ngx_de_size(&dir);
+ entry->uri = r->uri;
+ entry->name = name;
+ entry->dir = ngx_is_dir(&fi);
+ entry->mtime = ngx_file_mtime(&fi);
+ entry->size = ngx_file_size(&fi);
if (ngx_http_dav_ext_set_locks(r, entry) != NGX_OK) {
- rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
- break;
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http dav_ext propfind child name:\"%V\", uri:\"%V\"",
+ "http dav_ext propfind name:\"%V\", uri:\"%V\"",
&entry->name, &entry->uri);
- }
- if (ngx_close_dir(&dir) == NGX_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
- ngx_close_dir_n " \"%V\" failed", &path);
- }
+ if (depth == 0 || !entry->dir) {
+ return ngx_http_dav_ext_propfind_response(r, &entries, props);
+ }
- if (rc != NGX_OK) {
- return rc;
- }
+ if (ngx_open_dir(&path, &dir) == NGX_ERROR) {
+ ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
+ ngx_open_dir_n " \"%s\" failed", path.data);
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
- return ngx_http_dav_ext_propfind_response(r, &entries, props);
+ rc = NGX_OK;
+
+ filename = path.data;
+ filename[path.len] = '/';
+
+ for ( ;; ) {
+ ngx_set_errno(0);
+
+ if (ngx_read_dir(&dir) == NGX_ERROR) {
+ err = ngx_errno;
+
+ if (err != NGX_ENOMOREFILES) {
+ ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
+ ngx_read_dir_n " \"%V\" failed", &path);
+ rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ break;
+ }
+
+ name.len = ngx_de_namelen(&dir);
+ name.data = ngx_de_name(&dir);
+
+ if (name.data[0] == '.') {
+ continue;
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http dav_ext propfind child path: \"%s\"", name.data);
+
+ entry = ngx_array_push(&entries);
+ if (entry == NULL) {
+ rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ break;
+ }
+
+ ngx_memzero(entry, sizeof(ngx_http_dav_ext_entry_t));
+
+ if (!dir.valid_info) {
+
+ if (path.len + 1 + name.len + 1 > allocated) {
+ allocated = path.len + 1 + name.len + 1
+ + NGX_HTTP_DAV_EXT_PREALLOCATE;
+
+ filename = ngx_pnalloc(r->pool, allocated);
+ if (filename == NULL) {
+ rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ break;
+ }
+
+ last = ngx_cpystrn(filename, path.data, path.len + 1);
+ *last++ = '/';
+ }
+
+ ngx_cpystrn(last, name.data, name.len + 1);
+
+ 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);
+ rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ break;
+ }
+ }
+
+ p = ngx_pnalloc(r->pool, name.len);
+ if (p == NULL) {
+ rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ break;
+ }
+
+ ngx_memcpy(p, name.data, name.len);
+ entry->name.data = p;
+ entry->name.len = name.len;
+
+ p = ngx_pnalloc(r->pool, r->uri.len + 1 + name.len + 1);
+ if (p == NULL) {
+ rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ break;
+ }
+
+ entry->uri.data = p;
+
+ p = ngx_cpymem(p, r->uri.data, r->uri.len);
+ if (r->uri.len && r->uri.data[r->uri.len - 1] != '/') {
+ *p++ = '/';
+ }
+
+ p = ngx_cpymem(p, name.data, name.len);
+ if (ngx_de_is_dir(&dir)) {
+ *p++ = '/';
+ }
+
+ entry->uri.len = p - entry->uri.data;
+ entry->dir = ngx_de_is_dir(&dir);
+ entry->mtime = ngx_de_mtime(&dir);
+ entry->size = ngx_de_size(&dir);
+
+ if (ngx_http_dav_ext_set_locks(r, entry) != NGX_OK) {
+ rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ break;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http dav_ext propfind child name:\"%V\", uri:\"%V\"",
+ &entry->name, &entry->uri);
+ }
+
+ if (ngx_close_dir(&dir) == NGX_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
+ ngx_close_dir_n " \"%V\" failed", &path);
+ }
+
+ if (rc != NGX_OK) {
+ return rc;
+ }
+
+ return ngx_http_dav_ext_propfind_response(r, &entries, props);
}
+static ngx_int_t
+ngx_http_dav_ext_propfind_response(ngx_http_request_t *r, ngx_array_t *entries,
+ ngx_uint_t props)
+{
+ size_t len;
+ u_char *p;
+ uintptr_t escape;
+ ngx_buf_t *b;
+ ngx_int_t rc;
+ ngx_uint_t n;
+ ngx_chain_t cl;
+ ngx_http_dav_ext_entry_t *entry;
-static ngx_int_t ngx_http_dav_ext_propfind_response(ngx_http_request_t *r,
- ngx_array_t *entries,
- ngx_uint_t props) {
- size_t len;
- u_char *p;
- uintptr_t escape;
- ngx_buf_t *b;
- ngx_int_t rc;
- ngx_uint_t n;
- ngx_chain_t cl;
- ngx_http_dav_ext_entry_t *entry;
+ static u_char head[] =
+ "\n"
+ "\n";
- static u_char head[] = "\n"
- "\n";
+ static u_char tail[] =
+ "\n";
- static u_char tail[] = "\n";
+ entry = entries->elts;
- entry = entries->elts;
+ for (n = 0; n < entries->nelts; n++) {
+ escape = 2 * ngx_escape_uri(NULL, entry[n].uri.data, entry[n].uri.len,
+ NGX_ESCAPE_URI);
+ if (escape == 0) {
+ continue;
+ }
- for (n = 0; n < entries->nelts; n++) {
- escape = 2 * ngx_escape_uri(NULL, entry[n].uri.data, entry[n].uri.len,
- NGX_ESCAPE_URI_COMPONENT);
- if (escape == 0) {
- continue;
+ p = ngx_pnalloc(r->pool, entry[n].uri.len + escape);
+ if (p == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
+ entry[n].uri.len = (u_char *) ngx_escape_uri(p, entry[n].uri.data,
+ entry[n].uri.len,
+ NGX_ESCAPE_URI)
+ - p;
+ entry[n].uri.data = p;
}
- p = ngx_pnalloc(r->pool, entry[n].uri.len + escape);
- if (p == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ len = sizeof(head) - 1 + sizeof(tail) - 1;
+
+ for (n = 0; n < entries->nelts; n++) {
+ len += ngx_http_dav_ext_format_propfind(r, NULL, &entry[n], props);
}
- entry[n].uri.len =
- (u_char *)ngx_escape_uri(p, entry[n].uri.data, entry[n].uri.len,
- NGX_ESCAPE_URI_COMPONENT) -
- p;
- entry[n].uri.data = p;
- }
+ b = ngx_create_temp_buf(r->pool, len);
+ if (b == NULL) {
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
- len = sizeof(head) - 1 + sizeof(tail) - 1;
+ b->last = ngx_cpymem(b->last, head, sizeof(head) - 1);
- for (n = 0; n < entries->nelts; n++) {
- len += ngx_http_dav_ext_format_propfind(r, NULL, &entry[n], props);
- }
+ for (n = 0; n < entries->nelts; n++) {
+ b->last = (u_char *) ngx_http_dav_ext_format_propfind(r, b->last,
+ &entry[n], props);
+ }
- b = ngx_create_temp_buf(r->pool, len);
- if (b == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
+ b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1);
- b->last = ngx_cpymem(b->last, head, sizeof(head) - 1);
+ b->last_buf = (r == r->main) ? 1 : 0;
+ b->last_in_chain = 1;
- for (n = 0; n < entries->nelts; n++) {
- b->last = (u_char *)ngx_http_dav_ext_format_propfind(r, b->last, &entry[n],
- props);
- }
+ cl.buf = b;
+ cl.next = NULL;
- b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1);
+ r->headers_out.status = 207;
+ ngx_str_set(&r->headers_out.status_line, "207 Multi-Status");
- b->last_buf = (r == r->main) ? 1 : 0;
- b->last_in_chain = 1;
+ r->headers_out.content_length_n = b->last - b->pos;
- cl.buf = b;
- cl.next = NULL;
+ r->headers_out.content_type_len = sizeof("text/xml") - 1;
+ ngx_str_set(&r->headers_out.content_type, "text/xml");
+ r->headers_out.content_type_lowcase = NULL;
- r->headers_out.status = 207;
- ngx_str_set(&r->headers_out.status_line, "207 Multi-Status");
+ ngx_str_set(&r->headers_out.charset, "utf-8");
- r->headers_out.content_length_n = b->last - b->pos;
+ rc = ngx_http_send_header(r);
- r->headers_out.content_type_len = sizeof("text/xml") - 1;
- ngx_str_set(&r->headers_out.content_type, "text/xml");
- r->headers_out.content_type_lowcase = NULL;
+ if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
+ return rc;
+ }
- ngx_str_set(&r->headers_out.charset, "utf-8");
-
- rc = ngx_http_send_header(r);
-
- if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
- return rc;
- }
-
- return ngx_http_output_filter(r, &cl);
+ return ngx_http_output_filter(r, &cl);
}
static ngx_int_t ngx_http_dav_ext_lock_handler(ngx_http_request_t *r) {
@@ -1255,154 +1266,161 @@ static uint32_t ngx_http_dav_ext_lock_token(ngx_http_request_t *r) {
return 0;
}
-
static uintptr_t
ngx_http_dav_ext_format_propfind(ngx_http_request_t *r, u_char *dst,
- ngx_http_dav_ext_entry_t *entry,
- ngx_uint_t props) {
- size_t len;
+ ngx_http_dav_ext_entry_t *entry, ngx_uint_t props)
+{
+ size_t len;
- static u_char head[] = "\n"
- "";
+ static u_char head[] =
+ "\n"
+ "";
- /* uri */
+ /* uri */
- static u_char prop[] = "\n"
- "\n"
- "\n";
+ static u_char prop[] =
+ "\n"
+ "\n"
+ "\n";
- /* properties */
+ /* properties */
- static u_char tail[] = "\n"
- "HTTP/1.1 200 OK\n"
- "\n"
- "\n";
+ static u_char tail[] =
+ "\n"
+ "HTTP/1.1 200 OK\n"
+ "\n"
+ "\n";
- static u_char names[] = "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n";
+ static u_char names[] =
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n"
+ "\n";
- static u_char supportedlock[] = "\n"
- "\n"
- "\n"
- "\n";
+ static u_char supportedlock[] =
+ "\n"
+ "\n"
+ "\n"
+ "\n";
- if (dst == NULL) {
- len = sizeof(head) - 1 + sizeof(prop) - 1 + sizeof(tail) - 1;
+ if (dst == NULL) {
+ len = sizeof(head) - 1
+ + sizeof(prop) - 1
+ + sizeof(tail) - 1;
- len +=
- entry->uri.len + ngx_escape_html(NULL, entry->uri.data, entry->uri.len);
+ len += entry->uri.len + ngx_escape_html(NULL, entry->uri.data,
+ entry->uri.len);
+
+ if (props & NGX_HTTP_DAV_EXT_PROP_NAMES) {
+ len += sizeof(names) - 1;
+
+ } else {
+ len += sizeof(""
+ "\n"
+
+ ""
+ "\n"
+
+ ""
+ "Mon, 28 Sep 1970 06:00:00 GMT"
+ "\n"
+
+ ""
+ ""
+ "\n"
+
+ "\n"
+ "\n") - 1;
+
+ /* displayname */
+ len += entry->name.len
+ + ngx_escape_html(NULL, entry->name.data, entry->name.len);
+
+ /* getcontentlength */
+ len += NGX_OFF_T_LEN;
+
+ /* lockdiscovery */
+ len += ngx_http_dav_ext_format_lockdiscovery(r, NULL, entry);
+
+ /* supportedlock */
+ if (entry->lock_supported) {
+ len += sizeof(supportedlock) - 1;
+ }
+ }
+
+ return len;
+ }
+
+ dst = ngx_cpymem(dst, head, sizeof(head) - 1);
+ dst = (u_char *) ngx_escape_html(dst, entry->uri.data, entry->uri.len);
+ dst = ngx_cpymem(dst, prop, sizeof(prop) - 1);
if (props & NGX_HTTP_DAV_EXT_PROP_NAMES) {
- len += sizeof(names) - 1;
+ dst = ngx_cpymem(dst, names, sizeof(names) - 1);
} else {
- len += sizeof(""
- "\n"
+ if (props & NGX_HTTP_DAV_EXT_PROP_DISPLAYNAME) {
+ dst = ngx_cpymem(dst, "",
+ sizeof("") - 1);
+ dst = (u_char *) ngx_escape_html(dst, entry->name.data,
+ entry->name.len);
+ dst = ngx_cpymem(dst, "\n",
+ sizeof("\n") - 1);
+ }
- ""
- "\n"
+ if (props & NGX_HTTP_DAV_EXT_PROP_GETCONTENTLENGTH) {
+ if (!entry->dir) {
+ dst = ngx_sprintf(dst, "%O"
+ "\n", entry->size);
+ }
+ }
- ""
- "Mon, 28 Sep 1970 06:00:00 GMT"
- "\n"
+ if (props & NGX_HTTP_DAV_EXT_PROP_GETLASTMODIFIED) {
+ dst = ngx_cpymem(dst, "",
+ sizeof("") - 1);
+ dst = ngx_http_time(dst, entry->mtime);
+ dst = ngx_cpymem(dst, "\n",
+ sizeof("\n") - 1);
+ }
- ""
- ""
- "\n"
+ if (props & NGX_HTTP_DAV_EXT_PROP_RESOURCETYPE) {
+ dst = ngx_cpymem(dst, "",
+ sizeof("") - 1);
- "\n"
- "\n") -
- 1;
+ if (entry->dir) {
+ dst = ngx_cpymem(dst, "",
+ sizeof("") - 1);
+ }
- /* displayname */
- len += entry->name.len +
- ngx_escape_html(NULL, entry->name.data, entry->name.len);
+ dst = ngx_cpymem(dst, "\n",
+ sizeof("\n") - 1);
+ }
- /* getcontentlength */
- len += NGX_OFF_T_LEN;
+ if (props & NGX_HTTP_DAV_EXT_PROP_LOCKDISCOVERY) {
+ dst = (u_char *) ngx_http_dav_ext_format_lockdiscovery(r, dst,
+ entry);
+ }
- /* lockdiscovery */
- len += ngx_http_dav_ext_format_lockdiscovery(r, NULL, entry);
+ if (props & NGX_HTTP_DAV_EXT_PROP_SUPPORTEDLOCK) {
+ dst = ngx_cpymem(dst, "\n",
+ sizeof("\n") - 1);
- /* supportedlock */
- if (entry->lock_supported) {
- len += sizeof(supportedlock) - 1;
- }
+ if (entry->lock_supported) {
+ dst = ngx_cpymem(dst, supportedlock, sizeof(supportedlock) - 1);
+ }
+
+ dst = ngx_cpymem(dst, "\n",
+ sizeof("\n") - 1);
+ }
}
- return len;
- }
+ dst = ngx_cpymem(dst, tail, sizeof(tail) - 1);
- dst = ngx_cpymem(dst, head, sizeof(head) - 1);
- dst = (u_char *)ngx_escape_html(dst, entry->uri.data, entry->uri.len);
- dst = ngx_cpymem(dst, prop, sizeof(prop) - 1);
-
- if (props & NGX_HTTP_DAV_EXT_PROP_NAMES) {
- dst = ngx_cpymem(dst, names, sizeof(names) - 1);
-
- } else {
- if (props & NGX_HTTP_DAV_EXT_PROP_DISPLAYNAME) {
- dst = ngx_cpymem(dst, "", sizeof("") - 1);
- dst = (u_char *)ngx_escape_html(dst, entry->name.data, entry->name.len);
- dst = ngx_cpymem(dst, "\n",
- sizeof("\n") - 1);
- }
-
- if (props & NGX_HTTP_DAV_EXT_PROP_GETCONTENTLENGTH) {
- if (!entry->dir) {
- dst = ngx_sprintf(dst,
- "%O"
- "\n",
- entry->size);
- }
- }
-
- if (props & NGX_HTTP_DAV_EXT_PROP_GETLASTMODIFIED) {
- dst = ngx_cpymem(dst, "",
- sizeof("") - 1);
- dst = ngx_http_time(dst, entry->mtime);
- dst = ngx_cpymem(dst, "\n",
- sizeof("\n") - 1);
- }
-
- if (props & NGX_HTTP_DAV_EXT_PROP_RESOURCETYPE) {
- dst = ngx_cpymem(dst, "", sizeof("") - 1);
-
- if (entry->dir) {
- dst = ngx_cpymem(dst, "", sizeof("") - 1);
- }
-
- dst = ngx_cpymem(dst, "\n",
- sizeof("\n") - 1);
- }
-
- if (props & NGX_HTTP_DAV_EXT_PROP_LOCKDISCOVERY) {
- dst = (u_char *)ngx_http_dav_ext_format_lockdiscovery(r, dst, entry);
- }
-
- if (props & NGX_HTTP_DAV_EXT_PROP_SUPPORTEDLOCK) {
- dst = ngx_cpymem(dst, "\n",
- sizeof("\n") - 1);
-
- if (entry->lock_supported) {
- dst = ngx_cpymem(dst, supportedlock, sizeof(supportedlock) - 1);
- }
-
- dst = ngx_cpymem(dst, "\n",
- sizeof("\n") - 1);
- }
- }
-
- dst = ngx_cpymem(dst, tail, sizeof(tail) - 1);
-
- return (uintptr_t)dst;
+ return (uintptr_t) dst;
}
-
static ngx_int_t ngx_http_dav_ext_init_zone(ngx_shm_zone_t *shm_zone,
void *data) {
ngx_http_dav_ext_lock_t *olock = data;