Mercurial > hg > nginx-quic
annotate src/http/modules/ngx_http_dav_module.c @ 1073:d82560e9d147
client_body_in_file_only any
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Wed, 24 Jan 2007 09:14:08 +0000 |
parents | 8e5c032e7855 |
children | 4d203f76b757 |
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; | |
138 r->request_body_delete_incomplete_file = 1; | |
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 | |
669 | 255 if (ngx_create_dir(path.data, dlcf->access) != NGX_FILE_ERROR) { |
637 | 256 if (ngx_http_dav_location(r, path.data) != NGX_OK) { |
257 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
258 } | |
259 | |
260 return NGX_HTTP_CREATED; | |
261 } | |
262 | |
263 return ngx_http_dav_error(r, ngx_errno, NGX_HTTP_CONFLICT, | |
264 ngx_create_dir_n, path.data); | |
633 | 265 } |
266 | |
267 return NGX_DECLINED; | |
268 } | |
269 | |
270 | |
957 | 271 static ngx_int_t |
1058
01f818c6f7de
add size, access, and mtime to ngx_walk_tree()
Igor Sysoev <igor@sysoev.ru>
parents:
957
diff
changeset
|
272 ngx_http_dav_no_init(void *ctx, void *prev) |
957 | 273 { |
274 return NGX_OK; | |
275 } | |
276 | |
277 | |
278 static ngx_int_t | |
279 ngx_http_dav_noop(ngx_tree_ctx_t *ctx, ngx_str_t *path) | |
280 { | |
281 return NGX_OK; | |
282 } | |
283 | |
284 | |
285 static ngx_int_t | |
286 ngx_http_dav_delete_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path) | |
287 { | |
288 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, | |
289 "http delete dir: \"%s\"", path->data); | |
290 | |
291 ngx_delete_dir(path->data); | |
292 | |
293 return NGX_OK; | |
294 } | |
295 | |
296 | |
297 static ngx_int_t | |
298 ngx_http_dav_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path) | |
299 { | |
300 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0, | |
301 "http delete file: \"%s\"", path->data); | |
302 | |
303 ngx_delete_file(path->data); | |
304 | |
305 return NGX_OK; | |
306 } | |
307 | |
308 | |
633 | 309 static void |
310 ngx_http_dav_put_handler(ngx_http_request_t *r) | |
311 { | |
669 | 312 char *failed; |
313 u_char *name; | |
773 | 314 size_t root; |
681 | 315 time_t date; |
637 | 316 ngx_err_t err; |
317 ngx_str_t *temp, path; | |
318 ngx_uint_t status; | |
319 ngx_file_info_t fi; | |
320 ngx_http_dav_loc_conf_t *dlcf; | |
633 | 321 |
773 | 322 ngx_http_map_uri_to_path(r, &path, &root, 0); |
633 | 323 |
324 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
325 "http put filename: \"%s\"", path.data); | |
326 | |
327 temp = &r->request_body->temp_file->file.name; | |
328 | |
329 if (ngx_file_info(path.data, &fi) == -1) { | |
330 status = NGX_HTTP_CREATED; | |
331 | |
332 } else { | |
333 status = NGX_HTTP_NO_CONTENT; | |
663 | 334 |
335 if (ngx_is_dir(&fi)) { | |
336 ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_EISDIR, | |
337 "\"%s\" could not be created", path.data); | |
633 | 338 |
663 | 339 if (ngx_delete_file(temp->data) == NGX_FILE_ERROR) { |
340 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, | |
341 ngx_delete_file_n " \"%s\" failed", | |
342 temp->data); | |
343 } | |
344 | |
345 ngx_http_finalize_request(r, NGX_HTTP_CONFLICT); | |
346 return; | |
661 | 347 } |
637 | 348 } |
349 | |
669 | 350 dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module); |
351 | |
352 #if !(NGX_WIN32) | |
353 | |
354 if (ngx_change_file_access(temp->data, dlcf->access & ~0111) | |
355 == NGX_FILE_ERROR) | |
356 { | |
357 err = ngx_errno; | |
358 failed = ngx_change_file_access_n; | |
359 name = temp->data; | |
360 | |
361 goto failed; | |
362 } | |
363 | |
364 #endif | |
365 | |
681 | 366 if (r->headers_in.date) { |
367 date = ngx_http_parse_time(r->headers_in.date->value.data, | |
368 r->headers_in.date->value.len); | |
369 | |
370 if (date != NGX_ERROR) { | |
371 if (ngx_set_file_time(temp->data, | |
372 r->request_body->temp_file->file.fd, date) | |
373 != NGX_OK) | |
374 { | |
375 err = ngx_errno; | |
376 failed = ngx_set_file_time_n; | |
377 name = temp->data; | |
378 | |
379 goto failed; | |
380 } | |
381 } | |
382 } | |
383 | |
669 | 384 failed = ngx_rename_file_n; |
385 name = path.data; | |
386 | |
633 | 387 if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) { |
388 goto ok; | |
389 } | |
390 | |
391 err = ngx_errno; | |
392 | |
637 | 393 if (err == NGX_ENOENT) { |
394 | |
395 if (dlcf->create_full_put_path) { | |
669 | 396 err = ngx_create_full_path(path.data, dlcf->access); |
637 | 397 |
398 if (err == 0) { | |
399 if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) { | |
400 goto ok; | |
401 } | |
402 | |
403 err = ngx_errno; | |
404 } | |
405 } | |
406 } | |
407 | |
633 | 408 #if (NGX_WIN32) |
409 | |
410 if (err == NGX_EEXIST) { | |
411 if (ngx_win32_rename_file(temp, &path, r->pool) != NGX_ERROR) { | |
412 | |
413 if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) { | |
414 goto ok; | |
415 } | |
416 } | |
417 | |
418 err = ngx_errno; | |
419 } | |
420 | |
681 | 421 #endif |
669 | 422 |
423 failed: | |
424 | |
661 | 425 if (ngx_delete_file(temp->data) == NGX_FILE_ERROR) { |
426 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, | |
427 ngx_delete_file_n " \"%s\" failed", | |
428 temp->data); | |
429 } | |
430 | |
669 | 431 ngx_http_finalize_request(r, |
432 ngx_http_dav_error(r, err, NGX_HTTP_CONFLICT, failed, name)); | |
433 | |
633 | 434 return; |
435 | |
436 ok: | |
437 | |
438 if (status == NGX_HTTP_CREATED) { | |
637 | 439 if (ngx_http_dav_location(r, path.data) != NGX_OK) { |
633 | 440 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
441 return; | |
442 } | |
639 | 443 |
444 r->headers_out.content_length_n = 0; | |
633 | 445 } |
446 | |
447 r->headers_out.status = status; | |
448 r->header_only = 1; | |
449 | |
450 ngx_http_finalize_request(r, ngx_http_send_header(r)); | |
451 return; | |
452 } | |
453 | |
454 | |
637 | 455 static ngx_int_t |
456 ngx_http_dav_error(ngx_http_request_t *r, ngx_err_t err, ngx_int_t not_found, | |
457 char *failed, u_char *path) | |
458 { | |
459 ngx_int_t rc; | |
460 ngx_uint_t level; | |
461 | |
462 if (err == NGX_ENOENT || err == NGX_ENOTDIR || err == NGX_ENAMETOOLONG) { | |
463 level = NGX_LOG_ERR; | |
464 rc = not_found; | |
465 | |
466 } else if (err == NGX_EACCES || err == NGX_EPERM) { | |
467 level = NGX_LOG_ERR; | |
468 rc = NGX_HTTP_FORBIDDEN; | |
469 | |
470 } else if (err == NGX_EEXIST) { | |
471 level = NGX_LOG_ERR; | |
472 rc = NGX_HTTP_NOT_ALLOWED; | |
473 | |
474 } else if (err == NGX_ENOSPC) { | |
475 level = NGX_LOG_CRIT; | |
476 rc = NGX_HTTP_INSUFFICIENT_STORAGE; | |
477 | |
478 } else { | |
479 level = NGX_LOG_CRIT; | |
480 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; | |
481 } | |
482 | |
483 ngx_log_error(level, r->connection->log, err, | |
484 "%s \"%s\" failed", failed, path); | |
485 | |
486 return rc; | |
487 } | |
488 | |
489 | |
490 static ngx_int_t | |
491 ngx_http_dav_location(ngx_http_request_t *r, u_char *path) | |
492 { | |
493 u_char *location; | |
494 ngx_http_core_loc_conf_t *clcf; | |
495 | |
496 r->headers_out.location = ngx_palloc(r->pool, sizeof(ngx_table_elt_t)); | |
497 if (r->headers_out.location == NULL) { | |
498 return NGX_ERROR; | |
499 } | |
500 | |
501 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
502 | |
503 if (!clcf->alias && clcf->root_lengths == NULL) { | |
504 location = path + clcf->root.len; | |
505 | |
506 } else { | |
507 location = ngx_palloc(r->pool, r->uri.len); | |
508 if (location == NULL) { | |
509 return NGX_ERROR; | |
510 } | |
511 | |
512 ngx_memcpy(location, r->uri.data, r->uri.len); | |
513 } | |
514 | |
515 /* | |
516 * we do not need to set the r->headers_out.location->hash and | |
517 * r->headers_out.location->key fields | |
518 */ | |
519 | |
520 r->headers_out.location->value.len = r->uri.len; | |
521 r->headers_out.location->value.data = location; | |
522 | |
523 return NGX_OK; | |
524 } | |
525 | |
526 | |
669 | 527 static char * |
528 ngx_http_dav_access(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
529 { | |
530 ngx_http_dav_loc_conf_t *lcf = conf; | |
531 | |
532 u_char *p; | |
533 ngx_str_t *value; | |
534 ngx_uint_t i, right, shift; | |
535 | |
536 if (lcf->access != NGX_CONF_UNSET_UINT) { | |
537 return "is duplicate"; | |
538 } | |
539 | |
540 value = cf->args->elts; | |
541 | |
542 lcf->access = 0700; | |
543 | |
920 | 544 for (i = 1; i < cf->args->nelts; i++) { |
669 | 545 |
546 p = value[i].data; | |
547 | |
548 if (ngx_strncmp(p, "user:", sizeof("user:") - 1) == 0) { | |
549 shift = 6; | |
550 p += sizeof("user:") - 1; | |
551 | |
552 } else if (ngx_strncmp(p, "group:", sizeof("group:") - 1) == 0) { | |
553 shift = 3; | |
554 p += sizeof("group:") - 1; | |
555 | |
556 } else if (ngx_strncmp(p, "all:", sizeof("all:") - 1) == 0) { | |
557 shift = 0; | |
558 p += sizeof("all:") - 1; | |
559 | |
560 } else { | |
561 goto invalid; | |
562 } | |
563 | |
564 if (ngx_strcmp(p, "rw") == 0) { | |
565 right = 7; | |
566 | |
567 } else if (ngx_strcmp(p, "r") == 0) { | |
568 right = 5; | |
569 | |
570 } else { | |
571 goto invalid; | |
572 } | |
573 | |
574 lcf->access += right << shift; | |
575 } | |
576 | |
577 return NGX_CONF_OK; | |
578 | |
579 invalid: | |
580 | |
581 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
582 "invalid value \"%V\"", &value[i]); | |
583 return NGX_CONF_ERROR; | |
584 } | |
585 | |
586 | |
633 | 587 static void * |
588 ngx_http_dav_create_loc_conf(ngx_conf_t *cf) | |
589 { | |
590 ngx_http_dav_loc_conf_t *conf; | |
591 | |
592 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_dav_loc_conf_t)); | |
593 if (conf == NULL) { | |
594 return NGX_CONF_ERROR; | |
595 } | |
596 | |
597 /* | |
598 * set by ngx_pcalloc(): | |
599 * | |
600 * conf->methods = 0; | |
601 */ | |
602 | |
637 | 603 conf->create_full_put_path = NGX_CONF_UNSET; |
669 | 604 conf->access = NGX_CONF_UNSET_UINT; |
637 | 605 |
633 | 606 return conf; |
607 } | |
608 | |
609 | |
610 static char * | |
611 ngx_http_dav_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) | |
612 { | |
613 ngx_http_dav_loc_conf_t *prev = parent; | |
614 ngx_http_dav_loc_conf_t *conf = child; | |
615 | |
616 ngx_conf_merge_bitmask_value(conf->methods, prev->methods, | |
637 | 617 (NGX_CONF_BITMASK_SET|NGX_HTTP_DAV_OFF)); |
618 | |
619 ngx_conf_merge_value(conf->create_full_put_path, prev->create_full_put_path, | |
620 0); | |
633 | 621 |
669 | 622 ngx_conf_merge_uint_value(conf->access, prev->access, 0600); |
623 | |
633 | 624 return NGX_CONF_OK; |
625 } | |
626 | |
627 | |
628 static ngx_int_t | |
681 | 629 ngx_http_dav_init(ngx_conf_t *cf) |
633 | 630 { |
631 ngx_http_handler_pt *h; | |
632 ngx_http_core_main_conf_t *cmcf; | |
633 | |
681 | 634 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); |
633 | 635 |
636 h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers); | |
637 if (h == NULL) { | |
638 return NGX_ERROR; | |
639 } | |
640 | |
641 *h = ngx_http_dav_handler; | |
642 | |
643 return NGX_OK; | |
644 } |