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