Mercurial > hg > nginx
annotate src/http/modules/ngx_http_dav_module.c @ 4247:b79dbadb3d5e stable-1.0
Merging r4147, r4148, r4149, r4150, r4207:
Fixes of combination of error_page and return directives:
*) Fix for incorrect 201 replies from dav module.
Replies with 201 code contain body, and we should clearly indicate it's
empty if it's empty. Before 0.8.32 chunked was explicitly disabled for
201 replies and as a result empty body was indicated by connection close
(not perfect, but worked). Since 0.8.32 chunked is enabled, and this
causes incorrect responses from dav module when HTTP/1.1 is used: with
"Transfer-Encoding: chunked" but no chunks at all.
Fix is to actually return empty body in special response handler instead
of abusing r->header_only flag.
See here for initial report:
http://mailman.nginx.org/pipermail/nginx-ru/2010-October/037535.html
*) Fix for double content when return is used in error_page handler.
Test case:
location / {
error_page 405 /nope;
return 405;
}
location /nope {
return 200;
}
This is expected to return 405 with empty body, but in 0.8.42+ will return
builtin 405 error page as well (though not counted in Content-Length, thus
breaking protocol).
Fix is to use status provided by rewrite script execution in case
it's less than NGX_HTTP_BAD_REQUEST even if r->error_status set. This
check is in line with one in ngx_http_script_return_code().
Note that this patch also changes behaviour for "return 302 ..." and
"rewrite ... redirect" used as error handler. E.g.
location / {
error_page 405 /redirect;
return 405;
}
location /redirect {
rewrite ^ http://example.com/;
}
will actually return redirect to "http://example.com/" instead of builtin
405 error page with meaningless Location header. This looks like correct
change and it's in line with what happens on e.g. directory redirects
in error handlers.
*) Fix for "return 202" not discarding body.
Big POST (not fully preread) to a
location / {
return 202;
}
resulted in incorrect behaviour due to "return" code path not calling
ngx_http_discard_request_body(). The same applies to all "return" used
with 2xx/3xx codes except 201 and 204, and to all "return ... text" uses.
Fix is to add ngx_http_discard_request_body() call to
ngx_http_send_response() function where it looks appropriate.
Discard body call from emtpy gif module removed as it's now redundant.
Reported by Pyry Hakulinen, see
http://mailman.nginx.org/pipermail/nginx/2011-August/028503.html
*) Incorrect special case for "return 204" removed.
The special case in question leads to replies without body in
configuration like
location / { error_page 404 /zero; return 404; }
location /zero { return 204; }
while replies with empty body are expected per protocol specs.
Correct one will look like
if (status == NGX_HTTP_NO_CONTENT) {
rc = ngx_http_send_header(r);
if (rc == NGX_ERROR || r->header_only) {
return rc;
}
return ngx_http_send_special(r, NGX_HTTP_LAST);
}
though it looks like it's better to drop this special case at all.
*) Clear old Location header (if any) while adding a new one.
This prevents incorrect behaviour when another redirect is issued within
error_page 302 handler.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 01 Nov 2011 13:45:33 +0000 |
parents | d3568507db51 |
children | d620f497c50f |
rev | line source |
---|---|
633 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_http.h> | |
10 | |
11 | |
1116 | 12 #define NGX_HTTP_DAV_COPY_BLOCK 65536 |
13 | |
14 #define NGX_HTTP_DAV_OFF 2 | |
15 | |
16 | |
17 #define NGX_HTTP_DAV_NO_DEPTH -3 | |
18 #define NGX_HTTP_DAV_INVALID_DEPTH -2 | |
19 #define NGX_HTTP_DAV_INFINITY_DEPTH -1 | |
20 | |
633 | 21 |
22 typedef struct { | |
23 ngx_uint_t methods; | |
1816 | 24 ngx_uint_t access; |
25 ngx_uint_t min_delete_depth; | |
637 | 26 ngx_flag_t create_full_put_path; |
633 | 27 } ngx_http_dav_loc_conf_t; |
28 | |
29 | |
1116 | 30 typedef struct { |
31 ngx_str_t path; | |
32 size_t len; | |
33 } ngx_http_dav_copy_ctx_t; | |
34 | |
35 | |
633 | 36 static ngx_int_t ngx_http_dav_handler(ngx_http_request_t *r); |
1116 | 37 |
38 static void ngx_http_dav_put_handler(ngx_http_request_t *r); | |
39 | |
40 static ngx_int_t ngx_http_dav_delete_handler(ngx_http_request_t *r); | |
1820 | 41 static ngx_int_t ngx_http_dav_delete_path(ngx_http_request_t *r, |
42 ngx_str_t *path, ngx_uint_t dir); | |
957 | 43 static ngx_int_t ngx_http_dav_delete_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path); |
44 static ngx_int_t ngx_http_dav_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path); | |
1820 | 45 static ngx_int_t ngx_http_dav_noop(ngx_tree_ctx_t *ctx, ngx_str_t *path); |
1116 | 46 |
47 static ngx_int_t ngx_http_dav_mkcol_handler(ngx_http_request_t *r, | |
48 ngx_http_dav_loc_conf_t *dlcf); | |
49 | |
50 static ngx_int_t ngx_http_dav_copy_move_handler(ngx_http_request_t *r); | |
51 static ngx_int_t ngx_http_dav_copy_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path); | |
52 static ngx_int_t ngx_http_dav_copy_dir_time(ngx_tree_ctx_t *ctx, | |
53 ngx_str_t *path); | |
1825
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
54 static ngx_int_t ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx, |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
55 ngx_str_t *path); |
1116 | 56 |
57 static ngx_int_t ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt); | |
58 static ngx_int_t ngx_http_dav_error(ngx_log_t *log, ngx_err_t err, | |
637 | 59 ngx_int_t not_found, char *failed, u_char *path); |
60 static ngx_int_t ngx_http_dav_location(ngx_http_request_t *r, u_char *path); | |
633 | 61 static void *ngx_http_dav_create_loc_conf(ngx_conf_t *cf); |
62 static char *ngx_http_dav_merge_loc_conf(ngx_conf_t *cf, | |
63 void *parent, void *child); | |
681 | 64 static ngx_int_t ngx_http_dav_init(ngx_conf_t *cf); |
633 | 65 |
66 | |
67 static ngx_conf_bitmask_t ngx_http_dav_methods_mask[] = { | |
68 { ngx_string("off"), NGX_HTTP_DAV_OFF }, | |
69 { ngx_string("put"), NGX_HTTP_PUT }, | |
70 { ngx_string("delete"), NGX_HTTP_DELETE }, | |
637 | 71 { ngx_string("mkcol"), NGX_HTTP_MKCOL }, |
1116 | 72 { ngx_string("copy"), NGX_HTTP_COPY }, |
73 { ngx_string("move"), NGX_HTTP_MOVE }, | |
633 | 74 { ngx_null_string, 0 } |
75 }; | |
76 | |
77 | |
78 static ngx_command_t ngx_http_dav_commands[] = { | |
79 | |
80 { ngx_string("dav_methods"), | |
81 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | |
82 ngx_conf_set_bitmask_slot, | |
83 NGX_HTTP_LOC_CONF_OFFSET, | |
84 offsetof(ngx_http_dav_loc_conf_t, methods), | |
85 &ngx_http_dav_methods_mask }, | |
86 | |
637 | 87 { ngx_string("create_full_put_path"), |
88 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
89 ngx_conf_set_flag_slot, | |
90 NGX_HTTP_LOC_CONF_OFFSET, | |
91 offsetof(ngx_http_dav_loc_conf_t, create_full_put_path), | |
92 NULL }, | |
93 | |
1816 | 94 { ngx_string("min_delete_depth"), |
95 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
96 ngx_conf_set_num_slot, | |
97 NGX_HTTP_LOC_CONF_OFFSET, | |
98 offsetof(ngx_http_dav_loc_conf_t, min_delete_depth), | |
99 NULL }, | |
100 | |
669 | 101 { ngx_string("dav_access"), |
675 | 102 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123, |
1296
9fcfca54b208
dav_access uses ngx_conf_set_access_slot()
Igor Sysoev <igor@sysoev.ru>
parents:
1289
diff
changeset
|
103 ngx_conf_set_access_slot, |
669 | 104 NGX_HTTP_LOC_CONF_OFFSET, |
1296
9fcfca54b208
dav_access uses ngx_conf_set_access_slot()
Igor Sysoev <igor@sysoev.ru>
parents:
1289
diff
changeset
|
105 offsetof(ngx_http_dav_loc_conf_t, access), |
669 | 106 NULL }, |
107 | |
633 | 108 ngx_null_command |
109 }; | |
110 | |
111 | |
667 | 112 static ngx_http_module_t ngx_http_dav_module_ctx = { |
633 | 113 NULL, /* preconfiguration */ |
681 | 114 ngx_http_dav_init, /* postconfiguration */ |
633 | 115 |
116 NULL, /* create main configuration */ | |
117 NULL, /* init main configuration */ | |
118 | |
119 NULL, /* create server configuration */ | |
120 NULL, /* merge server configuration */ | |
121 | |
122 ngx_http_dav_create_loc_conf, /* create location configuration */ | |
123 ngx_http_dav_merge_loc_conf /* merge location configuration */ | |
124 }; | |
125 | |
126 | |
127 ngx_module_t ngx_http_dav_module = { | |
128 NGX_MODULE_V1, | |
129 &ngx_http_dav_module_ctx, /* module context */ | |
130 ngx_http_dav_commands, /* module directives */ | |
131 NGX_HTTP_MODULE, /* module type */ | |
132 NULL, /* init master */ | |
681 | 133 NULL, /* init module */ |
633 | 134 NULL, /* init process */ |
135 NULL, /* init thread */ | |
136 NULL, /* exit thread */ | |
137 NULL, /* exit process */ | |
138 NULL, /* exit master */ | |
139 NGX_MODULE_V1_PADDING | |
140 }; | |
141 | |
142 | |
143 static ngx_int_t | |
144 ngx_http_dav_handler(ngx_http_request_t *r) | |
145 { | |
146 ngx_int_t rc; | |
147 ngx_http_dav_loc_conf_t *dlcf; | |
148 | |
149 dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module); | |
150 | |
151 if (!(r->method & dlcf->methods)) { | |
152 return NGX_DECLINED; | |
153 } | |
154 | |
155 switch (r->method) { | |
156 | |
157 case NGX_HTTP_PUT: | |
158 | |
159 if (r->uri.data[r->uri.len - 1] == '/') { | |
1813
d3f80e0be8fa
change status code and add log message
Igor Sysoev <igor@sysoev.ru>
parents:
1804
diff
changeset
|
160 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
4246
d3568507db51
Merging r4132, r4134, r4143, r4183, r4191, r4199:
Igor Sysoev <igor@sysoev.ru>
parents:
3612
diff
changeset
|
161 "cannot PUT to a collection"); |
1813
d3f80e0be8fa
change status code and add log message
Igor Sysoev <igor@sysoev.ru>
parents:
1804
diff
changeset
|
162 return NGX_HTTP_CONFLICT; |
633 | 163 } |
164 | |
165 r->request_body_in_file_only = 1; | |
166 r->request_body_in_persistent_file = 1; | |
1075
4d203f76b757
undo "client_body_in_file_only any"
Igor Sysoev <igor@sysoev.ru>
parents:
1060
diff
changeset
|
167 r->request_body_in_clean_file = 1; |
633 | 168 r->request_body_file_group_access = 1; |
637 | 169 r->request_body_file_log_level = 0; |
633 | 170 |
171 rc = ngx_http_read_client_request_body(r, ngx_http_dav_put_handler); | |
172 | |
173 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { | |
174 return rc; | |
175 } | |
176 | |
177 return NGX_DONE; | |
178 | |
179 case NGX_HTTP_DELETE: | |
180 | |
1116 | 181 return ngx_http_dav_delete_handler(r); |
637 | 182 |
183 case NGX_HTTP_MKCOL: | |
184 | |
1116 | 185 return ngx_http_dav_mkcol_handler(r, dlcf); |
637 | 186 |
1116 | 187 case NGX_HTTP_COPY: |
637 | 188 |
1116 | 189 return ngx_http_dav_copy_move_handler(r); |
637 | 190 |
1116 | 191 case NGX_HTTP_MOVE: |
637 | 192 |
1116 | 193 return ngx_http_dav_copy_move_handler(r); |
633 | 194 } |
195 | |
196 return NGX_DECLINED; | |
197 } | |
198 | |
199 | |
200 static void | |
201 ngx_http_dav_put_handler(ngx_http_request_t *r) | |
202 { | |
773 | 203 size_t root; |
681 | 204 time_t date; |
637 | 205 ngx_str_t *temp, path; |
1828
1f3c2b6607e0
use ngx_ext_rename_file() in PUT
Igor Sysoev <igor@sysoev.ru>
parents:
1825
diff
changeset
|
206 ngx_uint_t status; |
637 | 207 ngx_file_info_t fi; |
1828
1f3c2b6607e0
use ngx_ext_rename_file() in PUT
Igor Sysoev <igor@sysoev.ru>
parents:
1825
diff
changeset
|
208 ngx_ext_rename_file_t ext; |
637 | 209 ngx_http_dav_loc_conf_t *dlcf; |
633 | 210 |
773 | 211 ngx_http_map_uri_to_path(r, &path, &root, 0); |
633 | 212 |
3032
524ba56ba9f7
fix copy destination name length, introduced in r3025
Igor Sysoev <igor@sysoev.ru>
parents:
3024
diff
changeset
|
213 path.len--; |
524ba56ba9f7
fix copy destination name length, introduced in r3025
Igor Sysoev <igor@sysoev.ru>
parents:
3024
diff
changeset
|
214 |
633 | 215 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
216 "http put filename: \"%s\"", path.data); | |
217 | |
218 temp = &r->request_body->temp_file->file.name; | |
219 | |
2782
4bd7825fab80
uniform ngx_file_info() interface with ngx_fd_info()
Igor Sysoev <igor@sysoev.ru>
parents:
2721
diff
changeset
|
220 if (ngx_file_info(path.data, &fi) == NGX_FILE_ERROR) { |
633 | 221 status = NGX_HTTP_CREATED; |
222 | |
223 } else { | |
224 status = NGX_HTTP_NO_CONTENT; | |
663 | 225 |
226 if (ngx_is_dir(&fi)) { | |
227 ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_EISDIR, | |
228 "\"%s\" could not be created", path.data); | |
633 | 229 |
663 | 230 if (ngx_delete_file(temp->data) == NGX_FILE_ERROR) { |
231 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, | |
232 ngx_delete_file_n " \"%s\" failed", | |
233 temp->data); | |
234 } | |
235 | |
236 ngx_http_finalize_request(r, NGX_HTTP_CONFLICT); | |
237 return; | |
661 | 238 } |
637 | 239 } |
240 | |
669 | 241 dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module); |
242 | |
1828
1f3c2b6607e0
use ngx_ext_rename_file() in PUT
Igor Sysoev <igor@sysoev.ru>
parents:
1825
diff
changeset
|
243 ext.access = dlcf->access; |
2394
dbe746851b31
use ngx_ext_rename_file() for single file MOVE
Igor Sysoev <igor@sysoev.ru>
parents:
2049
diff
changeset
|
244 ext.path_access = dlcf->access; |
1828
1f3c2b6607e0
use ngx_ext_rename_file() in PUT
Igor Sysoev <igor@sysoev.ru>
parents:
1825
diff
changeset
|
245 ext.time = -1; |
1f3c2b6607e0
use ngx_ext_rename_file() in PUT
Igor Sysoev <igor@sysoev.ru>
parents:
1825
diff
changeset
|
246 ext.create_path = dlcf->create_full_put_path; |
1909 | 247 ext.delete_file = 1; |
1828
1f3c2b6607e0
use ngx_ext_rename_file() in PUT
Igor Sysoev <igor@sysoev.ru>
parents:
1825
diff
changeset
|
248 ext.log = r->connection->log; |
669 | 249 |
681 | 250 if (r->headers_in.date) { |
251 date = ngx_http_parse_time(r->headers_in.date->value.data, | |
252 r->headers_in.date->value.len); | |
253 | |
254 if (date != NGX_ERROR) { | |
1828
1f3c2b6607e0
use ngx_ext_rename_file() in PUT
Igor Sysoev <igor@sysoev.ru>
parents:
1825
diff
changeset
|
255 ext.time = date; |
1f3c2b6607e0
use ngx_ext_rename_file() in PUT
Igor Sysoev <igor@sysoev.ru>
parents:
1825
diff
changeset
|
256 ext.fd = r->request_body->temp_file->file.fd; |
681 | 257 } |
258 } | |
259 | |
1828
1f3c2b6607e0
use ngx_ext_rename_file() in PUT
Igor Sysoev <igor@sysoev.ru>
parents:
1825
diff
changeset
|
260 if (ngx_ext_rename_file(temp, &path, &ext) != NGX_OK) { |
1f3c2b6607e0
use ngx_ext_rename_file() in PUT
Igor Sysoev <igor@sysoev.ru>
parents:
1825
diff
changeset
|
261 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
1f3c2b6607e0
use ngx_ext_rename_file() in PUT
Igor Sysoev <igor@sysoev.ru>
parents:
1825
diff
changeset
|
262 return; |
637 | 263 } |
264 | |
633 | 265 if (status == NGX_HTTP_CREATED) { |
637 | 266 if (ngx_http_dav_location(r, path.data) != NGX_OK) { |
633 | 267 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
268 return; | |
269 } | |
639 | 270 |
271 r->headers_out.content_length_n = 0; | |
633 | 272 } |
273 | |
274 r->headers_out.status = status; | |
275 r->header_only = 1; | |
276 | |
277 ngx_http_finalize_request(r, ngx_http_send_header(r)); | |
278 return; | |
279 } | |
280 | |
281 | |
637 | 282 static ngx_int_t |
1116 | 283 ngx_http_dav_delete_handler(ngx_http_request_t *r) |
284 { | |
1816 | 285 size_t root; |
286 ngx_err_t err; | |
287 ngx_int_t rc, depth; | |
288 ngx_uint_t i, d, dir; | |
289 ngx_str_t path; | |
290 ngx_file_info_t fi; | |
291 ngx_http_dav_loc_conf_t *dlcf; | |
1116 | 292 |
293 if (r->headers_in.content_length_n > 0) { | |
1815 | 294 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
295 "DELETE with body is unsupported"); | |
1116 | 296 return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE; |
297 } | |
298 | |
1816 | 299 dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module); |
300 | |
301 if (dlcf->min_delete_depth) { | |
302 d = 0; | |
303 | |
304 for (i = 0; i < r->uri.len; /* void */) { | |
305 if (r->uri.data[i++] == '/') { | |
306 if (++d >= dlcf->min_delete_depth && i < r->uri.len) { | |
307 goto ok; | |
308 } | |
309 } | |
310 } | |
311 | |
312 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
313 "insufficient URI depth:%i to DELETE", d); | |
314 return NGX_HTTP_CONFLICT; | |
315 } | |
316 | |
317 ok: | |
318 | |
1116 | 319 ngx_http_map_uri_to_path(r, &path, &root, 0); |
320 | |
321 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
322 "http delete filename: \"%s\"", path.data); | |
323 | |
3501
423ff11e3018
use lstat() for WebDAV DELETE, COPY, and MOVE to handle symlinks
Igor Sysoev <igor@sysoev.ru>
parents:
3182
diff
changeset
|
324 if (ngx_link_info(path.data, &fi) == NGX_FILE_ERROR) { |
1815 | 325 err = ngx_errno; |
326 | |
327 rc = (err == NGX_ENOTDIR) ? NGX_HTTP_CONFLICT : NGX_HTTP_NOT_FOUND; | |
328 | |
329 return ngx_http_dav_error(r->connection->log, err, | |
3501
423ff11e3018
use lstat() for WebDAV DELETE, COPY, and MOVE to handle symlinks
Igor Sysoev <igor@sysoev.ru>
parents:
3182
diff
changeset
|
330 rc, ngx_link_info_n, path.data); |
1116 | 331 } |
332 | |
333 if (ngx_is_dir(&fi)) { | |
334 | |
335 if (r->uri.data[r->uri.len - 1] != '/') { | |
1815 | 336 ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_EISDIR, |
337 "DELETE \"%s\" failed", path.data); | |
338 return NGX_HTTP_CONFLICT; | |
1116 | 339 } |
340 | |
341 depth = ngx_http_dav_depth(r, NGX_HTTP_DAV_INFINITY_DEPTH); | |
342 | |
343 if (depth != NGX_HTTP_DAV_INFINITY_DEPTH) { | |
1815 | 344 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
345 "\"Depth\" header must be infinity"); | |
1116 | 346 return NGX_HTTP_BAD_REQUEST; |
347 } | |
348 | |
349 path.len -= 2; /* omit "/\0" */ | |
350 | |
351 dir = 1; | |
352 | |
353 } else { | |
354 | |
1823 | 355 /* |
356 * we do not need to test (r->uri.data[r->uri.len - 1] == '/') | |
3501
423ff11e3018
use lstat() for WebDAV DELETE, COPY, and MOVE to handle symlinks
Igor Sysoev <igor@sysoev.ru>
parents:
3182
diff
changeset
|
357 * because ngx_link_info("/file/") returned NGX_ENOTDIR above |
1823 | 358 */ |
359 | |
1116 | 360 depth = ngx_http_dav_depth(r, 0); |
361 | |
362 if (depth != 0 && depth != NGX_HTTP_DAV_INFINITY_DEPTH) { | |
1815 | 363 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
364 "\"Depth\" header must be 0 or infinity"); | |
1116 | 365 return NGX_HTTP_BAD_REQUEST; |
366 } | |
367 | |
368 dir = 0; | |
369 } | |
370 | |
371 rc = ngx_http_dav_delete_path(r, &path, dir); | |
372 | |
373 if (rc == NGX_OK) { | |
374 return NGX_HTTP_NO_CONTENT; | |
375 } | |
376 | |
377 return rc; | |
378 } | |
379 | |
380 | |
381 static ngx_int_t | |
1820 | 382 ngx_http_dav_delete_path(ngx_http_request_t *r, ngx_str_t *path, ngx_uint_t dir) |
1116 | 383 { |
1820 | 384 char *failed; |
385 ngx_tree_ctx_t tree; | |
386 | |
387 if (dir) { | |
388 | |
389 tree.init_handler = NULL; | |
390 tree.file_handler = ngx_http_dav_delete_file; | |
391 tree.pre_tree_handler = ngx_http_dav_noop; | |
392 tree.post_tree_handler = ngx_http_dav_delete_dir; | |
393 tree.spec_handler = ngx_http_dav_delete_file; | |
394 tree.data = NULL; | |
395 tree.alloc = 0; | |
396 tree.log = r->connection->log; | |
397 | |
398 /* TODO: 207 */ | |
399 | |
400 if (ngx_walk_tree(&tree, path) != NGX_OK) { | |
401 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
402 } | |
403 | |
404 if (ngx_delete_dir(path->data) != NGX_FILE_ERROR) { | |
405 return NGX_OK; | |
406 } | |
407 | |
408 failed = ngx_delete_dir_n; | |
409 | |
410 } else { | |
411 | |
412 if (ngx_delete_file(path->data) != NGX_FILE_ERROR) { | |
413 return NGX_OK; | |
414 } | |
415 | |
416 failed = ngx_delete_file_n; | |
417 } | |
418 | |
419 return ngx_http_dav_error(r->connection->log, ngx_errno, | |
420 NGX_HTTP_NOT_FOUND, failed, path->data); | |
1116 | 421 } |
422 | |
423 | |
424 static ngx_int_t | |
425 ngx_http_dav_delete_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path) | |
426 { | |
427 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, | |
428 "http delete dir: \"%s\"", path->data); | |
429 | |
430 if (ngx_delete_dir(path->data) == NGX_FILE_ERROR) { | |
431 | |
432 /* TODO: add to 207 */ | |
433 | |
434 (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_delete_dir_n, | |
435 path->data); | |
436 } | |
437 | |
438 return NGX_OK; | |
439 } | |
440 | |
441 | |
442 static ngx_int_t | |
443 ngx_http_dav_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path) | |
444 { | |
445 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, | |
446 "http delete file: \"%s\"", path->data); | |
447 | |
448 if (ngx_delete_file(path->data) == NGX_FILE_ERROR) { | |
449 | |
450 /* TODO: add to 207 */ | |
451 | |
452 (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_delete_file_n, | |
453 path->data); | |
454 } | |
455 | |
456 return NGX_OK; | |
457 } | |
458 | |
459 | |
460 static ngx_int_t | |
1820 | 461 ngx_http_dav_noop(ngx_tree_ctx_t *ctx, ngx_str_t *path) |
462 { | |
463 return NGX_OK; | |
464 } | |
465 | |
466 | |
467 static ngx_int_t | |
1116 | 468 ngx_http_dav_mkcol_handler(ngx_http_request_t *r, ngx_http_dav_loc_conf_t *dlcf) |
469 { | |
1819
0f907513dd3c
change status code, add log message, and test collection URI
Igor Sysoev <igor@sysoev.ru>
parents:
1818
diff
changeset
|
470 u_char *p; |
1116 | 471 size_t root; |
472 ngx_str_t path; | |
473 | |
474 if (r->headers_in.content_length_n > 0) { | |
1819
0f907513dd3c
change status code, add log message, and test collection URI
Igor Sysoev <igor@sysoev.ru>
parents:
1818
diff
changeset
|
475 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
0f907513dd3c
change status code, add log message, and test collection URI
Igor Sysoev <igor@sysoev.ru>
parents:
1818
diff
changeset
|
476 "MKCOL with body is unsupported"); |
1116 | 477 return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE; |
478 } | |
479 | |
1819
0f907513dd3c
change status code, add log message, and test collection URI
Igor Sysoev <igor@sysoev.ru>
parents:
1818
diff
changeset
|
480 if (r->uri.data[r->uri.len - 1] != '/') { |
0f907513dd3c
change status code, add log message, and test collection URI
Igor Sysoev <igor@sysoev.ru>
parents:
1818
diff
changeset
|
481 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
0f907513dd3c
change status code, add log message, and test collection URI
Igor Sysoev <igor@sysoev.ru>
parents:
1818
diff
changeset
|
482 "MKCOL can create a collection only"); |
0f907513dd3c
change status code, add log message, and test collection URI
Igor Sysoev <igor@sysoev.ru>
parents:
1818
diff
changeset
|
483 return NGX_HTTP_CONFLICT; |
1116 | 484 } |
485 | |
1819
0f907513dd3c
change status code, add log message, and test collection URI
Igor Sysoev <igor@sysoev.ru>
parents:
1818
diff
changeset
|
486 p = ngx_http_map_uri_to_path(r, &path, &root, 0); |
0f907513dd3c
change status code, add log message, and test collection URI
Igor Sysoev <igor@sysoev.ru>
parents:
1818
diff
changeset
|
487 |
0f907513dd3c
change status code, add log message, and test collection URI
Igor Sysoev <igor@sysoev.ru>
parents:
1818
diff
changeset
|
488 *(p - 1) = '\0'; |
3182
6ddaac3e0bf7
omit '\0' from "Location" header on MKCOL request
Igor Sysoev <igor@sysoev.ru>
parents:
3161
diff
changeset
|
489 r->uri.len--; |
1116 | 490 |
491 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
492 "http mkcol path: \"%s\"", path.data); | |
493 | |
494 if (ngx_create_dir(path.data, ngx_dir_access(dlcf->access)) | |
495 != NGX_FILE_ERROR) | |
496 { | |
497 if (ngx_http_dav_location(r, path.data) != NGX_OK) { | |
498 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
499 } | |
500 | |
501 return NGX_HTTP_CREATED; | |
502 } | |
503 | |
504 return ngx_http_dav_error(r->connection->log, ngx_errno, | |
1819
0f907513dd3c
change status code, add log message, and test collection URI
Igor Sysoev <igor@sysoev.ru>
parents:
1818
diff
changeset
|
505 NGX_HTTP_CONFLICT, ngx_create_dir_n, path.data); |
1116 | 506 } |
507 | |
508 | |
509 static ngx_int_t | |
510 ngx_http_dav_copy_move_handler(ngx_http_request_t *r) | |
511 { | |
2007
b9de93d804ea
*) host in request line has priority
Igor Sysoev <igor@sysoev.ru>
parents:
1909
diff
changeset
|
512 u_char *p, *host, *last, ch; |
1804
d457a1576532
several changes in server_name:
Igor Sysoev <igor@sysoev.ru>
parents:
1803
diff
changeset
|
513 size_t len, root; |
1116 | 514 ngx_err_t err; |
515 ngx_int_t rc, depth; | |
3161 | 516 ngx_uint_t overwrite, slash, dir, flags; |
517 ngx_str_t path, uri, duri, args; | |
1116 | 518 ngx_tree_ctx_t tree; |
3024
8101d9101ed8
allow cross device temporary files atomic copying:
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
519 ngx_copy_file_t cf; |
1116 | 520 ngx_file_info_t fi; |
2007
b9de93d804ea
*) host in request line has priority
Igor Sysoev <igor@sysoev.ru>
parents:
1909
diff
changeset
|
521 ngx_table_elt_t *dest, *over; |
2394
dbe746851b31
use ngx_ext_rename_file() for single file MOVE
Igor Sysoev <igor@sysoev.ru>
parents:
2049
diff
changeset
|
522 ngx_ext_rename_file_t ext; |
1116 | 523 ngx_http_dav_copy_ctx_t copy; |
1825
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
524 ngx_http_dav_loc_conf_t *dlcf; |
1116 | 525 |
526 if (r->headers_in.content_length_n > 0) { | |
527 return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE; | |
528 } | |
529 | |
530 dest = r->headers_in.destination; | |
531 | |
532 if (dest == NULL) { | |
533 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
534 "client sent no \"Destination\" header"); | |
535 return NGX_HTTP_BAD_REQUEST; | |
536 } | |
537 | |
3612
f9a96545fee7
allow Destination URL without host
Igor Sysoev <igor@sysoev.ru>
parents:
3527
diff
changeset
|
538 p = dest->value.data; |
f9a96545fee7
allow Destination URL without host
Igor Sysoev <igor@sysoev.ru>
parents:
3527
diff
changeset
|
539 /* there is always '\0' even after empty header value */ |
f9a96545fee7
allow Destination URL without host
Igor Sysoev <igor@sysoev.ru>
parents:
3527
diff
changeset
|
540 if (p[0] == '/') { |
f9a96545fee7
allow Destination URL without host
Igor Sysoev <igor@sysoev.ru>
parents:
3527
diff
changeset
|
541 last = p + dest->value.len; |
f9a96545fee7
allow Destination URL without host
Igor Sysoev <igor@sysoev.ru>
parents:
3527
diff
changeset
|
542 goto destination_done; |
f9a96545fee7
allow Destination URL without host
Igor Sysoev <igor@sysoev.ru>
parents:
3527
diff
changeset
|
543 } |
f9a96545fee7
allow Destination URL without host
Igor Sysoev <igor@sysoev.ru>
parents:
3527
diff
changeset
|
544 |
2007
b9de93d804ea
*) host in request line has priority
Igor Sysoev <igor@sysoev.ru>
parents:
1909
diff
changeset
|
545 len = r->headers_in.server.len; |
1804
d457a1576532
several changes in server_name:
Igor Sysoev <igor@sysoev.ru>
parents:
1803
diff
changeset
|
546 |
2007
b9de93d804ea
*) host in request line has priority
Igor Sysoev <igor@sysoev.ru>
parents:
1909
diff
changeset
|
547 if (len == 0) { |
1804
d457a1576532
several changes in server_name:
Igor Sysoev <igor@sysoev.ru>
parents:
1803
diff
changeset
|
548 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
d457a1576532
several changes in server_name:
Igor Sysoev <igor@sysoev.ru>
parents:
1803
diff
changeset
|
549 "client sent no \"Host\" header"); |
d457a1576532
several changes in server_name:
Igor Sysoev <igor@sysoev.ru>
parents:
1803
diff
changeset
|
550 return NGX_HTTP_BAD_REQUEST; |
1116 | 551 } |
552 | |
553 #if (NGX_HTTP_SSL) | |
554 | |
555 if (r->connection->ssl) { | |
556 if (ngx_strncmp(dest->value.data, "https://", sizeof("https://") - 1) | |
557 != 0) | |
558 { | |
559 goto invalid_destination; | |
560 } | |
561 | |
2007
b9de93d804ea
*) host in request line has priority
Igor Sysoev <igor@sysoev.ru>
parents:
1909
diff
changeset
|
562 host = dest->value.data + sizeof("https://") - 1; |
1116 | 563 |
564 } else | |
565 #endif | |
566 { | |
567 if (ngx_strncmp(dest->value.data, "http://", sizeof("http://") - 1) | |
568 != 0) | |
569 { | |
570 goto invalid_destination; | |
571 } | |
572 | |
2007
b9de93d804ea
*) host in request line has priority
Igor Sysoev <igor@sysoev.ru>
parents:
1909
diff
changeset
|
573 host = dest->value.data + sizeof("http://") - 1; |
1116 | 574 } |
575 | |
2007
b9de93d804ea
*) host in request line has priority
Igor Sysoev <igor@sysoev.ru>
parents:
1909
diff
changeset
|
576 if (ngx_strncmp(host, r->headers_in.server.data, len) != 0) { |
1116 | 577 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
1822
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
578 "\"Destination\" URI \"%V\" is handled by " |
1116 | 579 "different repository than the source URI", |
580 &dest->value); | |
581 return NGX_HTTP_BAD_REQUEST; | |
582 } | |
583 | |
584 last = dest->value.data + dest->value.len; | |
585 | |
2007
b9de93d804ea
*) host in request line has priority
Igor Sysoev <igor@sysoev.ru>
parents:
1909
diff
changeset
|
586 for (p = host + len; p < last; p++) { |
1116 | 587 if (*p == '/') { |
588 goto destination_done; | |
589 } | |
590 } | |
591 | |
592 invalid_destination: | |
593 | |
594 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
595 "client sent invalid \"Destination\" header: \"%V\"", | |
596 &dest->value); | |
597 return NGX_HTTP_BAD_REQUEST; | |
598 | |
599 destination_done: | |
600 | |
3161 | 601 duri.len = last - p; |
602 duri.data = p; | |
603 flags = 0; | |
604 | |
605 if (ngx_http_parse_unsafe_uri(r, &duri, &args, &flags) != NGX_OK) { | |
606 goto invalid_destination; | |
607 } | |
608 | |
1822
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
609 if ((r->uri.data[r->uri.len - 1] == '/' && *(last - 1) != '/') |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
610 || (r->uri.data[r->uri.len - 1] != '/' && *(last - 1) == '/')) |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
611 { |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
612 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
613 "both URI \"%V\" and \"Destination\" URI \"%V\" " |
1834
aa343f669f11
style fix: remove trailing space
Igor Sysoev <igor@sysoev.ru>
parents:
1831
diff
changeset
|
614 "should be either collections or non-collections", |
1822
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
615 &r->uri, &dest->value); |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
616 return NGX_HTTP_CONFLICT; |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
617 } |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
618 |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
619 depth = ngx_http_dav_depth(r, NGX_HTTP_DAV_INFINITY_DEPTH); |
1116 | 620 |
1822
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
621 if (depth != NGX_HTTP_DAV_INFINITY_DEPTH) { |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
622 |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
623 if (r->method == NGX_HTTP_COPY) { |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
624 if (depth != 0) { |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
625 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
626 "\"Depth\" header must be 0 or infinity"); |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
627 return NGX_HTTP_BAD_REQUEST; |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
628 } |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
629 |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
630 } else { |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
631 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
632 "\"Depth\" header must be infinity"); |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
633 return NGX_HTTP_BAD_REQUEST; |
935427c55e04
test URI/Destination collection/non-collection and Depth
Igor Sysoev <igor@sysoev.ru>
parents:
1821
diff
changeset
|
634 } |
1116 | 635 } |
1174
6be5ee17d80b
style fix: remove trailing spaces
Igor Sysoev <igor@sysoev.ru>
parents:
1116
diff
changeset
|
636 |
1116 | 637 over = r->headers_in.overwrite; |
638 | |
639 if (over) { | |
640 if (over->value.len == 1) { | |
641 ch = over->value.data[0]; | |
642 | |
643 if (ch == 'T' || ch == 't') { | |
644 overwrite = 1; | |
645 goto overwrite_done; | |
646 } | |
647 | |
648 if (ch == 'F' || ch == 'f') { | |
649 overwrite = 0; | |
650 goto overwrite_done; | |
651 } | |
652 | |
653 } | |
654 | |
655 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
656 "client sent invalid \"Overwrite\" header: \"%V\"", | |
657 &over->value); | |
658 return NGX_HTTP_BAD_REQUEST; | |
659 } | |
660 | |
661 overwrite = 1; | |
662 | |
663 overwrite_done: | |
664 | |
665 ngx_http_map_uri_to_path(r, &path, &root, 0); | |
666 | |
667 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
668 "http copy from: \"%s\"", path.data); | |
669 | |
670 uri = r->uri; | |
3161 | 671 r->uri = duri; |
1116 | 672 |
673 ngx_http_map_uri_to_path(r, ©.path, &root, 0); | |
674 | |
675 r->uri = uri; | |
676 | |
677 copy.path.len--; /* omit "\0" */ | |
678 | |
679 if (copy.path.data[copy.path.len - 1] == '/') { | |
680 slash = 1; | |
681 copy.path.len--; | |
682 copy.path.data[copy.path.len] = '\0'; | |
683 | |
684 } else { | |
685 slash = 0; | |
686 } | |
687 | |
688 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
689 "http copy to: \"%s\"", copy.path.data); | |
690 | |
3501
423ff11e3018
use lstat() for WebDAV DELETE, COPY, and MOVE to handle symlinks
Igor Sysoev <igor@sysoev.ru>
parents:
3182
diff
changeset
|
691 if (ngx_link_info(copy.path.data, &fi) == NGX_FILE_ERROR) { |
1116 | 692 err = ngx_errno; |
693 | |
694 if (err != NGX_ENOENT) { | |
695 return ngx_http_dav_error(r->connection->log, err, | |
3501
423ff11e3018
use lstat() for WebDAV DELETE, COPY, and MOVE to handle symlinks
Igor Sysoev <igor@sysoev.ru>
parents:
3182
diff
changeset
|
696 NGX_HTTP_NOT_FOUND, ngx_link_info_n, |
1116 | 697 copy.path.data); |
698 } | |
699 | |
700 /* destination does not exist */ | |
701 | |
1825
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
702 overwrite = 0; |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
703 dir = 0; |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
704 |
1116 | 705 } else { |
706 | |
707 /* destination exists */ | |
708 | |
709 if (ngx_is_dir(&fi) && !slash) { | |
1824 | 710 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
711 "\"%V\" could not be %Ved to collection \"%V\"", | |
712 &r->uri, &r->method_name, &dest->value); | |
1116 | 713 return NGX_HTTP_CONFLICT; |
714 } | |
715 | |
716 if (!overwrite) { | |
1824 | 717 ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_EEXIST, |
718 "\"%s\" could not be created", copy.path.data); | |
1116 | 719 return NGX_HTTP_PRECONDITION_FAILED; |
720 } | |
721 | |
1825
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
722 dir = ngx_is_dir(&fi); |
1116 | 723 } |
724 | |
3501
423ff11e3018
use lstat() for WebDAV DELETE, COPY, and MOVE to handle symlinks
Igor Sysoev <igor@sysoev.ru>
parents:
3182
diff
changeset
|
725 if (ngx_link_info(path.data, &fi) == NGX_FILE_ERROR) { |
1116 | 726 return ngx_http_dav_error(r->connection->log, ngx_errno, |
3501
423ff11e3018
use lstat() for WebDAV DELETE, COPY, and MOVE to handle symlinks
Igor Sysoev <igor@sysoev.ru>
parents:
3182
diff
changeset
|
727 NGX_HTTP_NOT_FOUND, ngx_link_info_n, |
1116 | 728 path.data); |
729 } | |
730 | |
731 if (ngx_is_dir(&fi)) { | |
732 | |
733 if (r->uri.data[r->uri.len - 1] != '/') { | |
1825
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
734 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
735 "\"%V\" is collection", &r->uri); |
1116 | 736 return NGX_HTTP_BAD_REQUEST; |
737 } | |
738 | |
1825
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
739 if (overwrite) { |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
740 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
741 "http delete: \"%s\"", copy.path.data); |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
742 |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
743 rc = ngx_http_dav_delete_path(r, ©.path, dir); |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
744 |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
745 if (rc != NGX_OK) { |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
746 return rc; |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
747 } |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
748 } |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
749 } |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
750 |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
751 if (ngx_is_dir(&fi)) { |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
752 |
1116 | 753 path.len -= 2; /* omit "/\0" */ |
754 | |
755 if (r->method == NGX_HTTP_MOVE) { | |
756 if (ngx_rename_file(path.data, copy.path.data) != NGX_FILE_ERROR) { | |
757 return NGX_HTTP_CREATED; | |
758 } | |
759 } | |
760 | |
761 if (ngx_create_dir(copy.path.data, ngx_file_access(&fi)) | |
762 == NGX_FILE_ERROR) | |
763 { | |
764 return ngx_http_dav_error(r->connection->log, ngx_errno, | |
765 NGX_HTTP_NOT_FOUND, | |
766 ngx_create_dir_n, copy.path.data); | |
767 } | |
768 | |
769 copy.len = path.len; | |
770 | |
1769
a35bc4007ec3
tree.init_handler is never called
Igor Sysoev <igor@sysoev.ru>
parents:
1749
diff
changeset
|
771 tree.init_handler = NULL; |
1825
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
772 tree.file_handler = ngx_http_dav_copy_tree_file; |
1116 | 773 tree.pre_tree_handler = ngx_http_dav_copy_dir; |
774 tree.post_tree_handler = ngx_http_dav_copy_dir_time; | |
775 tree.spec_handler = ngx_http_dav_noop; | |
776 tree.data = © | |
777 tree.alloc = 0; | |
778 tree.log = r->connection->log; | |
779 | |
780 if (ngx_walk_tree(&tree, &path) == NGX_OK) { | |
781 | |
782 if (r->method == NGX_HTTP_MOVE) { | |
783 rc = ngx_http_dav_delete_path(r, &path, 1); | |
784 | |
785 if (rc != NGX_OK) { | |
786 return rc; | |
787 } | |
788 } | |
789 | |
790 return NGX_HTTP_CREATED; | |
791 } | |
792 | |
793 } else { | |
794 | |
795 if (r->method == NGX_HTTP_MOVE) { | |
2394
dbe746851b31
use ngx_ext_rename_file() for single file MOVE
Igor Sysoev <igor@sysoev.ru>
parents:
2049
diff
changeset
|
796 |
dbe746851b31
use ngx_ext_rename_file() for single file MOVE
Igor Sysoev <igor@sysoev.ru>
parents:
2049
diff
changeset
|
797 dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module); |
dbe746851b31
use ngx_ext_rename_file() for single file MOVE
Igor Sysoev <igor@sysoev.ru>
parents:
2049
diff
changeset
|
798 |
dbe746851b31
use ngx_ext_rename_file() for single file MOVE
Igor Sysoev <igor@sysoev.ru>
parents:
2049
diff
changeset
|
799 ext.access = 0; |
dbe746851b31
use ngx_ext_rename_file() for single file MOVE
Igor Sysoev <igor@sysoev.ru>
parents:
2049
diff
changeset
|
800 ext.path_access = dlcf->access; |
dbe746851b31
use ngx_ext_rename_file() for single file MOVE
Igor Sysoev <igor@sysoev.ru>
parents:
2049
diff
changeset
|
801 ext.time = -1; |
dbe746851b31
use ngx_ext_rename_file() for single file MOVE
Igor Sysoev <igor@sysoev.ru>
parents:
2049
diff
changeset
|
802 ext.create_path = 1; |
dbe746851b31
use ngx_ext_rename_file() for single file MOVE
Igor Sysoev <igor@sysoev.ru>
parents:
2049
diff
changeset
|
803 ext.delete_file = 0; |
dbe746851b31
use ngx_ext_rename_file() for single file MOVE
Igor Sysoev <igor@sysoev.ru>
parents:
2049
diff
changeset
|
804 ext.log = r->connection->log; |
dbe746851b31
use ngx_ext_rename_file() for single file MOVE
Igor Sysoev <igor@sysoev.ru>
parents:
2049
diff
changeset
|
805 |
dbe746851b31
use ngx_ext_rename_file() for single file MOVE
Igor Sysoev <igor@sysoev.ru>
parents:
2049
diff
changeset
|
806 if (ngx_ext_rename_file(&path, ©.path, &ext) == NGX_OK) { |
1116 | 807 return NGX_HTTP_NO_CONTENT; |
808 } | |
2394
dbe746851b31
use ngx_ext_rename_file() for single file MOVE
Igor Sysoev <igor@sysoev.ru>
parents:
2049
diff
changeset
|
809 |
3024
8101d9101ed8
allow cross device temporary files atomic copying:
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
810 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
1116 | 811 } |
812 | |
1825
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
813 dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module); |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
814 |
3024
8101d9101ed8
allow cross device temporary files atomic copying:
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
815 cf.size = ngx_file_size(&fi); |
8101d9101ed8
allow cross device temporary files atomic copying:
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
816 cf.buf_size = 0; |
8101d9101ed8
allow cross device temporary files atomic copying:
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
817 cf.access = dlcf->access; |
8101d9101ed8
allow cross device temporary files atomic copying:
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
818 cf.time = ngx_file_mtime(&fi); |
8101d9101ed8
allow cross device temporary files atomic copying:
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
819 cf.log = r->connection->log; |
1116 | 820 |
3024
8101d9101ed8
allow cross device temporary files atomic copying:
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
821 if (ngx_copy_file(path.data, copy.path.data, &cf) == NGX_OK) { |
1116 | 822 return NGX_HTTP_NO_CONTENT; |
823 } | |
824 } | |
825 | |
826 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
827 } | |
828 | |
829 | |
830 static ngx_int_t | |
831 ngx_http_dav_copy_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path) | |
832 { | |
833 u_char *p, *dir; | |
834 size_t len; | |
835 ngx_http_dav_copy_ctx_t *copy; | |
836 | |
837 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, | |
838 "http copy dir: \"%s\"", path->data); | |
839 | |
840 copy = ctx->data; | |
841 | |
842 len = copy->path.len + path->len; | |
843 | |
844 dir = ngx_alloc(len + 1, ctx->log); | |
845 if (dir == NULL) { | |
846 return NGX_ABORT; | |
847 } | |
848 | |
849 p = ngx_cpymem(dir, copy->path.data, copy->path.len); | |
850 (void) ngx_cpystrn(p, path->data + copy->len, path->len - copy->len + 1); | |
851 | |
852 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, | |
853 "http copy dir to: \"%s\"", dir); | |
854 | |
855 if (ngx_create_dir(dir, ngx_dir_access(ctx->access)) == NGX_FILE_ERROR) { | |
856 (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_create_dir_n, | |
857 dir); | |
858 } | |
859 | |
860 ngx_free(dir); | |
861 | |
862 return NGX_OK; | |
863 } | |
864 | |
865 | |
866 static ngx_int_t | |
867 ngx_http_dav_copy_dir_time(ngx_tree_ctx_t *ctx, ngx_str_t *path) | |
868 { | |
869 u_char *p, *dir; | |
870 size_t len; | |
871 ngx_http_dav_copy_ctx_t *copy; | |
872 | |
873 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, | |
874 "http copy dir time: \"%s\"", path->data); | |
875 | |
876 copy = ctx->data; | |
877 | |
878 len = copy->path.len + path->len; | |
879 | |
880 dir = ngx_alloc(len + 1, ctx->log); | |
881 if (dir == NULL) { | |
882 return NGX_ABORT; | |
883 } | |
884 | |
885 p = ngx_cpymem(dir, copy->path.data, copy->path.len); | |
886 (void) ngx_cpystrn(p, path->data + copy->len, path->len - copy->len + 1); | |
887 | |
888 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, | |
889 "http copy dir time to: \"%s\"", dir); | |
890 | |
1803
7405719e4848
condition declarations inside blocks update missed in r1705
Igor Sysoev <igor@sysoev.ru>
parents:
1769
diff
changeset
|
891 #if (NGX_WIN32) |
7405719e4848
condition declarations inside blocks update missed in r1705
Igor Sysoev <igor@sysoev.ru>
parents:
1769
diff
changeset
|
892 { |
7405719e4848
condition declarations inside blocks update missed in r1705
Igor Sysoev <igor@sysoev.ru>
parents:
1769
diff
changeset
|
893 ngx_fd_t fd; |
1116 | 894 |
895 fd = ngx_open_file(dir, NGX_FILE_RDWR, NGX_FILE_OPEN, 0); | |
896 | |
897 if (fd == NGX_INVALID_FILE) { | |
898 (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n, dir); | |
899 goto failed; | |
900 } | |
901 | |
902 if (ngx_set_file_time(NULL, fd, ctx->mtime) != NGX_OK) { | |
903 ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, | |
904 ngx_set_file_time_n " \"%s\" failed", dir); | |
905 } | |
906 | |
907 if (ngx_close_file(fd) == NGX_FILE_ERROR) { | |
908 ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, | |
909 ngx_close_file_n " \"%s\" failed", dir); | |
910 } | |
1803
7405719e4848
condition declarations inside blocks update missed in r1705
Igor Sysoev <igor@sysoev.ru>
parents:
1769
diff
changeset
|
911 } |
1116 | 912 |
913 failed: | |
914 | |
915 #else | |
916 | |
917 if (ngx_set_file_time(dir, 0, ctx->mtime) != NGX_OK) { | |
918 ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno, | |
919 ngx_set_file_time_n " \"%s\" failed", dir); | |
920 } | |
921 | |
922 #endif | |
923 | |
924 ngx_free(dir); | |
925 | |
926 return NGX_OK; | |
927 } | |
928 | |
929 | |
930 static ngx_int_t | |
1825
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
931 ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx, ngx_str_t *path) |
1116 | 932 { |
933 u_char *p, *file; | |
934 size_t len; | |
3024
8101d9101ed8
allow cross device temporary files atomic copying:
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
935 ngx_copy_file_t cf; |
1116 | 936 ngx_http_dav_copy_ctx_t *copy; |
937 | |
938 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, | |
939 "http copy file: \"%s\"", path->data); | |
940 | |
941 copy = ctx->data; | |
942 | |
943 len = copy->path.len + path->len; | |
944 | |
945 file = ngx_alloc(len + 1, ctx->log); | |
946 if (file == NULL) { | |
947 return NGX_ABORT; | |
948 } | |
949 | |
950 p = ngx_cpymem(file, copy->path.data, copy->path.len); | |
951 (void) ngx_cpystrn(p, path->data + copy->len, path->len - copy->len + 1); | |
952 | |
953 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, | |
954 "http copy file to: \"%s\"", file); | |
955 | |
3024
8101d9101ed8
allow cross device temporary files atomic copying:
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
956 cf.size = ctx->size; |
8101d9101ed8
allow cross device temporary files atomic copying:
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
957 cf.buf_size = 0; |
8101d9101ed8
allow cross device temporary files atomic copying:
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
958 cf.access = ctx->access; |
8101d9101ed8
allow cross device temporary files atomic copying:
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
959 cf.time = ctx->mtime; |
8101d9101ed8
allow cross device temporary files atomic copying:
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
960 cf.log = ctx->log; |
8101d9101ed8
allow cross device temporary files atomic copying:
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
961 |
8101d9101ed8
allow cross device temporary files atomic copying:
Igor Sysoev <igor@sysoev.ru>
parents:
2912
diff
changeset
|
962 (void) ngx_copy_file(path->data, file, &cf); |
1825
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
963 |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
964 ngx_free(file); |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
965 |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
966 return NGX_OK; |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
967 } |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
968 |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
969 |
2e0fbfef56d4
do not delete target until all tests will be done,
Igor Sysoev <igor@sysoev.ru>
parents:
1824
diff
changeset
|
970 static ngx_int_t |
1116 | 971 ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt) |
972 { | |
973 ngx_table_elt_t *depth; | |
1174
6be5ee17d80b
style fix: remove trailing spaces
Igor Sysoev <igor@sysoev.ru>
parents:
1116
diff
changeset
|
974 |
1116 | 975 depth = r->headers_in.depth; |
976 | |
977 if (depth == NULL) { | |
978 return dflt; | |
979 } | |
980 | |
981 if (depth->value.len == 1) { | |
982 | |
983 if (depth->value.data[0] == '0') { | |
984 return 0; | |
985 } | |
986 | |
987 if (depth->value.data[0] == '1') { | |
988 return 1; | |
989 } | |
990 | |
991 } else { | |
992 | |
993 if (depth->value.len == sizeof("infinity") - 1 | |
994 && ngx_strcmp(depth->value.data, "infinity") == 0) | |
995 { | |
996 return NGX_HTTP_DAV_INFINITY_DEPTH; | |
997 } | |
998 } | |
999 | |
1000 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
1001 "client sent invalid \"Depth\" header: \"%V\"", | |
1002 &depth->value); | |
1003 | |
1004 return NGX_HTTP_DAV_INVALID_DEPTH; | |
1005 } | |
1006 | |
1007 | |
1008 static ngx_int_t | |
1009 ngx_http_dav_error(ngx_log_t *log, ngx_err_t err, ngx_int_t not_found, | |
637 | 1010 char *failed, u_char *path) |
1011 { | |
1012 ngx_int_t rc; | |
1013 ngx_uint_t level; | |
1014 | |
1015 if (err == NGX_ENOENT || err == NGX_ENOTDIR || err == NGX_ENAMETOOLONG) { | |
1016 level = NGX_LOG_ERR; | |
1017 rc = not_found; | |
1018 | |
1019 } else if (err == NGX_EACCES || err == NGX_EPERM) { | |
1020 level = NGX_LOG_ERR; | |
1021 rc = NGX_HTTP_FORBIDDEN; | |
1022 | |
1023 } else if (err == NGX_EEXIST) { | |
1024 level = NGX_LOG_ERR; | |
1025 rc = NGX_HTTP_NOT_ALLOWED; | |
1026 | |
1027 } else if (err == NGX_ENOSPC) { | |
1028 level = NGX_LOG_CRIT; | |
1029 rc = NGX_HTTP_INSUFFICIENT_STORAGE; | |
1030 | |
1031 } else { | |
1032 level = NGX_LOG_CRIT; | |
1033 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; | |
1034 } | |
1035 | |
1116 | 1036 ngx_log_error(level, log, err, "%s \"%s\" failed", failed, path); |
637 | 1037 |
1038 return rc; | |
1039 } | |
1040 | |
1041 | |
1042 static ngx_int_t | |
1043 ngx_http_dav_location(ngx_http_request_t *r, u_char *path) | |
1044 { | |
1045 u_char *location; | |
1046 ngx_http_core_loc_conf_t *clcf; | |
1047 | |
1048 r->headers_out.location = ngx_palloc(r->pool, sizeof(ngx_table_elt_t)); | |
1049 if (r->headers_out.location == NULL) { | |
1050 return NGX_ERROR; | |
1051 } | |
1052 | |
1053 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
1054 | |
1055 if (!clcf->alias && clcf->root_lengths == NULL) { | |
1056 location = path + clcf->root.len; | |
1057 | |
1058 } else { | |
2049 | 1059 location = ngx_pnalloc(r->pool, r->uri.len); |
637 | 1060 if (location == NULL) { |
1061 return NGX_ERROR; | |
1062 } | |
1063 | |
1064 ngx_memcpy(location, r->uri.data, r->uri.len); | |
1065 } | |
1066 | |
1067 /* | |
1068 * we do not need to set the r->headers_out.location->hash and | |
1069 * r->headers_out.location->key fields | |
1070 */ | |
1071 | |
1072 r->headers_out.location->value.len = r->uri.len; | |
1073 r->headers_out.location->value.data = location; | |
1074 | |
1075 return NGX_OK; | |
1076 } | |
1077 | |
1078 | |
633 | 1079 static void * |
1080 ngx_http_dav_create_loc_conf(ngx_conf_t *cf) | |
1081 { | |
1082 ngx_http_dav_loc_conf_t *conf; | |
1083 | |
1084 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_dav_loc_conf_t)); | |
1085 if (conf == NULL) { | |
2912
c7d57b539248
return NULL instead of NGX_CONF_ERROR on a create conf failure
Igor Sysoev <igor@sysoev.ru>
parents:
2782
diff
changeset
|
1086 return NULL; |
633 | 1087 } |
1088 | |
1089 /* | |
1090 * set by ngx_pcalloc(): | |
1091 * | |
1092 * conf->methods = 0; | |
1093 */ | |
1094 | |
1864
524831ec3e69
fix building by msvc introduced in r1817
Igor Sysoev <igor@sysoev.ru>
parents:
1834
diff
changeset
|
1095 conf->min_delete_depth = NGX_CONF_UNSET_UINT; |
1816 | 1096 conf->access = NGX_CONF_UNSET_UINT; |
637 | 1097 conf->create_full_put_path = NGX_CONF_UNSET; |
1098 | |
633 | 1099 return conf; |
1100 } | |
1101 | |
1102 | |
1103 static char * | |
1104 ngx_http_dav_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) | |
1105 { | |
1106 ngx_http_dav_loc_conf_t *prev = parent; | |
1107 ngx_http_dav_loc_conf_t *conf = child; | |
1108 | |
1109 ngx_conf_merge_bitmask_value(conf->methods, prev->methods, | |
637 | 1110 (NGX_CONF_BITMASK_SET|NGX_HTTP_DAV_OFF)); |
1111 | |
1816 | 1112 ngx_conf_merge_uint_value(conf->min_delete_depth, |
1113 prev->min_delete_depth, 0); | |
633 | 1114 |
669 | 1115 ngx_conf_merge_uint_value(conf->access, prev->access, 0600); |
1116 | |
1816 | 1117 ngx_conf_merge_value(conf->create_full_put_path, |
1118 prev->create_full_put_path, 0); | |
1119 | |
633 | 1120 return NGX_CONF_OK; |
1121 } | |
1122 | |
1123 | |
1124 static ngx_int_t | |
681 | 1125 ngx_http_dav_init(ngx_conf_t *cf) |
633 | 1126 { |
1127 ngx_http_handler_pt *h; | |
1128 ngx_http_core_main_conf_t *cmcf; | |
1129 | |
681 | 1130 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); |
633 | 1131 |
1132 h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers); | |
1133 if (h == NULL) { | |
1134 return NGX_ERROR; | |
1135 } | |
1136 | |
1137 *h = ngx_http_dav_handler; | |
1138 | |
1139 return NGX_OK; | |
1140 } |