]> git.kaiwu.me - nginx.git/commitdiff
Autoindex: escape '?' in file names.
authorMaxim Dounin <mdounin@mdounin.ru>
Tue, 11 Oct 2011 17:56:51 +0000 (17:56 +0000)
committerMaxim Dounin <mdounin@mdounin.ru>
Tue, 11 Oct 2011 17:56:51 +0000 (17:56 +0000)
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.

src/core/ngx_string.c
src/core/ngx_string.h
src/http/modules/ngx_http_autoindex_module.c

index 75bc6578d4c4da53885f92b76443333dd9195080..8f29e9070054b6e2c3a7e1070c08d81ee6fcb89c 100644 (file)
@@ -1374,6 +1374,26 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
                     /*  ~}| {zyx wvut srqp  onml kjih gfed cba` */
         0x80000000, /* 1000 0000 0000 0000  0000 0000 0000 0000 */
 
+        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+        0xffffffff  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+    };
+
+                    /* not ALPHA, DIGIT, "-", ".", "_", "~" */
+
+    static uint32_t   uri_component[] = {
+        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+
+                    /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
+        0xfc009fff, /* 1111 1100 0000 0000  1001 1111 1111 1111 */
+
+                    /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
+        0x78000001, /* 0111 1000 0000 0000  0000 0000 0000 0001 */
+
+                    /*  ~}| {zyx wvut srqp  onml kjih gfed cba` */
+        0xb8000001, /* 1011 1000 0000 0000  0000 0000 0000 0001 */
+
         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
@@ -1443,7 +1463,7 @@ ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
                     /* mail_auth is the same as memcached */
 
     static uint32_t  *map[] =
-        { uri, args, html, refresh, memcached, memcached };
+        { uri, args, uri_component, html, refresh, memcached, memcached };
 
 
     escape = map[type];
index 2030988d89f69c4ec0c8c6768639a3c5c415a56a..2b9c59a5e62d6c40660fed5c23aedb51933bb8b4 100644 (file)
@@ -189,12 +189,13 @@ size_t ngx_utf8_length(u_char *p, size_t n);
 u_char *ngx_utf8_cpystrn(u_char *dst, u_char *src, size_t n, size_t len);
 
 
-#define NGX_ESCAPE_URI         0
-#define NGX_ESCAPE_ARGS        1
-#define NGX_ESCAPE_HTML        2
-#define NGX_ESCAPE_REFRESH     3
-#define NGX_ESCAPE_MEMCACHED   4
-#define NGX_ESCAPE_MAIL_AUTH   5
+#define NGX_ESCAPE_URI            0
+#define NGX_ESCAPE_ARGS           1
+#define NGX_ESCAPE_URI_COMPONENT  2
+#define NGX_ESCAPE_HTML           3
+#define NGX_ESCAPE_REFRESH        4
+#define NGX_ESCAPE_MEMCACHED      5
+#define NGX_ESCAPE_MAIL_AUTH      6
 
 #define NGX_UNESCAPE_URI       1
 #define NGX_UNESCAPE_REDIRECT  2
index b6793180698055182a581a7c20dfdc3d373594e1..166b17df8fe2f12567a330bb68a4d0090e7fccc1 100644 (file)
@@ -28,7 +28,6 @@ typedef struct {
     size_t         escape;
 
     unsigned       dir:1;
-    unsigned       colon:1;
 
     time_t         mtime;
     off_t          size;
@@ -338,7 +337,7 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
         ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1);
 
         entry->escape = 2 * ngx_escape_uri(NULL, ngx_de_name(&dir), len,
-                                           NGX_ESCAPE_HTML);
+                                           NGX_ESCAPE_URI_COMPONENT);
 
         if (utf8) {
             entry->utf_len = ngx_utf8_length(entry->name.data, entry->name.len);
@@ -346,8 +345,6 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
             entry->utf_len = len;
         }
 
-        entry->colon = (ngx_strchr(entry->name.data, ':') != NULL);
-
         entry->dir = ngx_de_is_dir(&dir);
         entry->mtime = ngx_de_mtime(&dir);
         entry->size = ngx_de_size(&dir);
@@ -373,7 +370,7 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
             + entry[i].name.len + entry[i].escape
             + 1                                          /* 1 is for "/" */
             + sizeof("\">") - 1
-            + entry[i].name.len - entry[i].utf_len + entry[i].colon * 2
+            + entry[i].name.len - entry[i].utf_len
             + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof("&gt;") - 2
             + sizeof("</a>") - 1
             + sizeof(" 28-Sep-1970 12:00 ") - 1
@@ -406,14 +403,9 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
     for (i = 0; i < entries.nelts; i++) {
         b->last = ngx_cpymem(b->last, "<a href=\"", sizeof("<a href=\"") - 1);
 
-        if (entry[i].colon) {
-            *b->last++ = '.';
-            *b->last++ = '/';
-        }
-
         if (entry[i].escape) {
             ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len,
-                           NGX_ESCAPE_HTML);
+                           NGX_ESCAPE_URI_COMPONENT);
 
             b->last += entry[i].name.len + entry[i].escape;