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