comparison src/http/modules/ngx_http_autoindex_module.c @ 4192:61e4af19df9f

Autoindex: escape '?' in file names. For files with '?' in their names autoindex generated links with '?' not escaped. This resulted in effectively truncated links as '?' indicates query string start. This is an updated version of the patch originally posted at [1]. It introduces generic NGX_ESCAPE_URI_COMPONENT which escapes everything but unreserved characters as per RFC 3986. This approach also renders unneeded special colon processing (as colon is percent-encoded now), it's dropped accordingly. [1] http://nginx.org/pipermail/nginx-devel/2010-February/000112.html Reported by Konstantin Leonov.
author Maxim Dounin <mdounin@mdounin.ru>
date Tue, 11 Oct 2011 17:56:51 +0000
parents 84905c7b2aa7
children 63aa6ab94630
comparison
equal deleted inserted replaced
4191:08d8af70760c 4192:61e4af19df9f
26 ngx_str_t name; 26 ngx_str_t name;
27 size_t utf_len; 27 size_t utf_len;
28 size_t escape; 28 size_t escape;
29 29
30 unsigned dir:1; 30 unsigned dir:1;
31 unsigned colon:1;
32 31
33 time_t mtime; 32 time_t mtime;
34 off_t size; 33 off_t size;
35 } ngx_http_autoindex_entry_t; 34 } ngx_http_autoindex_entry_t;
36 35
336 } 335 }
337 336
338 ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1); 337 ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1);
339 338
340 entry->escape = 2 * ngx_escape_uri(NULL, ngx_de_name(&dir), len, 339 entry->escape = 2 * ngx_escape_uri(NULL, ngx_de_name(&dir), len,
341 NGX_ESCAPE_HTML); 340 NGX_ESCAPE_URI_COMPONENT);
342 341
343 if (utf8) { 342 if (utf8) {
344 entry->utf_len = ngx_utf8_length(entry->name.data, entry->name.len); 343 entry->utf_len = ngx_utf8_length(entry->name.data, entry->name.len);
345 } else { 344 } else {
346 entry->utf_len = len; 345 entry->utf_len = len;
347 } 346 }
348
349 entry->colon = (ngx_strchr(entry->name.data, ':') != NULL);
350 347
351 entry->dir = ngx_de_is_dir(&dir); 348 entry->dir = ngx_de_is_dir(&dir);
352 entry->mtime = ngx_de_mtime(&dir); 349 entry->mtime = ngx_de_mtime(&dir);
353 entry->size = ngx_de_size(&dir); 350 entry->size = ngx_de_size(&dir);
354 } 351 }
371 for (i = 0; i < entries.nelts; i++) { 368 for (i = 0; i < entries.nelts; i++) {
372 len += sizeof("<a href=\"") - 1 369 len += sizeof("<a href=\"") - 1
373 + entry[i].name.len + entry[i].escape 370 + entry[i].name.len + entry[i].escape
374 + 1 /* 1 is for "/" */ 371 + 1 /* 1 is for "/" */
375 + sizeof("\">") - 1 372 + sizeof("\">") - 1
376 + entry[i].name.len - entry[i].utf_len + entry[i].colon * 2 373 + entry[i].name.len - entry[i].utf_len
377 + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof("&gt;") - 2 374 + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof("&gt;") - 2
378 + sizeof("</a>") - 1 375 + sizeof("</a>") - 1
379 + sizeof(" 28-Sep-1970 12:00 ") - 1 376 + sizeof(" 28-Sep-1970 12:00 ") - 1
380 + 20 /* the file size */ 377 + 20 /* the file size */
381 + 2; 378 + 2;
404 tp = ngx_timeofday(); 401 tp = ngx_timeofday();
405 402
406 for (i = 0; i < entries.nelts; i++) { 403 for (i = 0; i < entries.nelts; i++) {
407 b->last = ngx_cpymem(b->last, "<a href=\"", sizeof("<a href=\"") - 1); 404 b->last = ngx_cpymem(b->last, "<a href=\"", sizeof("<a href=\"") - 1);
408 405
409 if (entry[i].colon) {
410 *b->last++ = '.';
411 *b->last++ = '/';
412 }
413
414 if (entry[i].escape) { 406 if (entry[i].escape) {
415 ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len, 407 ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len,
416 NGX_ESCAPE_HTML); 408 NGX_ESCAPE_URI_COMPONENT);
417 409
418 b->last += entry[i].name.len + entry[i].escape; 410 b->last += entry[i].name.len + entry[i].escape;
419 411
420 } else { 412 } else {
421 b->last = ngx_cpymem(b->last, entry[i].name.data, 413 b->last = ngx_cpymem(b->last, entry[i].name.data,