comparison src/http/modules/ngx_http_dav_module.c @ 633:f971949ffb58 release-0.3.38

nginx-0.3.38-RELEASE import *) Feature: the ngx_http_dav_module. *) Change: the ngx_http_perl_module optimizations. Thanks to Sergey Skvortsov. *) Feature: the ngx_http_perl_module supports the $r->request_body_file method. *) Feature: the "client_body_in_file_only" directive. *) Workaround: now on disk overflow nginx tries to write access logs once a second only. Thanks to Anton Yuzhaninov and Maxim Dounin. *) Bugfix: now the "limit_rate" directive more precisely limits rate if rate is more than 100 Kbyte/s. Thanks to ForJest. *) Bugfix: now the IMAP/POP3 proxy escapes the "\r" and "\n" symbols in login and password to pass authorization server. Thanks to Maxim Dounin.
author Igor Sysoev <igor@sysoev.ru>
date Fri, 14 Apr 2006 09:53:38 +0000
parents
children e60fe4cf1d4e
comparison
equal deleted inserted replaced
632:5c60f5f0887d 633:f971949ffb58
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;
16 } ngx_http_dav_loc_conf_t;
17
18
19 static ngx_int_t ngx_http_dav_handler(ngx_http_request_t *r);
20 static void ngx_http_dav_put_handler(ngx_http_request_t *r);
21 static void *ngx_http_dav_create_loc_conf(ngx_conf_t *cf);
22 static char *ngx_http_dav_merge_loc_conf(ngx_conf_t *cf,
23 void *parent, void *child);
24 static ngx_int_t ngx_http_dav_init(ngx_cycle_t *cycle);
25
26
27 static ngx_conf_bitmask_t ngx_http_dav_methods_mask[] = {
28 { ngx_string("off"), NGX_HTTP_DAV_OFF },
29 { ngx_string("put"), NGX_HTTP_PUT },
30 { ngx_string("delete"), NGX_HTTP_DELETE },
31 { ngx_null_string, 0 }
32 };
33
34
35 static ngx_command_t ngx_http_dav_commands[] = {
36
37 { ngx_string("dav_methods"),
38 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
39 ngx_conf_set_bitmask_slot,
40 NGX_HTTP_LOC_CONF_OFFSET,
41 offsetof(ngx_http_dav_loc_conf_t, methods),
42 &ngx_http_dav_methods_mask },
43
44 ngx_null_command
45 };
46
47
48 ngx_http_module_t ngx_http_dav_module_ctx = {
49 NULL, /* preconfiguration */
50 NULL, /* postconfiguration */
51
52 NULL, /* create main configuration */
53 NULL, /* init main configuration */
54
55 NULL, /* create server configuration */
56 NULL, /* merge server configuration */
57
58 ngx_http_dav_create_loc_conf, /* create location configuration */
59 ngx_http_dav_merge_loc_conf /* merge location configuration */
60 };
61
62
63 ngx_module_t ngx_http_dav_module = {
64 NGX_MODULE_V1,
65 &ngx_http_dav_module_ctx, /* module context */
66 ngx_http_dav_commands, /* module directives */
67 NGX_HTTP_MODULE, /* module type */
68 NULL, /* init master */
69 ngx_http_dav_init, /* init module */
70 NULL, /* init process */
71 NULL, /* init thread */
72 NULL, /* exit thread */
73 NULL, /* exit process */
74 NULL, /* exit master */
75 NGX_MODULE_V1_PADDING
76 };
77
78
79 static ngx_int_t
80 ngx_http_dav_handler(ngx_http_request_t *r)
81 {
82 ngx_int_t rc;
83 ngx_str_t path;
84 ngx_http_dav_loc_conf_t *dlcf;
85
86 /* TODO: Win32 */
87 if (r->zero_in_uri) {
88 return NGX_DECLINED;
89 }
90
91 dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module);
92
93 if (!(r->method & dlcf->methods)) {
94 return NGX_DECLINED;
95 }
96
97 switch (r->method) {
98
99 case NGX_HTTP_PUT:
100
101 if (r->uri.data[r->uri.len - 1] == '/') {
102 return NGX_DECLINED;
103 }
104
105 r->request_body_in_file_only = 1;
106 r->request_body_in_persistent_file = 1;
107 r->request_body_delete_incomplete_file = 1;
108 r->request_body_file_group_access = 1;
109
110 rc = ngx_http_read_client_request_body(r, ngx_http_dav_put_handler);
111
112 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
113 return rc;
114 }
115
116 return NGX_DONE;
117
118 case NGX_HTTP_DELETE:
119
120 if (r->uri.data[r->uri.len - 1] == '/') {
121 return NGX_DECLINED;
122 }
123
124 ngx_http_map_uri_to_path(r, &path, 0);
125
126 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
127 "http delete filename: \"%s\"", path.data);
128
129 if (ngx_delete_file(path.data) == NGX_FILE_ERROR) {
130 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
131 ngx_delete_file_n " \"%s\" failed", path.data);
132
133 return NGX_HTTP_INTERNAL_SERVER_ERROR;
134 }
135
136 return NGX_HTTP_NO_CONTENT;
137 }
138
139 return NGX_DECLINED;
140 }
141
142
143 static void
144 ngx_http_dav_put_handler(ngx_http_request_t *r)
145 {
146 u_char *location;
147 ngx_err_t err;
148 ngx_str_t *temp, path;
149 ngx_uint_t status;
150 ngx_file_info_t fi;
151 ngx_http_core_loc_conf_t *clcf;
152
153 ngx_http_map_uri_to_path(r, &path, 0);
154
155 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
156 "http put filename: \"%s\"", path.data);
157
158 temp = &r->request_body->temp_file->file.name;
159
160 if (ngx_file_info(path.data, &fi) == -1) {
161 status = NGX_HTTP_CREATED;
162
163 } else {
164 status = NGX_HTTP_NO_CONTENT;
165 }
166
167 if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) {
168 goto ok;
169 }
170
171 err = ngx_errno;
172
173 #if (NGX_WIN32)
174
175 if (err == NGX_EEXIST) {
176 if (ngx_win32_rename_file(temp, &path, r->pool) != NGX_ERROR) {
177
178 if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) {
179 goto ok;
180 }
181 }
182
183 err = ngx_errno;
184 }
185
186 #endif
187
188 ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
189 ngx_rename_file_n " \"%s\" failed", path.data);
190
191 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
192 return;
193
194 ok:
195
196 if (status == NGX_HTTP_CREATED) {
197
198 r->headers_out.location = ngx_palloc(r->pool, sizeof(ngx_table_elt_t));
199 if (r->headers_out.location == NULL) {
200 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
201 return;
202 }
203
204 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
205
206 if (!clcf->alias && clcf->root_lengths == NULL) {
207 location = path.data + clcf->root.len;
208
209 } else {
210 location = ngx_palloc(r->pool, r->uri.len);
211 if (location == NULL) {
212 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
213 return;
214 }
215
216 ngx_memcpy(location, r->uri.data, r->uri.len);
217 }
218
219 /*
220 * we do not need to set the r->headers_out.location->hash and
221 * r->headers_out.location->key fields
222 */
223
224 r->headers_out.location->value.len = r->uri.len;
225 r->headers_out.location->value.data = location;
226
227 }
228
229 r->headers_out.status = status;
230 r->header_only = 1;
231
232 ngx_http_finalize_request(r, ngx_http_send_header(r));
233 return;
234 }
235
236
237 static void *
238 ngx_http_dav_create_loc_conf(ngx_conf_t *cf)
239 {
240 ngx_http_dav_loc_conf_t *conf;
241
242 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_dav_loc_conf_t));
243 if (conf == NULL) {
244 return NGX_CONF_ERROR;
245 }
246
247 /*
248 * set by ngx_pcalloc():
249 *
250 * conf->methods = 0;
251 */
252
253 return conf;
254 }
255
256
257 static char *
258 ngx_http_dav_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
259 {
260 ngx_http_dav_loc_conf_t *prev = parent;
261 ngx_http_dav_loc_conf_t *conf = child;
262
263 ngx_conf_merge_bitmask_value(conf->methods, prev->methods,
264 (NGX_CONF_BITMASK_SET|NGX_HTTP_DAV_OFF));
265
266 return NGX_CONF_OK;
267 }
268
269
270 static ngx_int_t
271 ngx_http_dav_init(ngx_cycle_t *cycle)
272 {
273 ngx_http_handler_pt *h;
274 ngx_http_core_main_conf_t *cmcf;
275
276 cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
277
278 h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
279 if (h == NULL) {
280 return NGX_ERROR;
281 }
282
283 *h = ngx_http_dav_handler;
284
285 return NGX_OK;
286 }