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)