From 8b075a6abd19f332cd15eb5612338c10d1ab2014 Mon Sep 17 00:00:00 2001 From: Pelagic Date: Tue, 16 Apr 2024 12:34:32 +0300 Subject: [PATCH] There was an error somewhere in the code when it was extracted from arut/dav-ext-module, perhaps due to the formatter. --- ngx_http_webdav_module.c | 1020 +++++++++++++++++++------------------- 1 file changed, 519 insertions(+), 501 deletions(-) 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;