Mercurial > hg > nginx
annotate src/http/modules/ngx_http_dav_module.c @ 1089:b2e6eb425770
use ngx_dir_access() to enable search bits for directory
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 29 Jan 2007 12:25:44 +0000 |
parents | 4d203f76b757 |
children | 6fcce6c4019a |
rev | line source |
---|---|
633 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_http.h> | |
10 | |
11 | |
12 #define NGX_HTTP_DAV_OFF 2 | |
13 | |
14 typedef struct { | |
15 ngx_uint_t methods; | |
637 | 16 ngx_flag_t create_full_put_path; |
669 | 17 ngx_uint_t access; |
633 | 18 } ngx_http_dav_loc_conf_t; |
19 | |
20 | |
21 static ngx_int_t ngx_http_dav_handler(ngx_http_request_t *r); | |
1058
01f818c6f7de
add size, access, and mtime to ngx_walk_tree()
Igor Sysoev <igor@sysoev.ru>
parents:
957
diff
changeset
|
22 static ngx_int_t ngx_http_dav_no_init(void *ctx, void *prev); |
957 | 23 static ngx_int_t ngx_http_dav_noop(ngx_tree_ctx_t *ctx, ngx_str_t *path); |
24 static ngx_int_t ngx_http_dav_delete_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path); | |
25 static ngx_int_t ngx_http_dav_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path); | |
633 | 26 static void ngx_http_dav_put_handler(ngx_http_request_t *r); |
637 | 27 static ngx_int_t ngx_http_dav_error(ngx_http_request_t *, ngx_err_t err, |
28 ngx_int_t not_found, char *failed, u_char *path); | |
29 static ngx_int_t ngx_http_dav_location(ngx_http_request_t *r, u_char *path); | |
669 | 30 static char *ngx_http_dav_access(ngx_conf_t *cf, ngx_command_t *cmd, |
31 void *conf); | |
633 | 32 static void *ngx_http_dav_create_loc_conf(ngx_conf_t *cf); |
33 static char *ngx_http_dav_merge_loc_conf(ngx_conf_t *cf, | |
34 void *parent, void *child); | |
681 | 35 static ngx_int_t ngx_http_dav_init(ngx_conf_t *cf); |
633 | 36 |
37 | |
38 static ngx_conf_bitmask_t ngx_http_dav_methods_mask[] = { | |
39 { ngx_string("off"), NGX_HTTP_DAV_OFF }, | |
40 { ngx_string("put"), NGX_HTTP_PUT }, | |
41 { ngx_string("delete"), NGX_HTTP_DELETE }, | |
637 | 42 { ngx_string("mkcol"), NGX_HTTP_MKCOL }, |
633 | 43 { ngx_null_string, 0 } |
44 }; | |
45 | |
46 | |
47 static ngx_command_t ngx_http_dav_commands[] = { | |
48 | |
49 { ngx_string("dav_methods"), | |
50 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | |
51 ngx_conf_set_bitmask_slot, | |
52 NGX_HTTP_LOC_CONF_OFFSET, | |
53 offsetof(ngx_http_dav_loc_conf_t, methods), | |
54 &ngx_http_dav_methods_mask }, | |
55 | |
637 | 56 { ngx_string("create_full_put_path"), |
57 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
58 ngx_conf_set_flag_slot, | |
59 NGX_HTTP_LOC_CONF_OFFSET, | |
60 offsetof(ngx_http_dav_loc_conf_t, create_full_put_path), | |
61 NULL }, | |
62 | |
669 | 63 { ngx_string("dav_access"), |
675 | 64 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123, |
669 | 65 ngx_http_dav_access, |
66 NGX_HTTP_LOC_CONF_OFFSET, | |
67 0, | |
68 NULL }, | |
69 | |
633 | 70 ngx_null_command |
71 }; | |
72 | |
73 | |
667 | 74 static ngx_http_module_t ngx_http_dav_module_ctx = { |
633 | 75 NULL, /* preconfiguration */ |
681 | 76 ngx_http_dav_init, /* postconfiguration */ |
633 | 77 |
78 NULL, /* create main configuration */ | |
79 NULL, /* init main configuration */ | |
80 | |
81 NULL, /* create server configuration */ | |
82 NULL, /* merge server configuration */ | |
83 | |
84 ngx_http_dav_create_loc_conf, /* create location configuration */ | |
85 ngx_http_dav_merge_loc_conf /* merge location configuration */ | |
86 }; | |
87 | |
88 | |
89 ngx_module_t ngx_http_dav_module = { | |
90 NGX_MODULE_V1, | |
91 &ngx_http_dav_module_ctx, /* module context */ | |
92 ngx_http_dav_commands, /* module directives */ | |
93 NGX_HTTP_MODULE, /* module type */ | |
94 NULL, /* init master */ | |
681 | 95 NULL, /* init module */ |
633 | 96 NULL, /* init process */ |
97 NULL, /* init thread */ | |
98 NULL, /* exit thread */ | |
99 NULL, /* exit process */ | |
100 NULL, /* exit master */ | |
101 NGX_MODULE_V1_PADDING | |
102 }; | |
103 | |
104 | |
105 static ngx_int_t | |
106 ngx_http_dav_handler(ngx_http_request_t *r) | |
107 { | |
637 | 108 char *failed; |
773 | 109 size_t root; |
633 | 110 ngx_int_t rc; |
111 ngx_str_t path; | |
957 | 112 ngx_tree_ctx_t tree; |
637 | 113 ngx_file_info_t fi; |
921
cba27113c33c
DELETE may not have the "Depth" header
Igor Sysoev <igor@sysoev.ru>
parents:
920
diff
changeset
|
114 ngx_table_elt_t *depth; |
633 | 115 ngx_http_dav_loc_conf_t *dlcf; |
116 | |
117 /* TODO: Win32 */ | |
118 if (r->zero_in_uri) { | |
119 return NGX_DECLINED; | |
120 } | |
121 | |
122 dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module); | |
123 | |
124 if (!(r->method & dlcf->methods)) { | |
125 return NGX_DECLINED; | |
126 } | |
127 | |
128 switch (r->method) { | |
129 | |
130 case NGX_HTTP_PUT: | |
131 | |
132 if (r->uri.data[r->uri.len - 1] == '/') { | |
1060
8e5c032e7855
the PUTing to collection must return NGX_HTTP_BAD_REQUEST
Igor Sysoev <igor@sysoev.ru>
parents:
1058
diff
changeset
|
133 return NGX_HTTP_BAD_REQUEST; |
633 | 134 } |
135 | |
136 r->request_body_in_file_only = 1; | |
137 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
|
138 r->request_body_in_clean_file = 1; |
633 | 139 r->request_body_file_group_access = 1; |
637 | 140 r->request_body_file_log_level = 0; |
633 | 141 |
142 rc = ngx_http_read_client_request_body(r, ngx_http_dav_put_handler); | |
143 | |
144 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { | |
145 return rc; | |
146 } | |
147 | |
148 return NGX_DONE; | |
149 | |
150 case NGX_HTTP_DELETE: | |
151 | |
637 | 152 if (r->headers_in.content_length_n > 0) { |
153 return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE; | |
154 } | |
155 | |
156 rc = ngx_http_discard_body(r); | |
157 | |
158 if (rc != NGX_OK && rc != NGX_AGAIN) { | |
159 return rc; | |
633 | 160 } |
161 | |
773 | 162 ngx_http_map_uri_to_path(r, &path, &root, 0); |
633 | 163 |
164 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
165 "http delete filename: \"%s\"", path.data); | |
166 | |
637 | 167 if (ngx_file_info(path.data, &fi) != -1) { |
168 | |
169 if (ngx_is_dir(&fi)) { | |
170 | |
921
cba27113c33c
DELETE may not have the "Depth" header
Igor Sysoev <igor@sysoev.ru>
parents:
920
diff
changeset
|
171 if (r->uri.data[r->uri.len - 1] != '/') { |
cba27113c33c
DELETE may not have the "Depth" header
Igor Sysoev <igor@sysoev.ru>
parents:
920
diff
changeset
|
172 return NGX_HTTP_BAD_REQUEST; |
cba27113c33c
DELETE may not have the "Depth" header
Igor Sysoev <igor@sysoev.ru>
parents:
920
diff
changeset
|
173 } |
cba27113c33c
DELETE may not have the "Depth" header
Igor Sysoev <igor@sysoev.ru>
parents:
920
diff
changeset
|
174 |
cba27113c33c
DELETE may not have the "Depth" header
Igor Sysoev <igor@sysoev.ru>
parents:
920
diff
changeset
|
175 depth = r->headers_in.depth; |
cba27113c33c
DELETE may not have the "Depth" header
Igor Sysoev <igor@sysoev.ru>
parents:
920
diff
changeset
|
176 |
cba27113c33c
DELETE may not have the "Depth" header
Igor Sysoev <igor@sysoev.ru>
parents:
920
diff
changeset
|
177 if (depth |
cba27113c33c
DELETE may not have the "Depth" header
Igor Sysoev <igor@sysoev.ru>
parents:
920
diff
changeset
|
178 && (depth->value.len != sizeof("infinity") - 1 |
cba27113c33c
DELETE may not have the "Depth" header
Igor Sysoev <igor@sysoev.ru>
parents:
920
diff
changeset
|
179 || ngx_strcmp(depth->value.data, "infinity") != 0)) |
637 | 180 { |
181 return NGX_HTTP_BAD_REQUEST; | |
182 } | |
183 | |
957 | 184 path.len -= 2; |
185 | |
186 tree.init_handler = ngx_http_dav_no_init; | |
187 tree.file_handler = ngx_http_dav_delete_file; | |
188 tree.pre_tree_handler = ngx_http_dav_noop; | |
189 tree.post_tree_handler = ngx_http_dav_delete_dir; | |
190 tree.spec_handler = ngx_http_dav_delete_file; | |
191 tree.data = NULL; | |
1058
01f818c6f7de
add size, access, and mtime to ngx_walk_tree()
Igor Sysoev <igor@sysoev.ru>
parents:
957
diff
changeset
|
192 tree.alloc = 0; |
957 | 193 tree.log = r->connection->log; |
194 | |
195 if (ngx_walk_tree(&tree, &path) == NGX_OK) { | |
196 | |
197 if (ngx_delete_dir(path.data) != NGX_FILE_ERROR) { | |
198 return NGX_HTTP_NO_CONTENT; | |
199 } | |
200 | |
637 | 201 } |
202 | |
203 failed = ngx_delete_dir_n; | |
204 | |
205 } else { | |
633 | 206 |
637 | 207 if (r->uri.data[r->uri.len - 1] == '/') { |
208 return NGX_HTTP_BAD_REQUEST; | |
209 } | |
210 | |
921
cba27113c33c
DELETE may not have the "Depth" header
Igor Sysoev <igor@sysoev.ru>
parents:
920
diff
changeset
|
211 depth = r->headers_in.depth; |
cba27113c33c
DELETE may not have the "Depth" header
Igor Sysoev <igor@sysoev.ru>
parents:
920
diff
changeset
|
212 |
cba27113c33c
DELETE may not have the "Depth" header
Igor Sysoev <igor@sysoev.ru>
parents:
920
diff
changeset
|
213 if (depth |
cba27113c33c
DELETE may not have the "Depth" header
Igor Sysoev <igor@sysoev.ru>
parents:
920
diff
changeset
|
214 && depth->value.len == 1 |
cba27113c33c
DELETE may not have the "Depth" header
Igor Sysoev <igor@sysoev.ru>
parents:
920
diff
changeset
|
215 && depth->value.data[0] == '1') |
637 | 216 { |
217 return NGX_HTTP_BAD_REQUEST; | |
218 } | |
219 | |
220 if (ngx_delete_file(path.data) != NGX_FILE_ERROR) { | |
221 return NGX_HTTP_NO_CONTENT; | |
222 } | |
223 | |
224 failed = ngx_delete_file_n; | |
225 } | |
226 | |
227 } else { | |
228 failed = ngx_file_info_n; | |
633 | 229 } |
230 | |
637 | 231 return ngx_http_dav_error(r, ngx_errno, NGX_HTTP_NOT_FOUND, failed, |
232 path.data); | |
233 | |
234 case NGX_HTTP_MKCOL: | |
235 | |
236 if (r->uri.data[r->uri.len - 1] != '/') { | |
237 return NGX_DECLINED; | |
238 } | |
239 | |
240 if (r->headers_in.content_length_n > 0) { | |
241 return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE; | |
242 } | |
243 | |
244 rc = ngx_http_discard_body(r); | |
245 | |
246 if (rc != NGX_OK && rc != NGX_AGAIN) { | |
247 return rc; | |
248 } | |
249 | |
773 | 250 ngx_http_map_uri_to_path(r, &path, &root, 0); |
637 | 251 |
252 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
253 "http mkcol path: \"%s\"", path.data); | |
254 | |
1089
b2e6eb425770
use ngx_dir_access() to enable search bits for directory
Igor Sysoev <igor@sysoev.ru>
parents:
1075
diff
changeset
|
255 if (ngx_create_dir(path.data, ngx_dir_access(dlcf->access)) |
b2e6eb425770
use ngx_dir_access() to enable search bits for directory
Igor Sysoev <igor@sysoev.ru>
parents:
1075
diff
changeset
|
256 != NGX_FILE_ERROR) |
b2e6eb425770
use ngx_dir_access() to enable search bits for directory
Igor Sysoev <igor@sysoev.ru>
parents:
1075
diff
changeset
|
257 { |
637 | 258 if (ngx_http_dav_location(r, path.data) != NGX_OK) { |
259 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
260 } | |
261 | |
262 return NGX_HTTP_CREATED; | |
263 } | |
264 | |
265 return ngx_http_dav_error(r, ngx_errno, NGX_HTTP_CONFLICT, | |
266 ngx_create_dir_n, path.data); | |
633 | 267 } |
268 | |
269 return NGX_DECLINED; | |
270 } | |
271 | |
272 | |
957 | 273 static ngx_int_t |
1058
01f818c6f7de
add size, access, and mtime to ngx_walk_tree()
Igor Sysoev <igor@sysoev.ru>
parents:
957
diff
changeset
|
274 ngx_http_dav_no_init(void *ctx, void *prev) |
957 | 275 { |
276 return NGX_OK; | |
277 } | |
278 | |
279 | |
280 static ngx_int_t | |
281 ngx_http_dav_noop(ngx_tree_ctx_t *ctx, ngx_str_t *path) | |
282 { | |
283 return NGX_OK; | |
284 } | |
285 | |
286 | |
287 static ngx_int_t | |
288 ngx_http_dav_delete_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path) | |
289 { | |
290 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, | |
291 "http delete dir: \"%s\"", path->data); | |
292 | |
293 ngx_delete_dir(path->data); | |
294 | |
295 return NGX_OK; | |
296 } | |
297 | |
298 | |
299 static ngx_int_t | |
300 ngx_http_dav_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path) | |
301 { | |
302 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, | |
303 "http delete file: \"%s\"", path->data); | |
304 | |
305 ngx_delete_file(path->data); | |
306 | |
307 return NGX_OK; | |
308 } | |
309 | |
310 | |
633 | 311 static void |
312 ngx_http_dav_put_handler(ngx_http_request_t *r) | |
313 { | |
669 | 314 char *failed; |
315 u_char *name; | |
773 | 316 size_t root; |
681 | 317 time_t date; |
637 | 318 ngx_err_t err; |
319 ngx_str_t *temp, path; | |
320 ngx_uint_t status; | |
321 ngx_file_info_t fi; | |
322 ngx_http_dav_loc_conf_t *dlcf; | |
633 | 323 |
773 | 324 ngx_http_map_uri_to_path(r, &path, &root, 0); |
633 | 325 |
326 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
327 "http put filename: \"%s\"", path.data); | |
328 | |
329 temp = &r->request_body->temp_file->file.name; | |
330 | |
331 if (ngx_file_info(path.data, &fi) == -1) { | |
332 status = NGX_HTTP_CREATED; | |
333 | |
334 } else { | |
335 status = NGX_HTTP_NO_CONTENT; | |
663 | 336 |
337 if (ngx_is_dir(&fi)) { | |
338 ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_EISDIR, | |
339 "\"%s\" could not be created", path.data); | |
633 | 340 |
663 | 341 if (ngx_delete_file(temp->data) == NGX_FILE_ERROR) { |
342 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, | |
343 ngx_delete_file_n " \"%s\" failed", | |
344 temp->data); | |
345 } | |
346 | |
347 ngx_http_finalize_request(r, NGX_HTTP_CONFLICT); | |
348 return; | |
661 | 349 } |
637 | 350 } |
351 | |
669 | 352 dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module); |
353 | |
354 #if !(NGX_WIN32) | |
355 | |
1089
b2e6eb425770
use ngx_dir_access() to enable search bits for directory
Igor Sysoev <igor@sysoev.ru>
parents:
1075
diff
changeset
|
356 if (ngx_change_file_access(temp->data, dlcf->access) |
669 | 357 == NGX_FILE_ERROR) |
358 { | |
359 err = ngx_errno; | |
360 failed = ngx_change_file_access_n; | |
361 name = temp->data; | |
362 | |
363 goto failed; | |
364 } | |
365 | |
366 #endif | |
367 | |
681 | 368 if (r->headers_in.date) { |
369 date = ngx_http_parse_time(r->headers_in.date->value.data, | |
370 r->headers_in.date->value.len); | |
371 | |
372 if (date != NGX_ERROR) { | |
373 if (ngx_set_file_time(temp->data, | |
374 r->request_body->temp_file->file.fd, date) | |
375 != NGX_OK) | |
376 { | |
377 err = ngx_errno; | |
378 failed = ngx_set_file_time_n; | |
379 name = temp->data; | |
380 | |
381 goto failed; | |
382 } | |
383 } | |
384 } | |
385 | |
669 | 386 failed = ngx_rename_file_n; |
387 name = path.data; | |
388 | |
633 | 389 if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) { |
390 goto ok; | |
391 } | |
392 | |
393 err = ngx_errno; | |
394 | |
637 | 395 if (err == NGX_ENOENT) { |
396 | |
397 if (dlcf->create_full_put_path) { | |
1089
b2e6eb425770
use ngx_dir_access() to enable search bits for directory
Igor Sysoev <igor@sysoev.ru>
parents:
1075
diff
changeset
|
398 err = ngx_create_full_path(path.data, ngx_dir_access(dlcf->access)); |
637 | 399 |
400 if (err == 0) { | |
401 if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) { | |
402 goto ok; | |
403 } | |
404 | |
405 err = ngx_errno; | |
406 } | |
407 } | |
408 } | |
409 | |
633 | 410 #if (NGX_WIN32) |
411 | |
412 if (err == NGX_EEXIST) { | |
413 if (ngx_win32_rename_file(temp, &path, r->pool) != NGX_ERROR) { | |
414 | |
415 if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) { | |
416 goto ok; | |
417 } | |
418 } | |
419 | |
420 err = ngx_errno; | |
421 } | |
422 | |
681 | 423 #endif |
669 | 424 |
425 failed: | |
426 | |
661 | 427 if (ngx_delete_file(temp->data) == NGX_FILE_ERROR) { |
428 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, | |
429 ngx_delete_file_n " \"%s\" failed", | |
430 temp->data); | |
431 } | |
432 | |
669 | 433 ngx_http_finalize_request(r, |
434 ngx_http_dav_error(r, err, NGX_HTTP_CONFLICT, failed, name)); | |
435 | |
633 | 436 return; |
437 | |
438 ok: | |
439 | |
440 if (status == NGX_HTTP_CREATED) { | |
637 | 441 if (ngx_http_dav_location(r, path.data) != NGX_OK) { |
633 | 442 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
443 return; | |
444 } | |
639 | 445 |
446 r->headers_out.content_length_n = 0; | |
633 | 447 } |
448 | |
449 r->headers_out.status = status; | |
450 r->header_only = 1; | |
451 | |
452 ngx_http_finalize_request(r, ngx_http_send_header(r)); | |
453 return; | |
454 } | |
455 | |
456 | |
637 | 457 static ngx_int_t |
458 ngx_http_dav_error(ngx_http_request_t *r, ngx_err_t err, ngx_int_t not_found, | |
459 char *failed, u_char *path) | |
460 { | |
461 ngx_int_t rc; | |
462 ngx_uint_t level; | |
463 | |
464 if (err == NGX_ENOENT || err == NGX_ENOTDIR || err == NGX_ENAMETOOLONG) { | |
465 level = NGX_LOG_ERR; | |
466 rc = not_found; | |
467 | |
468 } else if (err == NGX_EACCES || err == NGX_EPERM) { | |
469 level = NGX_LOG_ERR; | |
470 rc = NGX_HTTP_FORBIDDEN; | |
471 | |
472 } else if (err == NGX_EEXIST) { | |
473 level = NGX_LOG_ERR; | |
474 rc = NGX_HTTP_NOT_ALLOWED; | |
475 | |
476 } else if (err == NGX_ENOSPC) { | |
477 level = NGX_LOG_CRIT; | |
478 rc = NGX_HTTP_INSUFFICIENT_STORAGE; | |
479 | |
480 } else { | |
481 level = NGX_LOG_CRIT; | |
482 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; | |
483 } | |
484 | |
485 ngx_log_error(level, r->connection->log, err, | |
486 "%s \"%s\" failed", failed, path); | |
487 | |
488 return rc; | |
489 } | |
490 | |
491 | |
492 static ngx_int_t | |
493 ngx_http_dav_location(ngx_http_request_t *r, u_char *path) | |
494 { | |
495 u_char *location; | |
496 ngx_http_core_loc_conf_t *clcf; | |
497 | |
498 r->headers_out.location = ngx_palloc(r->pool, sizeof(ngx_table_elt_t)); | |
499 if (r->headers_out.location == NULL) { | |
500 return NGX_ERROR; | |
501 } | |
502 | |
503 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
504 | |
505 if (!clcf->alias && clcf->root_lengths == NULL) { | |
506 location = path + clcf->root.len; | |
507 | |
508 } else { | |
509 location = ngx_palloc(r->pool, r->uri.len); | |
510 if (location == NULL) { | |
511 return NGX_ERROR; | |
512 } | |
513 | |
514 ngx_memcpy(location, r->uri.data, r->uri.len); | |
515 } | |
516 | |
517 /* | |
518 * we do not need to set the r->headers_out.location->hash and | |
519 * r->headers_out.location->key fields | |
520 */ | |
521 | |
522 r->headers_out.location->value.len = r->uri.len; | |
523 r->headers_out.location->value.data = location; | |
524 | |
525 return NGX_OK; | |
526 } | |
527 | |
528 | |
669 | 529 static char * |
530 ngx_http_dav_access(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
531 { | |
532 ngx_http_dav_loc_conf_t *lcf = conf; | |
533 | |
534 u_char *p; | |
535 ngx_str_t *value; | |
536 ngx_uint_t i, right, shift; | |
537 | |
538 if (lcf->access != NGX_CONF_UNSET_UINT) { | |
539 return "is duplicate"; | |
540 } | |
541 | |
542 value = cf->args->elts; | |
543 | |
1089
b2e6eb425770
use ngx_dir_access() to enable search bits for directory
Igor Sysoev <igor@sysoev.ru>
parents:
1075
diff
changeset
|
544 lcf->access = 0600; |
669 | 545 |
920 | 546 for (i = 1; i < cf->args->nelts; i++) { |
669 | 547 |
548 p = value[i].data; | |
549 | |
550 if (ngx_strncmp(p, "user:", sizeof("user:") - 1) == 0) { | |
551 shift = 6; | |
552 p += sizeof("user:") - 1; | |
553 | |
554 } else if (ngx_strncmp(p, "group:", sizeof("group:") - 1) == 0) { | |
555 shift = 3; | |
556 p += sizeof("group:") - 1; | |
557 | |
558 } else if (ngx_strncmp(p, "all:", sizeof("all:") - 1) == 0) { | |
559 shift = 0; | |
560 p += sizeof("all:") - 1; | |
561 | |
562 } else { | |
563 goto invalid; | |
564 } | |
565 | |
566 if (ngx_strcmp(p, "rw") == 0) { | |
1089
b2e6eb425770
use ngx_dir_access() to enable search bits for directory
Igor Sysoev <igor@sysoev.ru>
parents:
1075
diff
changeset
|
567 right = 6; |
669 | 568 |
569 } else if (ngx_strcmp(p, "r") == 0) { | |
1089
b2e6eb425770
use ngx_dir_access() to enable search bits for directory
Igor Sysoev <igor@sysoev.ru>
parents:
1075
diff
changeset
|
570 right = 4; |
669 | 571 |
572 } else { | |
573 goto invalid; | |
574 } | |
575 | |
1089
b2e6eb425770
use ngx_dir_access() to enable search bits for directory
Igor Sysoev <igor@sysoev.ru>
parents:
1075
diff
changeset
|
576 lcf->access |= right << shift; |
669 | 577 } |
578 | |
579 return NGX_CONF_OK; | |
580 | |
581 invalid: | |
582 | |
583 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
584 "invalid value \"%V\"", &value[i]); | |
585 return NGX_CONF_ERROR; | |
586 } | |
587 | |
588 | |
633 | 589 static void * |
590 ngx_http_dav_create_loc_conf(ngx_conf_t *cf) | |
591 { | |
592 ngx_http_dav_loc_conf_t *conf; | |
593 | |
594 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_dav_loc_conf_t)); | |
595 if (conf == NULL) { | |
596 return NGX_CONF_ERROR; | |
597 } | |
598 | |
599 /* | |
600 * set by ngx_pcalloc(): | |
601 * | |
602 * conf->methods = 0; | |
603 */ | |
604 | |
637 | 605 conf->create_full_put_path = NGX_CONF_UNSET; |
669 | 606 conf->access = NGX_CONF_UNSET_UINT; |
637 | 607 |
633 | 608 return conf; |
609 } | |
610 | |
611 | |
612 static char * | |
613 ngx_http_dav_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) | |
614 { | |
615 ngx_http_dav_loc_conf_t *prev = parent; | |
616 ngx_http_dav_loc_conf_t *conf = child; | |
617 | |
618 ngx_conf_merge_bitmask_value(conf->methods, prev->methods, | |
637 | 619 (NGX_CONF_BITMASK_SET|NGX_HTTP_DAV_OFF)); |
620 | |
621 ngx_conf_merge_value(conf->create_full_put_path, prev->create_full_put_path, | |
622 0); | |
633 | 623 |
669 | 624 ngx_conf_merge_uint_value(conf->access, prev->access, 0600); |
625 | |
633 | 626 return NGX_CONF_OK; |
627 } | |
628 | |
629 | |
630 static ngx_int_t | |
681 | 631 ngx_http_dav_init(ngx_conf_t *cf) |
633 | 632 { |
633 ngx_http_handler_pt *h; | |
634 ngx_http_core_main_conf_t *cmcf; | |
635 | |
681 | 636 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); |
633 | 637 |
638 h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers); | |
639 if (h == NULL) { | |
640 return NGX_ERROR; | |
641 } | |
642 | |
643 *h = ngx_http_dav_handler; | |
644 | |
645 return NGX_OK; | |
646 } |