Mercurial > hg > nginx
comparison src/http/modules/ngx_http_autoindex_module.c @ 557:ecd9c160f25b release-0.3.0
nginx-0.3.0-RELEASE import
*) Change: the 10-days live time limit of worker process was
eliminated. The limit was introduced because of millisecond timers
overflow.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Fri, 07 Oct 2005 13:30:52 +0000 |
parents | 45033d85b30e |
children | 9c2f3ed7a247 |
comparison
equal
deleted
inserted
replaced
556:21a706ff4e1f | 557:ecd9c160f25b |
---|---|
37 ngx_flag_t localtime; | 37 ngx_flag_t localtime; |
38 ngx_flag_t exact_size; | 38 ngx_flag_t exact_size; |
39 } ngx_http_autoindex_loc_conf_t; | 39 } ngx_http_autoindex_loc_conf_t; |
40 | 40 |
41 | 41 |
42 #define NGX_HTTP_AUTOINDEX_NAME_LEN 50 | 42 #define NGX_HTTP_AUTOINDEX_PREALLOCATE 50 |
43 | |
44 #define NGX_HTTP_AUTOINDEX_NAME_LEN 50 | |
43 | 45 |
44 | 46 |
45 static int ngx_libc_cdecl ngx_http_autoindex_cmp_entries(const void *one, | 47 static int ngx_libc_cdecl ngx_http_autoindex_cmp_entries(const void *one, |
46 const void *two); | 48 const void *two); |
47 static ngx_int_t ngx_http_autoindex_error(ngx_http_request_t *r, | 49 static ngx_int_t ngx_http_autoindex_error(ngx_http_request_t *r, |
48 ngx_dir_t *dir, u_char *name); | 50 ngx_dir_t *dir, ngx_str_t *name); |
49 static ngx_int_t ngx_http_autoindex_init(ngx_cycle_t *cycle); | 51 static ngx_int_t ngx_http_autoindex_init(ngx_cycle_t *cycle); |
50 static void *ngx_http_autoindex_create_loc_conf(ngx_conf_t *cf); | 52 static void *ngx_http_autoindex_create_loc_conf(ngx_conf_t *cf); |
51 static char *ngx_http_autoindex_merge_loc_conf(ngx_conf_t *cf, | 53 static char *ngx_http_autoindex_merge_loc_conf(ngx_conf_t *cf, |
52 void *parent, void *child); | 54 void *parent, void *child); |
53 | 55 |
129 | 131 |
130 | 132 |
131 static ngx_int_t | 133 static ngx_int_t |
132 ngx_http_autoindex_handler(ngx_http_request_t *r) | 134 ngx_http_autoindex_handler(ngx_http_request_t *r) |
133 { | 135 { |
134 u_char *last, scale; | 136 u_char *last, *filename, scale; |
135 off_t length; | 137 off_t length; |
136 size_t len, copy; | 138 size_t len, copy, allocated; |
137 ngx_tm_t tm; | 139 ngx_tm_t tm; |
138 ngx_int_t rc, size; | |
139 ngx_uint_t i, level; | |
140 ngx_err_t err; | 140 ngx_err_t err; |
141 ngx_buf_t *b; | 141 ngx_buf_t *b; |
142 ngx_int_t rc, size; | |
143 ngx_str_t path; | |
144 ngx_dir_t dir; | |
145 ngx_uint_t i, level; | |
146 ngx_pool_t *pool; | |
142 ngx_chain_t out; | 147 ngx_chain_t out; |
143 ngx_str_t dname, fname; | |
144 ngx_dir_t dir; | |
145 ngx_pool_t *pool; | |
146 ngx_array_t entries; | 148 ngx_array_t entries; |
147 ngx_http_core_loc_conf_t *clcf; | |
148 ngx_http_autoindex_entry_t *entry; | 149 ngx_http_autoindex_entry_t *entry; |
149 ngx_http_autoindex_loc_conf_t *alcf; | 150 ngx_http_autoindex_loc_conf_t *alcf; |
150 | 151 |
151 static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", | 152 static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", |
152 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; | 153 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; |
164 | 165 |
165 if (!alcf->enable) { | 166 if (!alcf->enable) { |
166 return NGX_DECLINED; | 167 return NGX_DECLINED; |
167 } | 168 } |
168 | 169 |
169 /* TODO: pool should be temporary pool */ | 170 /* NGX_DIR_MASK_LEN is lesser than NGX_HTTP_AUTOINDEX_PREALLOCATE */ |
170 pool = r->pool; | 171 |
171 | 172 last = ngx_http_map_uri_to_path(r, &path, NGX_HTTP_AUTOINDEX_PREALLOCATE); |
172 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | 173 if (last == NULL) { |
173 | 174 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
174 if (clcf->alias) { | 175 } |
175 dname.data = ngx_palloc(pool, clcf->root.len + r->uri.len | 176 |
176 + NGX_DIR_MASK_LEN + 1 | 177 allocated = path.len; |
177 - clcf->name.len); | 178 path.len = last - path.data - 1; |
178 if (dname.data == NULL) { | 179 path.data[path.len] = '\0'; |
179 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
180 } | |
181 | |
182 last = ngx_cpymem(dname.data, clcf->root.data, clcf->root.len); | |
183 last = ngx_cpystrn(last, r->uri.data + clcf->name.len, | |
184 r->uri.len - clcf->name.len + 1); | |
185 | |
186 } else { | |
187 dname.data = ngx_palloc(pool, clcf->root.len + r->uri.len | |
188 + NGX_DIR_MASK_LEN); | |
189 if (dname.data == NULL) { | |
190 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
191 } | |
192 | |
193 last = ngx_cpymem(dname.data, clcf->root.data, clcf->root.len); | |
194 last = ngx_cpystrn(last, r->uri.data, r->uri.len); | |
195 } | |
196 | |
197 dname.len = last - dname.data; | |
198 | 180 |
199 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 181 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
200 "http autoindex: \"%s\"", dname.data); | 182 "http autoindex: \"%s\"", path.data); |
201 | 183 |
202 | 184 if (ngx_open_dir(&path, &dir) == NGX_ERROR) { |
203 if (ngx_open_dir(&dname, &dir) == NGX_ERROR) { | |
204 err = ngx_errno; | 185 err = ngx_errno; |
205 | 186 |
206 if (err == NGX_ENOENT | 187 if (err == NGX_ENOENT |
207 || err == NGX_ENOTDIR | 188 || err == NGX_ENOTDIR |
208 || err == NGX_ENAMETOOLONG) | 189 || err == NGX_ENAMETOOLONG) |
218 level = NGX_LOG_CRIT; | 199 level = NGX_LOG_CRIT; |
219 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; | 200 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; |
220 } | 201 } |
221 | 202 |
222 ngx_log_error(level, r->connection->log, err, | 203 ngx_log_error(level, r->connection->log, err, |
223 ngx_open_dir_n " \"%s\" failed", dname.data); | 204 ngx_open_dir_n " \"%s\" failed", path.data); |
224 | 205 |
225 return rc; | 206 return rc; |
226 } | 207 } |
227 | 208 |
228 #if (NGX_SUPPRESS_WARN) | 209 #if (NGX_SUPPRESS_WARN) |
210 | |
229 /* MSVC thinks 'entries' may be used without having been initialized */ | 211 /* MSVC thinks 'entries' may be used without having been initialized */ |
230 ngx_memzero(&entries, sizeof(ngx_array_t)); | 212 ngx_memzero(&entries, sizeof(ngx_array_t)); |
213 | |
231 #endif | 214 #endif |
232 | 215 |
233 if (ngx_array_init(&entries, pool, 50, sizeof(ngx_http_autoindex_entry_t)) | 216 /* TODO: pool should be temporary pool */ |
234 == NGX_ERROR) | 217 pool = r->pool; |
218 | |
219 if (ngx_array_init(&entries, pool, 40, sizeof(ngx_http_autoindex_entry_t)) | |
220 != NGX_OK) | |
235 { | 221 { |
236 return ngx_http_autoindex_error(r, &dir, dname.data); | 222 return ngx_http_autoindex_error(r, &dir, &path); |
237 } | 223 } |
238 | 224 |
239 r->headers_out.status = NGX_HTTP_OK; | 225 r->headers_out.status = NGX_HTTP_OK; |
240 r->headers_out.content_type.len = sizeof("text/html") - 1; | 226 r->headers_out.content_type.len = sizeof("text/html") - 1; |
241 r->headers_out.content_type.data = (u_char *) "text/html"; | 227 r->headers_out.content_type.data = (u_char *) "text/html"; |
244 | 230 |
245 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { | 231 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { |
246 return rc; | 232 return rc; |
247 } | 233 } |
248 | 234 |
249 fname.len = 0; | 235 filename = path.data; |
250 #if (NGX_SUPPRESS_WARN) | 236 filename[path.len] = '/'; |
251 fname.data = NULL; | |
252 #endif | |
253 | 237 |
254 for ( ;; ) { | 238 for ( ;; ) { |
255 ngx_set_errno(0); | 239 ngx_set_errno(0); |
256 | 240 |
257 if (ngx_read_dir(&dir) == NGX_ERROR) { | 241 if (ngx_read_dir(&dir) == NGX_ERROR) { |
258 err = ngx_errno; | 242 err = ngx_errno; |
259 | 243 |
260 if (err != NGX_ENOMOREFILES) { | 244 if (err != NGX_ENOMOREFILES) { |
261 ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, | 245 ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, |
262 ngx_read_dir_n " \"%s\" failed", dname.data); | 246 ngx_read_dir_n " \"%V\" failed", &path); |
263 return ngx_http_autoindex_error(r, &dir, dname.data); | 247 return ngx_http_autoindex_error(r, &dir, &path); |
264 } | 248 } |
265 | 249 |
266 break; | 250 break; |
267 } | 251 } |
268 | 252 |
275 continue; | 259 continue; |
276 } | 260 } |
277 | 261 |
278 if (!dir.valid_info) { | 262 if (!dir.valid_info) { |
279 | 263 |
280 if (dname.len + 1 + len + 1 > fname.len) { | 264 /* 1 byte for '/' and 1 byte for terminating '\0' */ |
281 fname.len = dname.len + 1 + len + 1 + 32; | 265 |
282 | 266 if (path.len + 1 + len + 1 > allocated) { |
283 fname.data = ngx_palloc(pool, fname.len); | 267 allocated = path.len + 1 + len + 1 |
284 if (fname.data == NULL) { | 268 + NGX_HTTP_AUTOINDEX_PREALLOCATE; |
285 return ngx_http_autoindex_error(r, &dir, dname.data); | 269 |
270 filename = ngx_palloc(pool, allocated); | |
271 if (filename == NULL) { | |
272 return ngx_http_autoindex_error(r, &dir, &path); | |
286 } | 273 } |
287 | 274 |
288 last = ngx_cpystrn(fname.data, dname.data, | 275 last = ngx_cpystrn(filename, path.data, path.len + 1); |
289 dname.len + 1); | |
290 *last++ = '/'; | 276 *last++ = '/'; |
291 } | 277 } |
292 | 278 |
293 ngx_cpystrn(last, ngx_de_name(&dir), len + 1); | 279 ngx_cpystrn(last, ngx_de_name(&dir), len + 1); |
294 | 280 |
295 if (ngx_de_info(fname.data, &dir) == NGX_FILE_ERROR) { | 281 if (ngx_de_info(filename, &dir) == NGX_FILE_ERROR) { |
296 err = ngx_errno; | 282 err = ngx_errno; |
297 | 283 |
298 if (err != NGX_ENOENT) { | 284 if (err != NGX_ENOENT) { |
299 ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, | 285 ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, |
300 ngx_de_info_n " \"%s\" failed", fname.data); | 286 ngx_de_info_n " \"%s\" failed", filename); |
301 return ngx_http_autoindex_error(r, &dir, dname.data); | 287 return ngx_http_autoindex_error(r, &dir, &path); |
302 } | 288 } |
303 | 289 |
304 if (ngx_de_link_info(fname.data, &dir) == NGX_FILE_ERROR) { | 290 if (ngx_de_link_info(filename, &dir) == NGX_FILE_ERROR) { |
305 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, | 291 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, |
306 ngx_de_link_info_n " \"%s\" failed", | 292 ngx_de_link_info_n " \"%s\" failed", |
307 fname.data); | 293 filename); |
308 return ngx_http_autoindex_error(r, &dir, dname.data); | 294 return ngx_http_autoindex_error(r, &dir, &path); |
309 } | 295 } |
310 } | 296 } |
311 } | 297 } |
312 | 298 |
313 entry = ngx_array_push(&entries); | 299 entry = ngx_array_push(&entries); |
314 if (entry == NULL) { | 300 if (entry == NULL) { |
315 return ngx_http_autoindex_error(r, &dir, dname.data); | 301 return ngx_http_autoindex_error(r, &dir, &path); |
316 } | 302 } |
317 | 303 |
318 entry->name.len = len; | 304 entry->name.len = len; |
319 | 305 |
320 entry->name.data = ngx_palloc(pool, len + 1); | 306 entry->name.data = ngx_palloc(pool, len + 1); |
321 if (entry->name.data == NULL) { | 307 if (entry->name.data == NULL) { |
322 return ngx_http_autoindex_error(r, &dir, dname.data); | 308 return ngx_http_autoindex_error(r, &dir, &path); |
323 } | 309 } |
324 | 310 |
325 ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1); | 311 ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1); |
326 | 312 |
327 entry->escape = 2 * ngx_escape_uri(NULL, ngx_de_name(&dir), len, | 313 entry->escape = 2 * ngx_escape_uri(NULL, ngx_de_name(&dir), len, |
338 entry->size = ngx_de_size(&dir); | 324 entry->size = ngx_de_size(&dir); |
339 } | 325 } |
340 | 326 |
341 if (ngx_close_dir(&dir) == NGX_ERROR) { | 327 if (ngx_close_dir(&dir) == NGX_ERROR) { |
342 ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, | 328 ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, |
343 ngx_close_dir_n " \"%s\" failed", dname.data); | 329 ngx_close_dir_n " \"%s\" failed", &path); |
344 } | 330 } |
345 | 331 |
346 len = sizeof(title) - 1 | 332 len = sizeof(title) - 1 |
347 + r->uri.len | 333 + r->uri.len |
348 + sizeof(header) - 1 | 334 + sizeof(header) - 1 |
584 | 570 |
585 #endif | 571 #endif |
586 | 572 |
587 | 573 |
588 static ngx_int_t | 574 static ngx_int_t |
589 ngx_http_autoindex_error(ngx_http_request_t *r, ngx_dir_t *dir, u_char *name) | 575 ngx_http_autoindex_error(ngx_http_request_t *r, ngx_dir_t *dir, ngx_str_t *name) |
590 { | 576 { |
591 if (ngx_close_dir(dir) == NGX_ERROR) { | 577 if (ngx_close_dir(dir) == NGX_ERROR) { |
592 ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, | 578 ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, |
593 ngx_close_dir_n " \"%s\" failed", name); | 579 ngx_close_dir_n " \"%V\" failed", name); |
594 } | 580 } |
595 | 581 |
596 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 582 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
597 } | 583 } |
598 | 584 |