Added all the rest of the project files. It doesn't work as an nginx module yet I need to find the error.
This commit is contained in:
27
config
Executable file
27
config
Executable file
@@ -0,0 +1,27 @@
|
||||
ngx_addon_name=ngx_http_webdav_module
|
||||
|
||||
HEADERS_MORE_SRCS="$ngx_addon_dir/ngx_http_webdav_module.c $ngx_addon_dir/ngx_http_webdav_utils.c"
|
||||
|
||||
HEADERS_MORE_DEPS="$ngx_addon_dir/ngx_http_webdav_module.h $ngx_addon_dir/ngx_http_webdav_utils.h"
|
||||
|
||||
if test -n "$ngx_module_link"; then
|
||||
ngx_module_type=HTTP_AUX_FILTER
|
||||
ngx_module_name=$ngx_addon_name
|
||||
ngx_module_incs=
|
||||
ngx_module_deps="$HEADERS_MORE_DEPS"
|
||||
ngx_module_srcs="$HEADERS_MORE_SRCS"
|
||||
|
||||
# nginx has robust builtin support for linking against
|
||||
# libxml2+libxslt. This is definitelty the right way to go if
|
||||
# building nginx with the xslt module, in which case libxslt will
|
||||
# be linked anyway. In other cases libxslt is just redundant.
|
||||
# If that's a big deal, libxml2 can be linked directly:
|
||||
# ngx_module_libs=-lxml2
|
||||
ngx_module_libs=LIBXSLT
|
||||
|
||||
. auto/module
|
||||
else
|
||||
HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES $ngx_addon_name"
|
||||
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $HEADERS_MORE_SRCS"
|
||||
NGX_ADDON_DEPS="$NGX_ADDON_DEPS $HEADERS_MORE_DEPS"
|
||||
fi
|
||||
2412
ngx_http_webdav_module.c
Normal file
2412
ngx_http_webdav_module.c
Normal file
File diff suppressed because it is too large
Load Diff
24
ngx_http_webdav_module.h
Normal file
24
ngx_http_webdav_module.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) Starfields
|
||||
*/
|
||||
|
||||
#include <ngx_http.h>
|
||||
|
||||
#ifndef NGX_HTTP_WEBDAV_MODULE_H
|
||||
#define NGX_HTTP_WEBDAV_MODULE_H
|
||||
|
||||
|
||||
// The module location configuration
|
||||
typedef struct {
|
||||
ngx_uint_t methods;
|
||||
ngx_shm_zone_t *shm_zone;
|
||||
ngx_http_complex_value_t *realm;
|
||||
ngx_http_complex_value_t *user_file;
|
||||
ngx_uint_t access;
|
||||
ngx_uint_t min_delete_depth;
|
||||
ngx_flag_t create_full_put_path;
|
||||
} ngx_http_dav_ext_loc_conf_t;
|
||||
|
||||
void ngx_http_dav_ext_proppatch_handler(ngx_http_request_t *r);
|
||||
|
||||
#endif
|
||||
708
ngx_http_webdav_utils.c
Normal file
708
ngx_http_webdav_utils.c
Normal file
@@ -0,0 +1,708 @@
|
||||
/*
|
||||
* Copyright (C) Starfields
|
||||
*/
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
#include <ngx_http.h>
|
||||
#include "ngx_http_webdav_utils.h"
|
||||
|
||||
|
||||
#define NGX_HTTP_DAV_NO_DEPTH -3
|
||||
#define NGX_HTTP_DAV_INVALID_DEPTH -2
|
||||
#define NGX_HTTP_DAV_INFINITY_DEPTH -1
|
||||
|
||||
|
||||
static ngx_int_t ngx_http_dav_delete_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path);
|
||||
static ngx_int_t ngx_http_dav_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path);
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_dav_error(ngx_log_t *log, ngx_err_t err, ngx_int_t not_found,
|
||||
char *failed, u_char *path)
|
||||
{
|
||||
ngx_int_t rc;
|
||||
ngx_uint_t level;
|
||||
|
||||
if (err == NGX_ENOENT || err == NGX_ENOTDIR || err == NGX_ENAMETOOLONG) {
|
||||
level = NGX_LOG_ERR;
|
||||
rc = not_found;
|
||||
|
||||
} else if (err == NGX_EACCES || err == NGX_EPERM) {
|
||||
level = NGX_LOG_ERR;
|
||||
rc = NGX_HTTP_FORBIDDEN;
|
||||
|
||||
} else if (err == NGX_EEXIST) {
|
||||
level = NGX_LOG_ERR;
|
||||
rc = NGX_HTTP_NOT_ALLOWED;
|
||||
|
||||
} else if (err == NGX_ENOSPC) {
|
||||
level = NGX_LOG_CRIT;
|
||||
rc = NGX_HTTP_INSUFFICIENT_STORAGE;
|
||||
|
||||
} else {
|
||||
level = NGX_LOG_CRIT;
|
||||
rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
ngx_log_error(level, log, err, "%s \"%s\" failed", failed, path);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_dav_noop(ngx_tree_ctx_t *ctx, ngx_str_t *path)
|
||||
{
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t ngx_http_dav_ext_strip_uri(ngx_http_request_t *r,
|
||||
ngx_str_t *uri) {
|
||||
u_char *p, *last, *host;
|
||||
size_t len;
|
||||
|
||||
if (uri->data[0] == '/') {
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http dav_ext strip uri:\"%V\" unchanged", uri);
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
len = r->headers_in.server.len;
|
||||
|
||||
if (len == 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
#if (NGX_HTTP_SSL)
|
||||
|
||||
if (r->connection->ssl) {
|
||||
if (ngx_strncmp(uri->data, "https://", sizeof("https://") - 1) != 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
host = uri->data + sizeof("https://") - 1;
|
||||
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (ngx_strncmp(uri->data, "http://", sizeof("http://") - 1) != 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
host = uri->data + sizeof("http://") - 1;
|
||||
}
|
||||
|
||||
if (ngx_strncmp(host, r->headers_in.server.data, len) != 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
last = uri->data + uri->len;
|
||||
|
||||
for (p = host + len; p != last; p++) {
|
||||
if (*p == '/') {
|
||||
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http dav_ext strip uri \"%V\" \"%*s\"", uri, last - p, p);
|
||||
|
||||
uri->data = p;
|
||||
uri->len = last - p;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
}
|
||||
|
||||
failed:
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http dav_ext strip uri \"%V\" failed", uri);
|
||||
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_dav_delete_path(ngx_http_request_t *r, ngx_str_t *path, ngx_uint_t dir)
|
||||
{
|
||||
char *failed;
|
||||
ngx_tree_ctx_t tree;
|
||||
|
||||
if (dir) {
|
||||
|
||||
tree.init_handler = NULL;
|
||||
tree.file_handler = ngx_http_dav_delete_file;
|
||||
tree.pre_tree_handler = ngx_http_dav_noop;
|
||||
tree.post_tree_handler = ngx_http_dav_delete_dir;
|
||||
tree.spec_handler = ngx_http_dav_delete_file;
|
||||
tree.data = NULL;
|
||||
tree.alloc = 0;
|
||||
tree.log = r->connection->log;
|
||||
|
||||
/* TODO: 207 */
|
||||
|
||||
if (ngx_walk_tree(&tree, path) != NGX_OK) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_delete_dir(path->data) != NGX_FILE_ERROR) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
failed = ngx_delete_dir_n;
|
||||
|
||||
} else {
|
||||
|
||||
if (ngx_delete_file(path->data) != NGX_FILE_ERROR) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
failed = ngx_delete_file_n;
|
||||
}
|
||||
|
||||
return ngx_http_dav_error(r->connection->log, ngx_errno,
|
||||
NGX_HTTP_NOT_FOUND, failed, path->data);
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_dav_delete_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path)
|
||||
{
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
|
||||
"http delete dir: \"%s\"", path->data);
|
||||
|
||||
if (ngx_delete_dir(path->data) == NGX_FILE_ERROR) {
|
||||
|
||||
/* TODO: add to 207 */
|
||||
|
||||
(void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_delete_dir_n,
|
||||
path->data);
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_dav_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path)
|
||||
{
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
|
||||
"http delete file: \"%s\"", path->data);
|
||||
|
||||
if (ngx_delete_file(path->data) == NGX_FILE_ERROR) {
|
||||
|
||||
/* TODO: add to 207 */
|
||||
|
||||
(void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_delete_file_n,
|
||||
path->data);
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t ensure_trailing_slash(ngx_http_request_t *r,
|
||||
ngx_str_t *path) {
|
||||
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"initial path: %s", path->data);
|
||||
|
||||
u_char *p = ngx_pnalloc(r->pool, path->len + 1);
|
||||
if (p == NULL) {
|
||||
return 0;
|
||||
}
|
||||
u_char *last = ngx_cpystrn(p, path->data, path->len + 1);
|
||||
*last++ = '/';
|
||||
*last++ = '\0';
|
||||
path->data = p;
|
||||
path->len += 1;
|
||||
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"rewritten the path with a trailing slash: %s", path->data);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt)
|
||||
{
|
||||
ngx_table_elt_t *depth;
|
||||
|
||||
depth = r->headers_in.depth;
|
||||
|
||||
if (depth == NULL) {
|
||||
return dflt;
|
||||
}
|
||||
|
||||
if (depth->value.len == 1) {
|
||||
|
||||
if (depth->value.data[0] == '0') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (depth->value.data[0] == '1') {
|
||||
return 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (depth->value.len == sizeof("infinity") - 1
|
||||
&& ngx_strcmp(depth->value.data, "infinity") == 0)
|
||||
{
|
||||
return NGX_HTTP_DAV_INFINITY_DEPTH;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"client sent invalid \"Depth\" header: \"%V\"",
|
||||
&depth->value);
|
||||
|
||||
return NGX_HTTP_DAV_INVALID_DEPTH;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t ngx_http_dav_ext_depth(ngx_http_request_t *r,
|
||||
ngx_int_t default_depth) {
|
||||
ngx_table_elt_t *depth;
|
||||
|
||||
depth = r->headers_in.depth;
|
||||
|
||||
if (depth == NULL) {
|
||||
return default_depth;
|
||||
}
|
||||
|
||||
if (depth->value.len == 1) {
|
||||
|
||||
if (depth->value.data[0] == '0') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (depth->value.data[0] == '1') {
|
||||
return 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (depth->value.len == sizeof("infinity") - 1 &&
|
||||
ngx_strcmp(depth->value.data, "infinity") == 0) {
|
||||
return NGX_MAX_INT_T_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||
"client sent invalid \"Depth\" header: \"%V\"", &depth->value);
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_dav_location(ngx_http_request_t *r)
|
||||
{
|
||||
u_char *p;
|
||||
size_t len;
|
||||
uintptr_t escape;
|
||||
|
||||
r->headers_out.location = ngx_list_push(&r->headers_out.headers);
|
||||
if (r->headers_out.location == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
r->headers_out.location->hash = 1;
|
||||
r->headers_out.location->next = NULL;
|
||||
ngx_str_set(&r->headers_out.location->key, "Location");
|
||||
|
||||
escape = 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len, NGX_ESCAPE_URI);
|
||||
|
||||
if (escape) {
|
||||
len = r->uri.len + escape;
|
||||
|
||||
p = ngx_pnalloc(r->pool, len);
|
||||
if (p == NULL) {
|
||||
ngx_http_clear_location(r);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
r->headers_out.location->value.len = len;
|
||||
r->headers_out.location->value.data = p;
|
||||
|
||||
ngx_escape_uri(p, r->uri.data, r->uri.len, NGX_ESCAPE_URI);
|
||||
|
||||
} else {
|
||||
r->headers_out.location->value = r->uri;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
uint32_t ngx_http_dav_ext_if(ngx_http_request_t *r, ngx_str_t *uri) {
|
||||
u_char *p, ch;
|
||||
uint32_t token;
|
||||
ngx_str_t tag;
|
||||
ngx_uint_t i, n;
|
||||
ngx_list_part_t *part;
|
||||
ngx_table_elt_t *header;
|
||||
|
||||
static u_char name[] = "if";
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http dav_ext if \"%V\"", uri);
|
||||
|
||||
part = &r->headers_in.headers.part;
|
||||
header = part->elts;
|
||||
|
||||
for (i = 0; /* void */; i++) {
|
||||
|
||||
if (i >= part->nelts) {
|
||||
if (part->next == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
part = part->next;
|
||||
header = part->elts;
|
||||
i = 0;
|
||||
}
|
||||
|
||||
for (n = 0; n < sizeof(name) - 1 && n < header[i].key.len; n++) {
|
||||
ch = header[i].key.data[n];
|
||||
|
||||
if (ch >= 'A' && ch <= 'Z') {
|
||||
ch |= 0x20;
|
||||
}
|
||||
|
||||
if (name[n] != ch) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (n == sizeof(name) - 1 && n == header[i].key.len) {
|
||||
p = header[i].value.data;
|
||||
tag = r->uri;
|
||||
|
||||
while (*p != '\0') {
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http dav_ext if list \"%s\"", p);
|
||||
|
||||
while (*p == ' ') {
|
||||
p++;
|
||||
}
|
||||
|
||||
if (*p == '<') {
|
||||
tag.data = ++p;
|
||||
|
||||
while (*p != '\0' && *p != '>') {
|
||||
p++;
|
||||
}
|
||||
|
||||
if (*p == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
tag.len = p++ - tag.data;
|
||||
|
||||
(void)ngx_http_dav_ext_strip_uri(r, &tag);
|
||||
|
||||
while (*p == ' ') {
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
if (*p != '(') {
|
||||
break;
|
||||
}
|
||||
|
||||
p++;
|
||||
|
||||
if (tag.len == 0 || tag.len > uri->len ||
|
||||
(tag.len < uri->len && tag.data[tag.len - 1] != '/') ||
|
||||
ngx_memcmp(tag.data, uri->data, tag.len)) {
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http dav_ext if tag mismatch \"%V\"", &tag);
|
||||
|
||||
while (*p != '\0' && *p != ')') {
|
||||
p++;
|
||||
}
|
||||
|
||||
if (*p == ')') {
|
||||
p++;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
while (*p != '\0') {
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http dav_ext if condition \"%s\"", p);
|
||||
|
||||
while (*p == ' ') {
|
||||
p++;
|
||||
}
|
||||
|
||||
if (ngx_strncmp(p, "Not", 3) == 0) {
|
||||
p += 3;
|
||||
while (*p == ' ') {
|
||||
p++;
|
||||
}
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (*p == '[') {
|
||||
p++;
|
||||
while (*p != '\0' && *p != ']') {
|
||||
p++;
|
||||
}
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (ngx_strncmp(p, "<urn:", 5)) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
p += 5;
|
||||
token = 0;
|
||||
|
||||
for (n = 0; n < 8; n++) {
|
||||
ch = *p++;
|
||||
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
token = token * 16 + (ch - '0');
|
||||
continue;
|
||||
}
|
||||
|
||||
ch = (u_char)(ch | 0x20);
|
||||
|
||||
if (ch >= 'a' && ch <= 'f') {
|
||||
token = token * 16 + (ch - 'a' + 10);
|
||||
continue;
|
||||
}
|
||||
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (*p != '>') {
|
||||
goto next;
|
||||
}
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http dav_ext if token: %uxD", token);
|
||||
|
||||
return token;
|
||||
|
||||
next:
|
||||
|
||||
while (*p != '\0' && *p != ' ' && *p != ')') {
|
||||
p++;
|
||||
}
|
||||
|
||||
if (*p == ')') {
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http dav_ext if header mismatch");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ngx_http_dav_ext_node_t *
|
||||
ngx_http_dav_ext_lock_lookup(ngx_http_request_t *r,
|
||||
ngx_http_dav_ext_lock_t *lock, ngx_str_t *uri,
|
||||
ngx_int_t depth) {
|
||||
time_t now;
|
||||
ngx_queue_t *q;
|
||||
ngx_http_dav_ext_node_t *node;
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http dav_ext lock lookup \"%V\"", uri);
|
||||
|
||||
if (uri->len == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
now = ngx_time();
|
||||
|
||||
while (!ngx_queue_empty(&lock->sh->queue)) {
|
||||
q = ngx_queue_head(&lock->sh->queue);
|
||||
node = (ngx_http_dav_ext_node_t *)q;
|
||||
|
||||
if (node->expire >= now) {
|
||||
break;
|
||||
}
|
||||
|
||||
ngx_queue_remove(q);
|
||||
ngx_slab_free_locked(lock->shpool, node);
|
||||
}
|
||||
|
||||
for (q = ngx_queue_head(&lock->sh->queue);
|
||||
q != ngx_queue_sentinel(&lock->sh->queue); q = ngx_queue_next(q)) {
|
||||
node = (ngx_http_dav_ext_node_t *)q;
|
||||
|
||||
if (uri->len >= node->len) {
|
||||
if (ngx_memcmp(uri->data, node->data, node->len)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uri->len > node->len) {
|
||||
if (node->data[node->len - 1] != '/') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!node->infinite &&
|
||||
ngx_strlchr(uri->data + node->len, uri->data + uri->len - 1, '/')) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http dav_ext lock found \"%*s\"", node->len, node->data);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/* uri->len < node->len */
|
||||
|
||||
if (depth >= 0) {
|
||||
if (ngx_memcmp(node->data, uri->data, uri->len)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uri->data[uri->len - 1] != '/') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (depth == 0 &&
|
||||
ngx_strlchr(node->data + uri->len, node->data + node->len - 1, '/')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http dav_ext lock found \"%*s\"", node->len, node->data);
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http dav_ext lock not found");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
uintptr_t
|
||||
ngx_http_dav_ext_format_lockdiscovery(ngx_http_request_t *r, u_char *dst,
|
||||
ngx_http_dav_ext_entry_t *entry) {
|
||||
size_t len;
|
||||
time_t now;
|
||||
|
||||
if (dst == NULL) {
|
||||
if (entry->lock_token == 0) {
|
||||
return sizeof("<D:lockdiscovery/>\n") - 1;
|
||||
}
|
||||
|
||||
len = sizeof("<D:lockdiscovery>\n"
|
||||
"<D:activelock>\n"
|
||||
"<D:locktype><D:write/></D:locktype>\n"
|
||||
"<D:lockscope><D:exclusive/></D:lockscope>\n"
|
||||
"<D:depth>infinity</D:depth>\n"
|
||||
"<D:timeout>Second-</D:timeout>\n"
|
||||
"<D:locktoken><D:href></D:href></D:locktoken>\n"
|
||||
"<D:lockroot><D:href></D:href></D:lockroot>\n"
|
||||
"</D:activelock>\n"
|
||||
"</D:lockdiscovery>\n") -
|
||||
1;
|
||||
|
||||
/* timeout */
|
||||
len += NGX_TIME_T_LEN;
|
||||
|
||||
/* token */
|
||||
len += ngx_http_dav_ext_format_token(NULL, entry->lock_token, 0);
|
||||
|
||||
/* lockroot */
|
||||
len += entry->lock_root.len +
|
||||
ngx_escape_html(NULL, entry->lock_root.data, entry->lock_root.len);
|
||||
return len;
|
||||
}
|
||||
|
||||
if (entry->lock_token == 0) {
|
||||
dst = ngx_cpymem(dst, "<D:lockdiscovery/>\n",
|
||||
sizeof("<D:lockdiscovery/>\n") - 1);
|
||||
return (uintptr_t)dst;
|
||||
}
|
||||
|
||||
now = ngx_time();
|
||||
|
||||
dst =
|
||||
ngx_cpymem(dst, "<D:lockdiscovery>\n", sizeof("<D:lockdiscovery>\n") - 1);
|
||||
|
||||
dst = ngx_cpymem(dst, "<D:activelock>\n", sizeof("<D:activelock>\n") - 1);
|
||||
|
||||
dst = ngx_cpymem(dst, "<D:locktype><D:write/></D:locktype>\n",
|
||||
sizeof("<D:locktype><D:write/></D:locktype>\n") - 1);
|
||||
|
||||
dst = ngx_cpymem(dst, "<D:lockscope><D:exclusive/></D:lockscope>\n",
|
||||
sizeof("<D:lockscope><D:exclusive/></D:lockscope>\n") - 1);
|
||||
|
||||
dst = ngx_sprintf(dst, "<D:depth>%s</D:depth>\n",
|
||||
entry->lock_infinite ? "infinity" : "0");
|
||||
|
||||
dst = ngx_sprintf(dst, "<D:timeout>Second-%T</D:timeout>\n",
|
||||
entry->lock_expire - now);
|
||||
|
||||
dst = ngx_cpymem(dst, "<D:locktoken><D:href>",
|
||||
sizeof("<D:locktoken><D:href>") - 1);
|
||||
dst = (u_char *)ngx_http_dav_ext_format_token(dst, entry->lock_token, 0);
|
||||
dst = ngx_cpymem(dst, "</D:href></D:locktoken>\n",
|
||||
sizeof("</D:href></D:locktoken>\n") - 1);
|
||||
|
||||
dst = ngx_cpymem(dst, "<D:lockroot><D:href>",
|
||||
sizeof("<D:lockroot><D:href>") - 1);
|
||||
dst = (u_char *)ngx_escape_html(dst, entry->lock_root.data,
|
||||
entry->lock_root.len);
|
||||
dst = ngx_cpymem(dst, "</D:href></D:lockroot>\n",
|
||||
sizeof("</D:href></D:lockroot>\n") - 1);
|
||||
|
||||
dst = ngx_cpymem(dst, "</D:activelock>\n", sizeof("</D:activelock>\n") - 1);
|
||||
|
||||
dst = ngx_cpymem(dst, "</D:lockdiscovery>\n",
|
||||
sizeof("</D:lockdiscovery>\n") - 1);
|
||||
|
||||
return (uintptr_t)dst;
|
||||
}
|
||||
|
||||
|
||||
uintptr_t ngx_http_dav_ext_format_token(u_char *dst, uint32_t token,
|
||||
ngx_uint_t brackets) {
|
||||
ngx_uint_t n;
|
||||
|
||||
static u_char hex[] = "0123456789abcdef";
|
||||
|
||||
if (dst == NULL) {
|
||||
return sizeof("<urn:deadbeef>") - 1 + (brackets ? 2 : 0);
|
||||
}
|
||||
|
||||
if (brackets) {
|
||||
*dst++ = '<';
|
||||
}
|
||||
|
||||
dst = ngx_cpymem(dst, "urn:", 4);
|
||||
|
||||
for (n = 0; n < 4; n++) {
|
||||
*dst++ = hex[token >> 28];
|
||||
*dst++ = hex[(token >> 24) & 0xf];
|
||||
token <<= 8;
|
||||
}
|
||||
|
||||
if (brackets) {
|
||||
*dst++ = '>';
|
||||
}
|
||||
|
||||
return (uintptr_t)dst;
|
||||
}
|
||||
78
ngx_http_webdav_utils.h
Normal file
78
ngx_http_webdav_utils.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) Starfields
|
||||
*/
|
||||
|
||||
#include <ngx_http.h>
|
||||
|
||||
#ifndef NGX_HTTP_DAV_EXT_CONF_H
|
||||
#define NGX_HTTP_DAV_EXT_CONF_H
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_str_t uri;
|
||||
ngx_str_t name;
|
||||
time_t mtime;
|
||||
off_t size;
|
||||
|
||||
time_t lock_expire;
|
||||
ngx_str_t lock_root;
|
||||
uint32_t lock_token;
|
||||
|
||||
unsigned dir : 1;
|
||||
unsigned lock_supported : 1;
|
||||
unsigned lock_infinite : 1;
|
||||
} ngx_http_dav_ext_entry_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_queue_t queue;
|
||||
} ngx_http_dav_ext_lock_sh_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
time_t timeout;
|
||||
ngx_slab_pool_t *shpool;
|
||||
ngx_http_dav_ext_lock_sh_t *sh;
|
||||
} ngx_http_dav_ext_lock_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ngx_queue_t queue;
|
||||
uint32_t token;
|
||||
time_t expire;
|
||||
ngx_uint_t infinite; /* unsigned infinite:1; */
|
||||
size_t len;
|
||||
u_char data[1];
|
||||
} ngx_http_dav_ext_node_t;
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_dav_delete_path(ngx_http_request_t *r, ngx_str_t *path, ngx_uint_t dir);
|
||||
ngx_int_t ensure_trailing_slash(ngx_http_request_t *r, ngx_str_t *uri);
|
||||
ngx_int_t ngx_http_dav_depth(ngx_http_request_t *r,
|
||||
ngx_int_t default_depth);
|
||||
ngx_int_t ngx_http_dav_ext_depth(ngx_http_request_t *r,
|
||||
ngx_int_t default_depth);
|
||||
ngx_int_t ngx_http_dav_location(ngx_http_request_t *r);
|
||||
ngx_int_t
|
||||
ngx_http_dav_error(ngx_log_t *log, ngx_err_t err, ngx_int_t not_found,
|
||||
char *failed, u_char *path);
|
||||
uint32_t ngx_http_dav_ext_if(ngx_http_request_t *r, ngx_str_t *uri);
|
||||
ngx_http_dav_ext_node_t *
|
||||
ngx_http_dav_ext_lock_lookup(ngx_http_request_t *r,
|
||||
ngx_http_dav_ext_lock_t *lock, ngx_str_t *uri,
|
||||
ngx_int_t depth);
|
||||
ngx_int_t ngx_http_dav_ext_set_locks(ngx_http_request_t *r,
|
||||
ngx_http_dav_ext_entry_t *entry);
|
||||
uintptr_t
|
||||
ngx_http_dav_ext_format_lockdiscovery(ngx_http_request_t *r, u_char *dst,
|
||||
ngx_http_dav_ext_entry_t *entry);
|
||||
uintptr_t ngx_http_dav_ext_format_token(u_char *dst, uint32_t token,
|
||||
ngx_uint_t brackets);
|
||||
ngx_int_t ngx_http_dav_ext_strip_uri(ngx_http_request_t *r,
|
||||
ngx_str_t *uri);
|
||||
ngx_int_t
|
||||
ngx_http_dav_noop(ngx_tree_ctx_t *ctx, ngx_str_t *path);
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user