diff src/http/modules/ngx_http_log_module.c @ 376:edf1cb6c328e NGINX_0_7_0

nginx 0.7.0 *) Change: now the 0x00-0x1F, '"' and '\' characters are escaped as \xXX in an access_log. Thanks to Maxim Dounin. *) Change: now nginx allows several "Host" request header line. *) Feature: the "modified" flag in the "expires" directive. *) Feature: the $uid_got and $uid_set variables may be used at any request processing stage. *) Feature: the $hostname variable. Thanks to Andrei Nigmatulin. *) Feature: DESTDIR support. Thanks to Todd A. Fisher and Andras Voroskoi. *) Bugfix: a segmentation fault might occur in worker process on Linux, if keepalive was enabled.
author Igor Sysoev <http://sysoev.ru>
date Mon, 19 May 2008 00:00:00 +0400
parents 05693816539c
children bc21d9cd9c54
line wrap: on
line diff
--- a/src/http/modules/ngx_http_log_module.c
+++ b/src/http/modules/ngx_http_log_module.c
@@ -88,6 +88,7 @@ static size_t ngx_http_log_variable_getl
     uintptr_t data);
 static u_char *ngx_http_log_variable(ngx_http_request_t *r, u_char *buf,
     ngx_http_log_op_t *op);
+static uintptr_t ngx_http_log_escape(u_char *dst, u_char *src, size_t size);
 
 
 static void *ngx_http_log_create_main_conf(ngx_conf_t *cf);
@@ -478,6 +479,7 @@ ngx_http_log_variable_compile(ngx_conf_t
 static size_t
 ngx_http_log_variable_getlen(ngx_http_request_t *r, uintptr_t data)
 {
+    uintptr_t                   len;
     ngx_http_variable_value_t  *value;
 
     value = ngx_http_get_indexed_variable(r, data);
@@ -486,7 +488,11 @@ ngx_http_log_variable_getlen(ngx_http_re
         return 1;
     }
 
-    return value->len;
+    len = ngx_http_log_escape(NULL, value->data, value->len);
+
+    value->escape = len ? 1 : 0;
+
+    return value->len + len * 3;
 }
 
 
@@ -502,7 +508,70 @@ ngx_http_log_variable(ngx_http_request_t
         return buf + 1;
     }
 
-    return ngx_cpymem(buf, value->data, value->len);
+    if (value->escape == 0) {
+        return ngx_cpymem(buf, value->data, value->len);
+
+    } else {
+        return (u_char *) ngx_http_log_escape(buf, value->data, value->len);
+    }
+}
+
+
+static uintptr_t
+ngx_http_log_escape(u_char *dst, u_char *src, size_t size)
+{
+    ngx_uint_t      i, n;
+    static u_char   hex[] = "0123456789ABCDEF";
+
+    static uint32_t   escape[] = {
+        0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
+
+                    /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
+        0x00000004, /* 0000 0000 0000 0000  0000 0000 0000 0100 */
+
+                    /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
+        0x10000000, /* 0001 0000 0000 0000  0000 0000 0000 0000 */
+
+                    /*  ~}| {zyx wvut srqp  onml kjih gfed cba` */
+        0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
+
+        0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
+        0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
+        0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
+        0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
+    };
+
+
+    if (dst == NULL) {
+
+        /* find the number of the characters to be escaped */
+
+        n  = 0;
+
+        for (i = 0; i < size; i++) {
+            if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
+                n++;
+            }
+            src++;
+        }
+
+        return (uintptr_t) n;
+    }
+
+    for (i = 0; i < size; i++) {
+        if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
+            *dst++ = '\\';
+            *dst++ = 'x';
+            *dst++ = hex[*src >> 4];
+            *dst++ = hex[*src & 0xf];
+            src++;
+
+        } else {
+            *dst++ = *src++;
+        }
+    }
+
+    return (uintptr_t) dst;
 }