diff src/http/ngx_http_parse.c @ 254:f3ec44f4a53b NGINX_0_4_12

nginx 0.4.12 *) Feature: the ngx_http_perl_module supports the $r->variable method. *) Bugfix: if a big static file was included using SSI in a response, then the response may be transferred incomplete. *) Bugfix: nginx did not omit the "#fragment" part in URI.
author Igor Sysoev <http://sysoev.ru>
date Tue, 31 Oct 2006 00:00:00 +0300
parents fbf2b2f66c9f
children 2e9c57a5e50a
line wrap: on
line diff
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -9,6 +9,29 @@
 #include <ngx_http.h>
 
 
+static uint32_t  usual[] = {
+    0xffffdbfe, /* 1111 1111 1111 1111  1101 1011 1111 1110 */
+
+                /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
+    0x7fff37d6, /* 0111 1111 1111 1111  0011 0111 1101 0110 */
+
+                /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
+#if (NGX_WIN32)
+    0xefffffff, /* 1110 1111 1111 1111  1111 1111 1111 1111 */
+#else
+    0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+#endif
+
+                /*  ~}| {zyx wvut srqp  onml kjih gfed cba` */
+    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 */
+    0xffffffff  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+};
+
+
 /* gcc, icc, msvc and others compile these switches as an jump table */
 
 ngx_int_t
@@ -18,7 +41,6 @@ ngx_http_parse_request_line(ngx_http_req
     enum {
         sw_start = 0,
         sw_method,
-        sw_space_after_method,
         sw_spaces_before_uri,
         sw_schema,
         sw_schema_slash,
@@ -118,20 +140,15 @@ ngx_http_parse_request_line(ngx_http_req
 
             break;
 
-        /* single space after method */
-        case sw_space_after_method:
-            switch (ch) {
-            case ' ':
-                state = sw_spaces_before_uri;
-                break;
-            default:
-                return NGX_HTTP_PARSE_INVALID_METHOD;
-            }
-            break;
-
         /* space* before URI */
         case sw_spaces_before_uri:
 
+            if (ch == '/' ){
+                r->uri_start = p;
+                state = sw_after_slash_in_uri;
+                break;
+            }
+
             c = (u_char) (ch | 0x20);
             if (c >= 'a' && c <= 'z') {
                 r->schema_start = p;
@@ -140,10 +157,6 @@ ngx_http_parse_request_line(ngx_http_req
             }
 
             switch (ch) {
-            case '/':
-                r->uri_start = p;
-                state = sw_after_slash_in_uri;
-                break;
             case ' ':
                 break;
             default:
@@ -196,8 +209,7 @@ ngx_http_parse_request_line(ngx_http_req
                 break;
             }
 
-            if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '-')
-            {
+            if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '-') {
                 break;
             }
 
@@ -235,13 +247,7 @@ ngx_http_parse_request_line(ngx_http_req
         /* check "/.", "//", "%", and "\" (Win32) in URI */
         case sw_after_slash_in_uri:
 
-            c = (u_char) (ch | 0x20);
-            if (c >= 'a' && c <= 'z') {
-                state = sw_check_uri;
-                break;
-            }
-
-            if (ch >= '0' && ch <= '9') {
+            if (usual[ch >> 5] & (1 << (ch & 0x1f))) {
                 state = sw_check_uri;
                 break;
             }
@@ -282,6 +288,10 @@ ngx_http_parse_request_line(ngx_http_req
                 r->args_start = p + 1;
                 state = sw_uri;
                 break;
+            case '#':
+                r->complex_uri = 1;
+                state = sw_uri;
+                break;
             case '+':
                 r->plus_in_uri = 1;
                 break;
@@ -297,12 +307,7 @@ ngx_http_parse_request_line(ngx_http_req
         /* check "/", "%" and "\" (Win32) in URI */
         case sw_check_uri:
 
-            c = (u_char) (ch | 0x20);
-            if (c >= 'a' && c <= 'z') {
-                break;
-            }
-
-            if (ch >= '0' && ch <= '9') {
+            if (usual[ch >> 5] & (1 << (ch & 0x1f))) {
                 break;
             }
 
@@ -341,6 +346,10 @@ ngx_http_parse_request_line(ngx_http_req
                 r->args_start = p + 1;
                 state = sw_uri;
                 break;
+            case '#':
+                r->complex_uri = 1;
+                state = sw_uri;
+                break;
             case '+':
                 r->plus_in_uri = 1;
                 break;
@@ -352,6 +361,11 @@ ngx_http_parse_request_line(ngx_http_req
 
         /* URI */
         case sw_uri:
+
+            if (usual[ch >> 5] & (1 << (ch & 0x1f))) {
+                break;
+            }
+
             switch (ch) {
             case ' ':
                 r->uri_end = p;
@@ -366,6 +380,9 @@ ngx_http_parse_request_line(ngx_http_req
                 r->uri_end = p;
                 r->http_minor = 9;
                 goto done;
+            case '#':
+                r->complex_uri = 1;
+                break;
             case '\0':
                 r->zero_in_uri = 1;
                 break;
@@ -792,6 +809,13 @@ ngx_http_parse_complex_uri(ngx_http_requ
         switch (state) {
 
         case sw_usual:
+
+            if (usual[ch >> 5] & (1 << (ch & 0x1f))) {
+                *u++ = ch;
+                ch = *p++;
+                break;
+            }
+
             switch(ch) {
 #if (NGX_WIN32)
             case '\\':
@@ -822,6 +846,8 @@ ngx_http_parse_complex_uri(ngx_http_requ
                 break;
             case '?':
                 r->args_start = p;
+                goto args;
+            case '#':
                 goto done;
             case '.':
                 r->uri_ext = u + 1;
@@ -833,10 +859,19 @@ ngx_http_parse_complex_uri(ngx_http_requ
                 *u++ = ch;
                 break;
             }
+
             ch = *p++;
             break;
 
         case sw_slash:
+
+            if (usual[ch >> 5] & (1 << (ch & 0x1f))) {
+                state = sw_usual;
+                *u++ = ch;
+                ch = *p++;
+                break;
+            }
+
             switch(ch) {
 #if (NGX_WIN32)
             case '\\':
@@ -853,6 +888,8 @@ ngx_http_parse_complex_uri(ngx_http_requ
                 break;
             case '?':
                 r->args_start = p;
+                goto args;
+            case '#':
                 goto done;
             case '+':
                 r->plus_in_uri = 1;
@@ -861,10 +898,19 @@ ngx_http_parse_complex_uri(ngx_http_requ
                 *u++ = ch;
                 break;
             }
+
             ch = *p++;
             break;
 
         case sw_dot:
+
+            if (usual[ch >> 5] & (1 << (ch & 0x1f))) {
+                state = sw_usual;
+                *u++ = ch;
+                ch = *p++;
+                break;
+            }
+
             switch(ch) {
 #if (NGX_WIN32)
             case '\\':
@@ -883,6 +929,8 @@ ngx_http_parse_complex_uri(ngx_http_requ
                 break;
             case '?':
                 r->args_start = p;
+                goto args;
+            case '#':
                 goto done;
             case '+':
                 r->plus_in_uri = 1;
@@ -891,10 +939,19 @@ ngx_http_parse_complex_uri(ngx_http_requ
                 *u++ = ch;
                 break;
             }
+
             ch = *p++;
             break;
 
         case sw_dot_dot:
+
+            if (usual[ch >> 5] & (1 << (ch & 0x1f))) {
+                state = sw_usual;
+                *u++ = ch;
+                ch = *p++;
+                break;
+            }
+
             switch(ch) {
 #if (NGX_WIN32)
             case '\\':
@@ -915,6 +972,8 @@ ngx_http_parse_complex_uri(ngx_http_requ
                 break;
             case '?':
                 r->args_start = p;
+                goto args;
+            case '#':
                 goto done;
 #if (NGX_WIN32)
             case '.':
@@ -929,11 +988,20 @@ ngx_http_parse_complex_uri(ngx_http_requ
                 *u++ = ch;
                 break;
             }
+
             ch = *p++;
             break;
 
 #if (NGX_WIN32)
         case sw_dot_dot_dot:
+
+            if (usual[ch >> 5] & (1 << (ch & 0x1f))) {
+                state = sw_usual;
+                *u++ = ch;
+                ch = *p++;
+                break;
+            }
+
             switch(ch) {
             case '\\':
             case '/':
@@ -958,6 +1026,8 @@ ngx_http_parse_complex_uri(ngx_http_requ
                 break;
             case '?':
                 r->args_start = p;
+                goto args;
+            case '#':
                 goto done;
             case '+':
                 r->plus_in_uri = 1;
@@ -966,6 +1036,7 @@ ngx_http_parse_complex_uri(ngx_http_requ
                 *u++ = ch;
                 break;
             }
+
             ch = *p++;
             break;
 #endif
@@ -1001,7 +1072,11 @@ ngx_http_parse_complex_uri(ngx_http_requ
                     break;
                 }
 
-                if (ch == '\0') {
+                if (ch == '#') {
+                    *u++ = ch;
+                    ch = *p++;
+
+                } else if (ch == '\0') {
                     r->zero_in_uri = 1;
                 }
 
@@ -1032,7 +1107,31 @@ ngx_http_parse_complex_uri(ngx_http_requ
 done:
 
     r->uri.len = u - r->uri.data;
-    r->uri.data[r->uri.len] = '\0';
+
+    if (r->uri_ext) {
+        r->exten.len = u - r->uri_ext;
+        r->exten.data = r->uri_ext;
+    }
+
+    r->uri_ext = NULL;
+
+    return NGX_OK;
+
+args:
+
+    while (p < r->uri_end) {
+        if (*p++ != '#') {
+            continue;
+        }
+
+        r->args.len = p - 1 - r->args_start;
+        r->args.data = r->args_start;
+        r->args_start = NULL;
+
+        break;
+    }
+
+    r->uri.len = u - r->uri.data;
 
     if (r->uri_ext) {
         r->exten.len = u - r->uri_ext;
@@ -1072,6 +1171,10 @@ ngx_http_parse_unsafe_uri(ngx_http_reque
 
         ch = *p++;
 
+        if (usual[ch >> 5] & (1 << (ch & 0x1f))) {
+            continue;
+        }
+
         if (ch == '?') {
             args->len = len - 1;
             args->data = p;
@@ -1085,17 +1188,12 @@ ngx_http_parse_unsafe_uri(ngx_http_reque
             continue;
         }
 
-        if (ch != '/'
+        if ((ch == '/'
 #if (NGX_WIN32)
-            && ch != '\\'
+             || ch == '\\'
 #endif
-            )
+            ) && len > 2)
         {
-            continue;
-        }
-
-        if (len > 2) {
-
             /* detect "/../" */
 
             if (p[0] == '.' && p[1] == '.' && p[2] == '/') {