Mercurial > hg > nginx
comparison src/http/modules/ngx_http_autoindex_module.c @ 5943:631dee7bfd4e
Autoindex: rendering code moved to a separate function.
No functional changes.
author | Valentin Bartenev <vbart@nginx.com> |
---|---|
date | Fri, 12 Dec 2014 20:25:28 +0300 |
parents | 2cfc095a607a |
children | 33c08d7e2915 |
comparison
equal
deleted
inserted
replaced
5942:4983f7d18fe3 | 5943:631dee7bfd4e |
---|---|
46 #define NGX_HTTP_AUTOINDEX_PREALLOCATE 50 | 46 #define NGX_HTTP_AUTOINDEX_PREALLOCATE 50 |
47 | 47 |
48 #define NGX_HTTP_AUTOINDEX_NAME_LEN 50 | 48 #define NGX_HTTP_AUTOINDEX_NAME_LEN 50 |
49 | 49 |
50 | 50 |
51 static ngx_buf_t *ngx_http_autoindex_html(ngx_http_request_t *r, | |
52 ngx_array_t *entries); | |
51 static int ngx_libc_cdecl ngx_http_autoindex_cmp_entries(const void *one, | 53 static int ngx_libc_cdecl ngx_http_autoindex_cmp_entries(const void *one, |
52 const void *two); | 54 const void *two); |
53 static ngx_int_t ngx_http_autoindex_error(ngx_http_request_t *r, | 55 static ngx_int_t ngx_http_autoindex_error(ngx_http_request_t *r, |
54 ngx_dir_t *dir, ngx_str_t *name); | 56 ngx_dir_t *dir, ngx_str_t *name); |
55 static ngx_int_t ngx_http_autoindex_init(ngx_conf_t *cf); | 57 static ngx_int_t ngx_http_autoindex_init(ngx_conf_t *cf); |
114 NULL, /* exit master */ | 116 NULL, /* exit master */ |
115 NGX_MODULE_V1_PADDING | 117 NGX_MODULE_V1_PADDING |
116 }; | 118 }; |
117 | 119 |
118 | 120 |
119 static u_char title[] = | |
120 "<html>" CRLF | |
121 "<head><title>Index of " | |
122 ; | |
123 | |
124 | |
125 static u_char header[] = | |
126 "</title></head>" CRLF | |
127 "<body bgcolor=\"white\">" CRLF | |
128 "<h1>Index of " | |
129 ; | |
130 | |
131 static u_char tail[] = | |
132 "</body>" CRLF | |
133 "</html>" CRLF | |
134 ; | |
135 | |
136 | |
137 static ngx_int_t | 121 static ngx_int_t |
138 ngx_http_autoindex_handler(ngx_http_request_t *r) | 122 ngx_http_autoindex_handler(ngx_http_request_t *r) |
139 { | 123 { |
140 u_char *last, *filename, scale; | 124 u_char *last, *filename; |
141 off_t length; | 125 size_t len, allocated, root; |
142 size_t len, char_len, escape_html, allocated, root; | |
143 ngx_tm_t tm; | |
144 ngx_err_t err; | 126 ngx_err_t err; |
145 ngx_buf_t *b; | 127 ngx_buf_t *b; |
146 ngx_int_t rc, size; | 128 ngx_int_t rc; |
147 ngx_str_t path; | 129 ngx_str_t path; |
148 ngx_dir_t dir; | 130 ngx_dir_t dir; |
149 ngx_uint_t i, level, utf8; | 131 ngx_uint_t level; |
150 ngx_pool_t *pool; | 132 ngx_pool_t *pool; |
151 ngx_time_t *tp; | |
152 ngx_chain_t out; | 133 ngx_chain_t out; |
153 ngx_array_t entries; | 134 ngx_array_t entries; |
154 ngx_http_autoindex_entry_t *entry; | 135 ngx_http_autoindex_entry_t *entry; |
155 ngx_http_autoindex_loc_conf_t *alcf; | 136 ngx_http_autoindex_loc_conf_t *alcf; |
156 | |
157 static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", | |
158 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; | |
159 | 137 |
160 if (r->uri.data[r->uri.len - 1] != '/') { | 138 if (r->uri.data[r->uri.len - 1] != '/') { |
161 return NGX_DECLINED; | 139 return NGX_DECLINED; |
162 } | 140 } |
163 | 141 |
247 } | 225 } |
248 | 226 |
249 filename = path.data; | 227 filename = path.data; |
250 filename[path.len] = '/'; | 228 filename[path.len] = '/'; |
251 | 229 |
252 if (r->headers_out.charset.len == 5 | |
253 && ngx_strncasecmp(r->headers_out.charset.data, (u_char *) "utf-8", 5) | |
254 == 0) | |
255 { | |
256 utf8 = 1; | |
257 | |
258 } else { | |
259 utf8 = 0; | |
260 } | |
261 | |
262 for ( ;; ) { | 230 for ( ;; ) { |
263 ngx_set_errno(0); | 231 ngx_set_errno(0); |
264 | 232 |
265 if (ngx_read_dir(&dir) == NGX_ERROR) { | 233 if (ngx_read_dir(&dir) == NGX_ERROR) { |
266 err = ngx_errno; | 234 err = ngx_errno; |
337 return ngx_http_autoindex_error(r, &dir, &path); | 305 return ngx_http_autoindex_error(r, &dir, &path); |
338 } | 306 } |
339 | 307 |
340 ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1); | 308 ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1); |
341 | 309 |
342 entry->escape = 2 * ngx_escape_uri(NULL, ngx_de_name(&dir), len, | |
343 NGX_ESCAPE_URI_COMPONENT); | |
344 | |
345 entry->escape_html = ngx_escape_html(NULL, entry->name.data, | |
346 entry->name.len); | |
347 | |
348 if (utf8) { | |
349 entry->utf_len = ngx_utf8_length(entry->name.data, entry->name.len); | |
350 } else { | |
351 entry->utf_len = len; | |
352 } | |
353 | |
354 entry->dir = ngx_de_is_dir(&dir); | 310 entry->dir = ngx_de_is_dir(&dir); |
355 entry->mtime = ngx_de_mtime(&dir); | 311 entry->mtime = ngx_de_mtime(&dir); |
356 entry->size = ngx_de_size(&dir); | 312 entry->size = ngx_de_size(&dir); |
357 } | 313 } |
358 | 314 |
359 if (ngx_close_dir(&dir) == NGX_ERROR) { | 315 if (ngx_close_dir(&dir) == NGX_ERROR) { |
360 ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, | 316 ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, |
361 ngx_close_dir_n " \"%V\" failed", &path); | 317 ngx_close_dir_n " \"%V\" failed", &path); |
318 } | |
319 | |
320 if (entries.nelts > 1) { | |
321 ngx_qsort(entries.elts, (size_t) entries.nelts, | |
322 sizeof(ngx_http_autoindex_entry_t), | |
323 ngx_http_autoindex_cmp_entries); | |
324 } | |
325 | |
326 b = ngx_http_autoindex_html(r, &entries); | |
327 | |
328 if (b == NULL) { | |
329 return NGX_ERROR; | |
330 } | |
331 | |
332 /* TODO: free temporary pool */ | |
333 | |
334 if (r == r->main) { | |
335 b->last_buf = 1; | |
336 } | |
337 | |
338 b->last_in_chain = 1; | |
339 | |
340 out.buf = b; | |
341 out.next = NULL; | |
342 | |
343 return ngx_http_output_filter(r, &out); | |
344 } | |
345 | |
346 | |
347 static ngx_buf_t * | |
348 ngx_http_autoindex_html(ngx_http_request_t *r, ngx_array_t *entries) | |
349 { | |
350 u_char *last, scale; | |
351 off_t length; | |
352 size_t len, char_len, escape_html; | |
353 ngx_tm_t tm; | |
354 ngx_buf_t *b; | |
355 ngx_int_t size; | |
356 ngx_uint_t i, utf8; | |
357 ngx_time_t *tp; | |
358 ngx_http_autoindex_entry_t *entry; | |
359 ngx_http_autoindex_loc_conf_t *alcf; | |
360 | |
361 static u_char title[] = | |
362 "<html>" CRLF | |
363 "<head><title>Index of " | |
364 ; | |
365 | |
366 static u_char header[] = | |
367 "</title></head>" CRLF | |
368 "<body bgcolor=\"white\">" CRLF | |
369 "<h1>Index of " | |
370 ; | |
371 | |
372 static u_char tail[] = | |
373 "</body>" CRLF | |
374 "</html>" CRLF | |
375 ; | |
376 | |
377 static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", | |
378 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; | |
379 | |
380 if (r->headers_out.charset.len == 5 | |
381 && ngx_strncasecmp(r->headers_out.charset.data, (u_char *) "utf-8", 5) | |
382 == 0) | |
383 { | |
384 utf8 = 1; | |
385 | |
386 } else { | |
387 utf8 = 0; | |
362 } | 388 } |
363 | 389 |
364 escape_html = ngx_escape_html(NULL, r->uri.data, r->uri.len); | 390 escape_html = ngx_escape_html(NULL, r->uri.data, r->uri.len); |
365 | 391 |
366 len = sizeof(title) - 1 | 392 len = sizeof(title) - 1 |
370 + sizeof("</h1>") - 1 | 396 + sizeof("</h1>") - 1 |
371 + sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1 | 397 + sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1 |
372 + sizeof("</pre><hr>") - 1 | 398 + sizeof("</pre><hr>") - 1 |
373 + sizeof(tail) - 1; | 399 + sizeof(tail) - 1; |
374 | 400 |
375 entry = entries.elts; | 401 entry = entries->elts; |
376 for (i = 0; i < entries.nelts; i++) { | 402 for (i = 0; i < entries->nelts; i++) { |
403 entry[i].escape = 2 * ngx_escape_uri(NULL, entry[i].name.data, | |
404 entry[i].name.len, | |
405 NGX_ESCAPE_URI_COMPONENT); | |
406 | |
407 entry[i].escape_html = ngx_escape_html(NULL, entry[i].name.data, | |
408 entry[i].name.len); | |
409 | |
410 if (utf8) { | |
411 entry[i].utf_len = ngx_utf8_length(entry[i].name.data, | |
412 entry[i].name.len); | |
413 } else { | |
414 entry[i].utf_len = entry[i].name.len; | |
415 } | |
416 | |
377 len += sizeof("<a href=\"") - 1 | 417 len += sizeof("<a href=\"") - 1 |
378 + entry[i].name.len + entry[i].escape | 418 + entry[i].name.len + entry[i].escape |
379 + 1 /* 1 is for "/" */ | 419 + 1 /* 1 is for "/" */ |
380 + sizeof("\">") - 1 | 420 + sizeof("\">") - 1 |
381 + entry[i].name.len - entry[i].utf_len | 421 + entry[i].name.len - entry[i].utf_len |
387 + 2; | 427 + 2; |
388 } | 428 } |
389 | 429 |
390 b = ngx_create_temp_buf(r->pool, len); | 430 b = ngx_create_temp_buf(r->pool, len); |
391 if (b == NULL) { | 431 if (b == NULL) { |
392 return NGX_ERROR; | 432 return NULL; |
393 } | |
394 | |
395 if (entries.nelts > 1) { | |
396 ngx_qsort(entry, (size_t) entries.nelts, | |
397 sizeof(ngx_http_autoindex_entry_t), | |
398 ngx_http_autoindex_cmp_entries); | |
399 } | 433 } |
400 | 434 |
401 b->last = ngx_cpymem(b->last, title, sizeof(title) - 1); | 435 b->last = ngx_cpymem(b->last, title, sizeof(title) - 1); |
402 | 436 |
403 if (escape_html) { | 437 if (escape_html) { |
414 b->last = ngx_cpymem(b->last, "</h1>", sizeof("</h1>") - 1); | 448 b->last = ngx_cpymem(b->last, "</h1>", sizeof("</h1>") - 1); |
415 | 449 |
416 b->last = ngx_cpymem(b->last, "<hr><pre><a href=\"../\">../</a>" CRLF, | 450 b->last = ngx_cpymem(b->last, "<hr><pre><a href=\"../\">../</a>" CRLF, |
417 sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1); | 451 sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1); |
418 | 452 |
453 alcf = ngx_http_get_module_loc_conf(r, ngx_http_autoindex_module); | |
419 tp = ngx_timeofday(); | 454 tp = ngx_timeofday(); |
420 | 455 |
421 for (i = 0; i < entries.nelts; i++) { | 456 for (i = 0; i < entries->nelts; i++) { |
422 b->last = ngx_cpymem(b->last, "<a href=\"", sizeof("<a href=\"") - 1); | 457 b->last = ngx_cpymem(b->last, "<a href=\"", sizeof("<a href=\"") - 1); |
423 | 458 |
424 if (entry[i].escape) { | 459 if (entry[i].escape) { |
425 ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len, | 460 ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len, |
426 NGX_ESCAPE_URI_COMPONENT); | 461 NGX_ESCAPE_URI_COMPONENT); |
563 | 598 |
564 *b->last++ = CR; | 599 *b->last++ = CR; |
565 *b->last++ = LF; | 600 *b->last++ = LF; |
566 } | 601 } |
567 | 602 |
568 /* TODO: free temporary pool */ | |
569 | |
570 b->last = ngx_cpymem(b->last, "</pre><hr>", sizeof("</pre><hr>") - 1); | 603 b->last = ngx_cpymem(b->last, "</pre><hr>", sizeof("</pre><hr>") - 1); |
571 | 604 |
572 b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1); | 605 b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1); |
573 | 606 |
574 if (r == r->main) { | 607 return b; |
575 b->last_buf = 1; | |
576 } | |
577 | |
578 b->last_in_chain = 1; | |
579 | |
580 out.buf = b; | |
581 out.next = NULL; | |
582 | |
583 return ngx_http_output_filter(r, &out); | |
584 } | 608 } |
585 | 609 |
586 | 610 |
587 static int ngx_libc_cdecl | 611 static int ngx_libc_cdecl |
588 ngx_http_autoindex_cmp_entries(const void *one, const void *two) | 612 ngx_http_autoindex_cmp_entries(const void *one, const void *two) |