changeset 409:8ac40cae79f0

nginx-0.0.10-2004-08-29-07:55:41 import
author Igor Sysoev <igor@sysoev.ru>
date Sun, 29 Aug 2004 03:55:41 +0000
parents d6e2b445c1b8
children 48b9ad5ca1fc
files auto/modules auto/options auto/sources src/core/nginx.c src/core/ngx_string.c src/core/ngx_string.h src/core/ngx_times.c src/core/ngx_times.h src/http/modules/ngx_http_userid_filter.c src/http/modules/ngx_http_userid_handler.c src/http/ngx_http_log_handler.c
diffstat 11 files changed, 593 insertions(+), 523 deletions(-) [+]
line wrap: on
line diff
--- a/auto/modules	Fri Aug 27 15:40:59 2004 +0000
+++ b/auto/modules	Sun Aug 29 03:55:41 2004 +0000
@@ -79,6 +79,11 @@
     HTTP_SRCS="$HTTP_SRCS $HTTP_SSI_SRCS"
 fi
 
+if [ $HTTP_USERID = YES ]; then
+    HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_USERID_FILTER_MODULE"
+    HTTP_SRCS="$HTTP_SRCS $HTTP_USERID_SRCS"
+fi
+
 HTTP_MODULES="$HTTP_MODULES $HTTP_STATIC_MODULE $HTTP_INDEX_MODULE"
 
 if [ $HTTP_ACCESS = YES ]; then
@@ -87,11 +92,6 @@
     HTTP_SRCS="$HTTP_SRCS $HTTP_ACCESS_SRCS"
 fi
 
-if [ $HTTP_USERID = YES ]; then
-    HTTP_MODULES="$HTTP_MODULES $HTTP_USERID_MODULE"
-    HTTP_SRCS="$HTTP_SRCS $HTTP_USERID_SRCS"
-fi
-
 if [ $HTTP_STATUS = YES ]; then
     have=NGX_HTTP_STATUS . auto/have
     HTTP_MODULES="$HTTP_MODULES $HTTP_STATUS_MODULE"
--- a/auto/options	Fri Aug 27 15:40:59 2004 +0000
+++ b/auto/options	Sun Aug 29 03:55:41 2004 +0000
@@ -92,8 +92,8 @@
         --without-http_charset_module)   HTTP_CHARSET=NO            ;;
         --without-http_gzip_module)      HTTP_GZIP=NO               ;;
         --without-http_ssi_module)       HTTP_SSI=NO                ;;
+        --without-http_userid_module)    HTTP_USERID=NO             ;;
         --without-http_access_module)    HTTP_ACCESS=NO             ;;
-        --without-http_userid_module)    HTTP_USERID=NO             ;;
         --without-http_status_module)    HTTP_STATUS=NO             ;;
         --without-http_rewrite_module)   HTTP_REWRITE=NO            ;;
         --without-http_proxy_module)     HTTP_PROXY=NO              ;;
--- a/auto/sources	Fri Aug 27 15:40:59 2004 +0000
+++ b/auto/sources	Sun Aug 29 03:55:41 2004 +0000
@@ -257,14 +257,14 @@
 HTTP_SSI_SRCS=src/http/modules/ngx_http_ssi_filter.c
 
 
+HTTP_USERID_FILTER_MODULE=ngx_http_userid_filter_module
+HTTP_USERID_SRCS=src/http/modules/ngx_http_userid_filter.c
+
+
 HTTP_ACCESS_MODULE=ngx_http_access_module
 HTTP_ACCESS_SRCS=src/http/modules/ngx_http_access_handler.c
 
 
-HTTP_USERID_MODULE=ngx_http_userid_module
-HTTP_USERID_SRCS=src/http/modules/ngx_http_userid_handler.c
-
-
 HTTP_STATUS_MODULE=ngx_http_status_module
 HTTP_STATUS_SRCS=src/http/modules/ngx_http_status_handler.c
 
--- a/src/core/nginx.c	Fri Aug 27 15:40:59 2004 +0000
+++ b/src/core/nginx.c	Sun Aug 29 03:55:41 2004 +0000
@@ -140,65 +140,6 @@
         return 1;
     }
 
-{
-    ngx_str_t  d, s;
-
-    s.data = "12";
-    s.len = sizeof("12") - 1;
-
-    if (ngx_encode_base64(init_cycle.pool, &s, &d) != NGX_OK) {
-        ngx_log_error(NGX_LOG_ERR, log, 0, "ngx_encode_base64() failed");
-    } else {
-        ngx_log_error(NGX_LOG_NOTICE, log, 0, "BASE64: %d:\"%s\"", d.len, d.data);
-    }
-
-    s.data = "123";
-    s.len = sizeof("123") - 1;
-
-    if (ngx_encode_base64(init_cycle.pool, &s, &d) != NGX_OK) {
-        ngx_log_error(NGX_LOG_ERR, log, 0, "ngx_encode_base64() failed");
-    } else {
-        ngx_log_error(NGX_LOG_NOTICE, log, 0, "BASE64: %d:\"%s\"", d.len, d.data);
-    }
-
-    s.data = "1234";
-    s.len = sizeof("1234") - 1;
-
-    if (ngx_encode_base64(init_cycle.pool, &s, &d) != NGX_OK) {
-        ngx_log_error(NGX_LOG_ERR, log, 0, "ngx_encode_base64() failed");
-    } else {
-        ngx_log_error(NGX_LOG_NOTICE, log, 0, "BASE64: %d:\"%s\"", d.len, d.data);
-    }
-
-    s.data = "12345";
-    s.len = sizeof("12345") - 1;
-
-    if (ngx_encode_base64(init_cycle.pool, &s, &d) != NGX_OK) {
-        ngx_log_error(NGX_LOG_ERR, log, 0, "ngx_encode_base64() failed");
-    } else {
-        ngx_log_error(NGX_LOG_NOTICE, log, 0, "BASE64: %d:\"%s\"", d.len, d.data);
-    }
-
-    s.data = "123456";
-    s.len = sizeof("123456") - 1;
-
-    if (ngx_encode_base64(init_cycle.pool, &s, &d) != NGX_OK) {
-        ngx_log_error(NGX_LOG_ERR, log, 0, "ngx_encode_base64() failed");
-    } else {
-        ngx_log_error(NGX_LOG_NOTICE, log, 0, "BASE64: %d:\"%s\"", d.len, d.data);
-    }
-
-    s.data = "12345678901234567890";
-    s.len = sizeof("12345678901234567890") - 1;
-
-    if (ngx_encode_base64(init_cycle.pool, &s, &d) != NGX_OK) {
-        ngx_log_error(NGX_LOG_ERR, log, 0, "ngx_encode_base64() failed");
-    } else {
-        ngx_log_error(NGX_LOG_NOTICE, log, 0, "BASE64: %d:\"%s\"", d.len, d.data);
-    }
-
-}
-
     if (ngx_add_inherited_sockets(&init_cycle) == NGX_ERROR) {
         return 1;
     }
--- a/src/core/ngx_string.c	Fri Aug 27 15:40:59 2004 +0000
+++ b/src/core/ngx_string.c	Sun Aug 29 03:55:41 2004 +0000
@@ -123,20 +123,16 @@
 }
 
 
-ngx_int_t ngx_encode_base64(ngx_pool_t *pool, ngx_str_t *src, ngx_str_t *dst)
+void ngx_encode_base64(ngx_str_t *src, ngx_str_t *dst)
 {
     u_char         *d, *s;
     size_t          len;
     static u_char   basis64[] =
             "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
-    if (!(d = ngx_palloc(pool, ((src->len + 2) / 3) * 4 + 1))) {
-        return NGX_ERROR;
-    }
-
-    dst->data = d;
+    len = src->len;
     s = src->data;
-    len = src->len;
+    d = dst->data;
 
     while (len > 2) {
         *d++ = basis64[(s[0] >> 2) & 0x3f];
@@ -164,13 +160,10 @@
     }
 
     dst->len = d - dst->data;
-    *d++ = '\0';
-
-    return NGX_OK;
 }
 
 
-ngx_int_t ngx_decode_base64(ngx_pool_t *pool, ngx_str_t *src, ngx_str_t *dst)
+ngx_int_t ngx_decode_base64(ngx_str_t *src, ngx_str_t *dst)
 {
     size_t          len;
     u_char         *d, *s;
@@ -207,33 +200,27 @@
         return NGX_ERROR;
     }
 
-    if (!(d = ngx_palloc(pool, ((len + 3) / 4) * 3 + 1))) {
-        return NGX_ABORT;
-    }
-
-    dst->data = d;
-
     s = src->data;
+    d = dst->data;
 
     while (len > 3) {
-        *d++ = basis64[s[0]] << 2 | basis64[s[1]] >> 4;
-        *d++ = basis64[s[1]] << 4 | basis64[s[2]] >> 2;
-        *d++ = basis64[s[2]] << 6 | basis64[s[3]];
+        *d++ = (u_char) (basis64[s[0]] << 2 | basis64[s[1]] >> 4);
+        *d++ = (u_char) (basis64[s[1]] << 4 | basis64[s[2]] >> 2);
+        *d++ = (u_char) (basis64[s[2]] << 6 | basis64[s[3]]);
 
         s += 4;
         len -= 4;
     }
 
     if (len > 1) {
-        *d++ = basis64[s[0]] << 2 | basis64[s[1]] >> 4;
+        *d++ = (u_char) (basis64[s[0]] << 2 | basis64[s[1]] >> 4);
     }
 
     if (len > 2) {
-        *d++ = basis64[s[1]] << 4 | basis64[s[2]] >> 2;
+        *d++ = (u_char) (basis64[s[1]] << 4 | basis64[s[2]] >> 2);
     }
 
     dst->len = d - dst->data;
-    *d++ = '\0';
 
     return NGX_OK;
 }
--- a/src/core/ngx_string.h	Fri Aug 27 15:40:59 2004 +0000
+++ b/src/core/ngx_string.h	Sun Aug 29 03:55:41 2004 +0000
@@ -71,8 +71,12 @@
 
 void ngx_md5_text(u_char *text, u_char *md5);
 
-ngx_int_t ngx_encode_base64(ngx_pool_t *pool, ngx_str_t *src, ngx_str_t *dst);
-ngx_int_t ngx_decode_base64(ngx_pool_t *pool, ngx_str_t *src, ngx_str_t *dst);
+
+#define ngx_base64_encoded_length(len)  (((len + 2) / 3) * 4)
+#define ngx_base64_decoded_length(len)  (((len + 3) / 4) * 3)
+
+void ngx_encode_base64(ngx_str_t *src, ngx_str_t *dst);
+ngx_int_t ngx_decode_base64(ngx_str_t *src, ngx_str_t *dst);
 
 
 #define  ngx_qsort                qsort
--- a/src/core/ngx_times.c	Fri Aug 27 15:40:59 2004 +0000
+++ b/src/core/ngx_times.c	Sun Aug 29 03:55:41 2004 +0000
@@ -214,14 +214,51 @@
     ngx_gmtime(t, &tm);
 
     return ngx_snprintf((char *) buf, sizeof("Mon, 28 Sep 1970 06:00:00 GMT"),
-                                       "%s, %02d %s %4d %02d:%02d:%02d GMT",
-                                       week[tm.ngx_tm_wday],
-                                       tm.ngx_tm_mday,
-                                       months[tm.ngx_tm_mon - 1],
-                                       tm.ngx_tm_year,
-                                       tm.ngx_tm_hour,
-                                       tm.ngx_tm_min,
-                                       tm.ngx_tm_sec);
+                                      "%s, %02d %s %4d %02d:%02d:%02d GMT",
+                                      week[tm.ngx_tm_wday],
+                                      tm.ngx_tm_mday,
+                                      months[tm.ngx_tm_mon - 1],
+                                      tm.ngx_tm_year,
+                                      tm.ngx_tm_hour,
+                                      tm.ngx_tm_min,
+                                      tm.ngx_tm_sec);
+}
+
+
+size_t ngx_http_cookie_time(u_char *buf, time_t t)
+{
+    ngx_tm_t  tm;
+
+    ngx_gmtime(t, &tm);
+
+    /*
+     * Netscape 3.x does not understand 4-digit years at all and
+     * 2-digit years more than "37"
+     */
+
+    if (tm.ngx_tm_year > 2037) {
+        return ngx_snprintf((char *) buf,
+                                      sizeof("Mon, 28-Sep-1970 06:00:00 GMT"),
+                                      "%s, %02d-%s-%d %02d:%02d:%02d GMT",
+                                      week[tm.ngx_tm_wday],
+                                      tm.ngx_tm_mday,
+                                      months[tm.ngx_tm_mon - 1],
+                                      tm.ngx_tm_year,
+                                      tm.ngx_tm_hour,
+                                      tm.ngx_tm_min,
+                                      tm.ngx_tm_sec);
+    } else {
+        return ngx_snprintf((char *) buf,
+                                      sizeof("Mon, 28-Sep-70 06:00:00 GMT"),
+                                      "%s, %02d-%s-%02d %02d:%02d:%02d GMT",
+                                      week[tm.ngx_tm_wday],
+                                      tm.ngx_tm_mday,
+                                      months[tm.ngx_tm_mon - 1],
+                                      tm.ngx_tm_year % 100,
+                                      tm.ngx_tm_hour,
+                                      tm.ngx_tm_min,
+                                      tm.ngx_tm_sec);
+    }
 }
 
 
--- a/src/core/ngx_times.h	Fri Aug 27 15:40:59 2004 +0000
+++ b/src/core/ngx_times.h	Sun Aug 29 03:55:41 2004 +0000
@@ -9,6 +9,7 @@
 void ngx_time_init();
 void ngx_time_update(time_t s);
 size_t ngx_http_time(u_char *buf, time_t t);
+size_t ngx_http_cookie_time(u_char *buf, time_t t);
 void ngx_gmtime(time_t t, ngx_tm_t *tp);
 
 #if (NGX_THREADS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/http/modules/ngx_http_userid_filter.c	Sun Aug 29 03:55:41 2004 +0000
@@ -0,0 +1,506 @@
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+#define NGX_HTTP_USERID_OFF   0
+#define NGX_HTTP_USERID_LOG   1
+#define NGX_HTTP_USERID_V1    2
+#define NGX_HTTP_USERID_ON    3
+
+/* 31 Dec 2037 23:55:55 GMT */
+#define NGX_HTTP_USERID_MAX_EXPIRES  2145916555
+
+
+typedef struct {
+    ngx_flag_t  enable;
+
+    ngx_int_t   service;
+
+    ngx_str_t   name;
+    ngx_str_t   domain;
+    ngx_str_t   path;
+    time_t      expires;
+
+    ngx_int_t   p3p;
+    ngx_str_t   p3p_string;
+} ngx_http_userid_conf_t;
+
+
+typedef struct {
+    uint32_t          uid_got[4];
+    uint32_t          uid_set[4];
+} ngx_http_userid_ctx_t;
+
+
+static ngx_int_t ngx_http_userid_get_uid(ngx_http_request_t *r,
+                                         ngx_http_userid_ctx_t *ctx,
+                                         ngx_http_userid_conf_t *conf);
+static ngx_int_t ngx_http_userid_set_uid(ngx_http_request_t *r,
+                                         ngx_http_userid_ctx_t *ctx,
+                                         ngx_http_userid_conf_t *conf);
+
+static u_char *ngx_http_userid_log_uid_got(ngx_http_request_t *r, u_char *buf,
+                                           uintptr_t data);
+static u_char *ngx_http_userid_log_uid_set(ngx_http_request_t *r, u_char *buf,
+                                           uintptr_t data);
+
+static ngx_int_t ngx_http_userid_pre_conf(ngx_conf_t *cf);
+static void *ngx_http_userid_create_conf(ngx_conf_t *cf);
+static char *ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent,
+                                        void *child);
+static ngx_int_t ngx_http_userid_init(ngx_cycle_t *cycle);
+
+
+static uint32_t  sequencer_v1 = 1;
+static uint32_t  sequencer_v2 = 0x03030302;
+
+
+static u_char expires[] = "; expires=Thu, 31-Dec-37 23:55:55 GMT";
+
+
+static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
+
+
+static ngx_conf_enum_t  ngx_http_userid_state[] = {
+    { ngx_string("off"), NGX_HTTP_USERID_OFF },
+    { ngx_string("log"), NGX_HTTP_USERID_LOG },
+    { ngx_string("v1"), NGX_HTTP_USERID_V1 },
+    { ngx_string("on"), NGX_HTTP_USERID_ON },
+    { ngx_null_string, 0 }
+};
+
+
+static ngx_command_t  ngx_http_userid_commands[] = {
+
+    { ngx_string("userid"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_enum_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_userid_conf_t, enable),
+      ngx_http_userid_state},
+
+    { ngx_string("userid_service"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_num_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_userid_conf_t, service),
+      NULL},
+
+    { ngx_string("userid_name"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_str_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_userid_conf_t, name),
+      NULL},
+
+    { ngx_string("userid_domain"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_str_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_userid_conf_t, domain),
+      NULL},
+
+    { ngx_string("userid_path"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_str_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_userid_conf_t, path),
+      NULL},
+
+    { ngx_string("userid_expires"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_sec_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_userid_conf_t, expires),
+      NULL},
+
+    ngx_null_command
+};
+
+
+ngx_http_module_t  ngx_http_userid_filter_module_ctx = {
+    ngx_http_userid_pre_conf,              /* pre conf */
+
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    ngx_http_userid_create_conf,           /* create location configration */
+    ngx_http_userid_merge_conf             /* merge location configration */
+};
+
+
+ngx_module_t  ngx_http_userid_filter_module = {
+    NGX_MODULE,
+    &ngx_http_userid_filter_module_ctx,    /* module context */
+    ngx_http_userid_commands,              /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_userid_init,                  /* init module */
+    NULL                                   /* init process */
+};
+
+
+static ngx_http_log_op_name_t ngx_http_userid_log_fmt_ops[] = {
+    { ngx_string("uid_got"), 0, ngx_http_userid_log_uid_got },
+    { ngx_string("uid_set"), 0, ngx_http_userid_log_uid_set },
+    { ngx_null_string, 0, NULL }
+};
+
+
+static ngx_int_t ngx_http_userid_filter(ngx_http_request_t *r)
+{
+    ngx_int_t                rc;
+    ngx_http_userid_ctx_t   *ctx;
+    ngx_http_userid_conf_t  *conf;
+
+    conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module);
+
+    if (conf->enable == NGX_HTTP_USERID_OFF) {
+        return ngx_http_next_header_filter(r);
+    }
+
+    ngx_http_create_ctx(r, ctx, ngx_http_userid_filter_module,
+                        sizeof(ngx_http_userid_ctx_t),
+                        NGX_HTTP_INTERNAL_SERVER_ERROR);
+
+    rc = ngx_http_userid_get_uid(r, ctx, conf);
+
+    if (rc != NGX_OK) {
+        return rc;
+    }
+
+    if (conf->enable == NGX_HTTP_USERID_LOG /* || ctx->uid_got[3] != 0 */) {
+        return NGX_OK;
+    }
+
+    rc = ngx_http_userid_set_uid(r, ctx, conf);
+
+    if (rc != NGX_OK) {
+        return rc;
+    }
+
+    return ngx_http_next_header_filter(r);
+}
+
+
+static ngx_int_t ngx_http_userid_get_uid(ngx_http_request_t *r,
+                                         ngx_http_userid_ctx_t *ctx,
+                                         ngx_http_userid_conf_t *conf)
+{
+    u_char           *start, *last, *end;
+    ngx_uint_t       *cookies, i;
+    ngx_str_t         src, dst;
+    ngx_table_elt_t  *headers;
+
+    headers = r->headers_in.headers.elts;
+    cookies = r->headers_in.cookies.elts;
+
+    for (i = 0; i < r->headers_in.cookies.nelts; i++) {
+        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                       "cookie: %d:\"%s\"",
+                       cookies[i],
+                       headers[cookies[i]].value.data);
+
+        end = headers[cookies[i]].value.data + headers[cookies[i]].value.len;
+
+        for (start = headers[cookies[i]].value.data; start < end; /* void */) {
+
+            if (conf->name.len >= headers[cookies[i]].value.len
+                || ngx_strncmp(start, conf->name.data, conf->name.len) != 0)
+            {
+                start += conf->name.len;
+                while (start < end && *start++ != ';') { /* void */ }
+
+                for (/* void */; start < end && *start == ' '; start++) { /**/ }
+
+                continue;
+            }
+
+            for (start += conf->name.len; start < end && *start == ' '; start++)
+            {
+                /* void */
+            }
+
+            if (*start != '=') {
+                break;
+            }
+
+            for (start++; start < end && *start == ' '; start++) { /* void */ }
+
+            for (last = start; last < end && *last != ';'; last++) { /**/ }
+
+            if (last - start < 22) {
+                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                              "client sent too short userid cookie \"%s\"",
+                              headers[cookies[i]].value.data);
+                break;
+            }
+
+            /*
+             * we have to limit encoded string to 22 characters
+             * because there are already the millions cookies with a garbage
+             * instead of the correct base64 trail "=="
+             */
+
+            src.len = 22;
+            src.data = start;
+            dst.data = (u_char *) ctx->uid_got;
+
+            if (ngx_decode_base64(&src, &dst) == NGX_ERROR) {
+                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                              "client sent invalid userid cookie \"%s\"",
+                              headers[cookies[i]].value.data);
+                break;
+            }
+
+            ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                           "uid: %08X%08X%08X%08X",
+                           ctx->uid_got[0], ctx->uid_got[1],
+                           ctx->uid_got[2], ctx->uid_got[3]);
+
+            return NGX_OK;
+        }
+    }
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t ngx_http_userid_set_uid(ngx_http_request_t *r,
+                                         ngx_http_userid_ctx_t *ctx,
+                                         ngx_http_userid_conf_t *conf)
+
+{
+    u_char           *cookie, *p;
+    size_t            len;
+    ngx_str_t         src, dst;
+    ngx_table_elt_t  *set_cookie;
+
+    /* TODO: mutex for sequencers */
+
+    if (conf->enable == NGX_HTTP_USERID_V1) {
+        ctx->uid_set[0] = conf->service;
+        ctx->uid_set[1] = ngx_time();
+        ctx->uid_set[2] = ngx_pid;
+        ctx->uid_set[3] = sequencer_v1;
+        sequencer_v1 += 0x100;
+
+    } else {
+        ctx->uid_set[0] = htonl(conf->service);
+        ctx->uid_set[1] = htonl(ngx_time());
+        ctx->uid_set[2] = htonl(ngx_pid);
+        ctx->uid_set[3] = htonl(sequencer_v2);
+        sequencer_v2 += 0x100;
+        if (sequencer_v2 < 0x03030302) {
+            sequencer_v2 = 0x03030302;
+        }
+    }
+
+    len = conf->name.len + 1 + ngx_base64_encoded_length(16) + 1;
+
+    if (conf->expires) {
+        len += sizeof(expires) - 1 + 2;
+    }
+
+    if (conf->domain.len > 1) {
+        len += sizeof("; domain=") - 1 + conf->domain.len;
+    }
+
+    if (conf->path.len) {
+        len += sizeof("; path=") - 1 + conf->path.len;
+    }
+
+    if (!(cookie = ngx_palloc(r->pool, len))) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    p = ngx_cpymem(cookie, conf->name.data, conf->name.len);
+    *p++ = '=';
+
+    src.len = 16;
+    src.data = (u_char *) ctx->uid_set;
+    dst.data = p;
+
+    ngx_encode_base64(&src, &dst);
+
+    p += dst.len;
+
+    if (conf->expires == NGX_HTTP_USERID_MAX_EXPIRES) {
+        p = ngx_cpymem(p, expires, sizeof(expires) - 1);
+
+    } else if (conf->expires) {
+        p = ngx_cpymem(p, expires, sizeof("; expires=") - 1);
+        p += ngx_http_cookie_time(p, ngx_time() + conf->expires);
+    }
+
+    if (conf->domain.len > 1) {
+        p = ngx_cpymem(p, "; domain=", sizeof("; domain=") - 1);
+        p = ngx_cpymem(p, conf->domain.data, conf->domain.len);
+    }
+
+    if (conf->path.len) {
+        p = ngx_cpymem(p, "; path=", sizeof("; path=") - 1);
+        p = ngx_cpymem(p, conf->path.data, conf->path.len);
+    }
+
+    *p = '\0';
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "uid cookie: \"%s\"", cookie);
+
+    set_cookie = ngx_http_add_header(&r->headers_out, ngx_http_headers_out);
+    if (set_cookie == NULL) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    set_cookie->key.len = sizeof("Set-Cookie") - 1;
+    set_cookie->key.data = (u_char *) "Set-Cookie";
+    set_cookie->value.len = p - cookie;
+    set_cookie->value.data = cookie;
+
+    return NGX_OK;
+}
+
+
+static u_char *ngx_http_userid_log_uid_got(ngx_http_request_t *r, u_char *buf,
+                                           uintptr_t data)
+{
+    ngx_http_userid_ctx_t   *ctx;
+    ngx_http_userid_conf_t  *conf;
+
+    ctx = ngx_http_get_module_ctx(r, ngx_http_userid_filter_module);
+
+    if (ctx == NULL || ctx->uid_got[3] == 0) {
+        if (buf == NULL) {
+            return (u_char *) 1;
+        }
+
+        *buf = '-';
+        return buf + 1;
+    }
+
+    conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module);
+
+    if (buf == NULL) {
+        return (u_char *) (conf->name.len + 1 + 32);
+    }
+
+    buf = ngx_cpymem(buf, conf->name.data, conf->name.len);
+
+    *buf++ = '=';
+
+    return buf + ngx_snprintf((char *) buf, 33, "%08X%08X%08X%08X",
+                              ctx->uid_got[0], ctx->uid_got[1],
+                              ctx->uid_got[2], ctx->uid_got[3]);
+}
+
+
+static u_char *ngx_http_userid_log_uid_set(ngx_http_request_t *r, u_char *buf,
+                                           uintptr_t data)
+{
+    ngx_http_userid_ctx_t   *ctx;
+    ngx_http_userid_conf_t  *conf;
+
+    ctx = ngx_http_get_module_ctx(r, ngx_http_userid_filter_module);
+
+    if (ctx == NULL || ctx->uid_set[3] == 0) {
+        if (buf == NULL) {
+            return (u_char *) 1;
+        }
+
+        *buf = '-';
+        return buf + 1;
+    }
+
+    conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module);
+
+    if (buf == NULL) {
+        return (u_char *) (conf->name.len + 1 + 32);
+    }
+
+    buf = ngx_cpymem(buf, conf->name.data, conf->name.len);
+
+    *buf++ = '=';
+
+    return buf + ngx_snprintf((char *) buf, 33, "%08X%08X%08X%08X",
+                              ctx->uid_set[0], ctx->uid_set[1],
+                              ctx->uid_set[2], ctx->uid_set[3]);
+}
+
+
+static ngx_int_t ngx_http_userid_pre_conf(ngx_conf_t *cf)
+{
+    ngx_http_log_op_name_t  *op;
+
+    for (op = ngx_http_userid_log_fmt_ops; op->name.len; op++) { /* void */ }
+    op->op = NULL;
+
+    op = ngx_http_log_fmt_ops;
+
+    for (op = ngx_http_log_fmt_ops; op->op; op++) {
+        if (op->name.len == 0) {
+            op = (ngx_http_log_op_name_t *) op->op;
+        }
+    }
+
+    op->op = (ngx_http_log_op_pt) ngx_http_userid_log_fmt_ops;
+
+    return NGX_OK;
+}
+
+
+static void *ngx_http_userid_create_conf(ngx_conf_t *cf)
+{   
+    ngx_http_userid_conf_t  *conf;
+
+    if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_userid_conf_t)))) {
+        return NGX_CONF_ERROR;
+    }
+
+    /* set by ngx_pcalloc():
+
+    conf->name.len = 0;
+    conf->name.date = NULL;
+    conf->domain.len = 0;
+    conf->domain.date = NULL;
+    conf->path.len = 0;
+    conf->path.date = NULL;
+
+    */
+
+    conf->enable = NGX_CONF_UNSET;
+    conf->expires = NGX_CONF_UNSET;
+
+    return conf;
+}   
+
+
+static char *ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent,
+                                        void *child)
+{
+    ngx_http_userid_conf_t *prev = parent;
+    ngx_http_userid_conf_t *conf = child;
+
+    ngx_conf_merge_value(conf->enable, prev->enable, NGX_HTTP_USERID_OFF);
+
+    ngx_conf_merge_str_value(conf->name, prev->name, "uid");
+    ngx_conf_merge_str_value(conf->domain, prev->domain, ".");
+    ngx_conf_merge_str_value(conf->path, prev->path, "/");
+
+    ngx_conf_merge_sec_value(conf->expires, prev->expires, 0);
+
+    return NGX_CONF_OK;
+}   
+
+
+static ngx_int_t ngx_http_userid_init(ngx_cycle_t *cycle)
+{
+    ngx_http_next_header_filter = ngx_http_top_header_filter;
+    ngx_http_top_header_filter = ngx_http_userid_filter;
+
+    return NGX_OK;
+}
--- a/src/http/modules/ngx_http_userid_handler.c	Fri Aug 27 15:40:59 2004 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,421 +0,0 @@
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-#define NGX_HTTP_USERID_OFF       0x0002
-#define NGX_HTTP_USERID_ON        0x0004
-#define NGX_HTTP_USERID_LOGONLY   0x0008
-#define NGX_HTTP_USERID_TIME      0x0010
-
-
-typedef struct {
-    ngx_flag_t  enable;
-
-    ngx_int_t   version;
-    ngx_int_t   service;
-
-    ngx_str_t   name;
-    ngx_str_t   domain;
-    ngx_str_t   path;
-    time_t      expires;
-
-    ngx_int_t   p3p;
-    ngx_str_t   p3p_string;
-} ngx_http_userid_conf_t;
-
-
-typedef struct {
-    uint32_t          uid_got[4];
-    uint32_t          uid_set[4];
-    struct timeval    tv;
-} ngx_http_userid_ctx_t;
-
-
-static ngx_int_t ngx_http_userid_get_uid(ngx_http_request_t *r,
-                                         ngx_http_userid_ctx_t *ctx,
-                                         ngx_http_userid_conf_t *conf);
-
-static u_char *ngx_http_userid_log_uid_got(ngx_http_request_t *r, u_char *buf,
-                                           uintptr_t data);
-static u_char *ngx_http_userid_log_uid_set(ngx_http_request_t *r, u_char *buf,
-                                           uintptr_t data);
-static u_char *ngx_http_userid_log_uid_time(ngx_http_request_t *r, u_char *buf,
-                                            uintptr_t data);
-
-static ngx_int_t ngx_http_userid_pre_conf(ngx_conf_t *cf);
-static void *ngx_http_userid_create_conf(ngx_conf_t *cf);
-static char *ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent,
-                                        void *child);
-static ngx_int_t ngx_http_userid_init(ngx_cycle_t *cycle);
-
-
-static ngx_conf_enum_t  ngx_http_userid_mask[] = {
-    { ngx_string("off"), NGX_HTTP_USERID_OFF },
-    { ngx_string("on"), NGX_HTTP_USERID_ON },
-    { ngx_string("logonly"), NGX_HTTP_USERID_LOGONLY },
-    { ngx_string("time"), NGX_HTTP_USERID_TIME },
-    { ngx_null_string, 0 }
-};
-
-
-static ngx_command_t  ngx_http_userid_commands[] = {
-
-    { ngx_string("userid"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY,
-      ngx_conf_set_bitmask_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_userid_conf_t, enable),
-      ngx_http_userid_mask},
-
-    { ngx_string("userid_service"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
-      ngx_conf_set_num_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_userid_conf_t, service),
-      NULL},
-
-    { ngx_string("userid_name"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
-      ngx_conf_set_str_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_userid_conf_t, name),
-      NULL},
-
-    { ngx_string("userid_domain"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
-      ngx_conf_set_str_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_userid_conf_t, domain),
-      NULL},
-
-    { ngx_string("userid_path"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
-      ngx_conf_set_str_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_userid_conf_t, path),
-      NULL},
-
-    { ngx_string("userid_expires"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
-      ngx_conf_set_sec_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_userid_conf_t, expires),
-      NULL},
-
-    ngx_null_command
-};
-
-
-ngx_http_module_t  ngx_http_userid_module_ctx = {
-    ngx_http_userid_pre_conf,              /* pre conf */
-
-    NULL,                                  /* create main configuration */
-    NULL,                                  /* init main configuration */
-
-    NULL,                                  /* create server configuration */
-    NULL,                                  /* merge server configuration */
-
-    ngx_http_userid_create_conf,           /* create location configration */
-    ngx_http_userid_merge_conf             /* merge location configration */
-};
-
-
-ngx_module_t  ngx_http_userid_module = {
-    NGX_MODULE,
-    &ngx_http_userid_module_ctx,           /* module context */
-    ngx_http_userid_commands,              /* module directives */
-    NGX_HTTP_MODULE,                       /* module type */
-    ngx_http_userid_init,                  /* init module */
-    NULL                                   /* init process */
-};
-
-
-static ngx_http_log_op_name_t ngx_http_userid_log_fmt_ops[] = {
-    { ngx_string("uid_got"), 0, ngx_http_userid_log_uid_got },
-    { ngx_string("uid_set"), 0, ngx_http_userid_log_uid_set },
-    { ngx_string("uid_time"), TIME_T_LEN + 4, ngx_http_userid_log_uid_time },
-    { ngx_null_string, 0, NULL }
-};
-
-
-static ngx_int_t ngx_http_userid_handler(ngx_http_request_t *r)
-{
-    ngx_int_t                rc;
-    struct timeval           tv;
-    ngx_http_userid_ctx_t   *ctx;
-    ngx_http_userid_conf_t  *conf;
-
-    conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_module);
-
-    if (conf->enable & NGX_HTTP_USERID_OFF) {
-        return NGX_OK;
-    }
-
-    ctx = ngx_http_get_module_ctx(r, ngx_http_userid_module);
-
-    if (ctx) {
-        return NGX_OK;
-    }
-
-    ngx_http_create_ctx(r, ctx, ngx_http_userid_module,
-                        sizeof(ngx_http_userid_ctx_t),
-                        NGX_HTTP_INTERNAL_SERVER_ERROR);
-
-    if (conf->enable & (NGX_HTTP_USERID_ON|NGX_HTTP_USERID_LOGONLY)) {
-        rc = ngx_http_userid_get_uid(r, ctx, conf);
-
-        if (rc != NGX_OK) {
-            return rc;
-        }
-    }
-
-    if (conf->enable & NGX_HTTP_USERID_TIME) {
-        ngx_gettimeofday(&ctx->tv);
-    }
-
-    return NGX_OK;
-}
-
-
-static ngx_int_t ngx_http_userid_get_uid(ngx_http_request_t *r,
-                                         ngx_http_userid_ctx_t *ctx,
-                                         ngx_http_userid_conf_t *conf)
-{
-    u_char           *start, *last, *end;
-    uint32_t         *uid;
-    ngx_int_t         rc;
-    ngx_uint_t       *cookies, i;
-    ngx_str_t         src, dst;
-    ngx_table_elt_t  *headers;
-
-    headers = r->headers_in.headers.elts;
-    cookies = r->headers_in.cookies.elts;
-
-    for (i = 0; i < r->headers_in.cookies.nelts; i++) {
-        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                       "cookie: %d:\"%s\"",
-                       cookies[i],
-                       headers[cookies[i]].value.data);
-
-        end = headers[cookies[i]].value.data + headers[cookies[i]].value.len;
-
-        for (start = headers[cookies[i]].value.data; start < end; /* void */) {
-
-            if (conf->name.len >= headers[cookies[i]].value.len
-                || ngx_strncmp(start, conf->name.data, conf->name.len) != 0)
-            {
-                start += conf->name.len;
-                while (start < end && *start++ != ';') { /* void */ }
-
-                for (/* void */; start < end && *start == ' '; start++) { /**/ }
-
-                continue;
-            }
-
-            for (start += conf->name.len; start < end && *start == ' '; start++)
-            {
-                /* void */
-            }
-
-            if (*start != '=') {
-                break;
-            }
-
-            for (start++; start < end && *start == ' '; start++) { /* void */ }
-
-            for (last = start; last < end && *last != ';'; last++) { /**/ }
-
-            if (last - start < 22) {
-                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                              "client sent too short userid cookie \"%s\"",
-                              headers[cookies[i]].value.data);
-                break;
-            }
-
-            /*
-             * we have to limit encoded string to 22 characters
-             * because there are already the millions cookies with a garbage
-             * instead of the correct base64 trail "=="
-             */
-
-            src.len = 22;
-            src.data = start;
-
-            rc = ngx_decode_base64(r->pool, &src, &dst);
-
-            if (rc == NGX_ABORT) {
-                return NGX_HTTP_INTERNAL_SERVER_ERROR;
-            }
-
-            if (rc == NGX_ERROR) {
-                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                              "client sent invalid userid cookie \"%s\"",
-                              headers[cookies[i]].value.data);
-                break;
-            }
-
-            uid = (uint32_t *) dst.data;
-            ctx->uid_got[0] = uid[0];
-            ctx->uid_got[1] = uid[1];
-            ctx->uid_got[2] = uid[2];
-            ctx->uid_got[3] = uid[3];
-
-            ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                           "uid: %08X%08X%08X%08X",
-                           uid[0], uid[1], uid[2], uid[3]);
-
-            return NGX_OK;
-        }
-    }
-
-    return NGX_OK;
-}
-
-
-static u_char *ngx_http_userid_log_uid_got(ngx_http_request_t *r, u_char *buf,
-                                           uintptr_t data)
-{
-    ngx_http_userid_ctx_t   *ctx;
-    ngx_http_userid_conf_t  *conf;
-
-    ctx = ngx_http_get_module_ctx(r, ngx_http_userid_module);
-
-    if (ctx == NULL || ctx->uid_got[3] == 0) {
-        if (buf == NULL) {
-            return (u_char *) 1;
-        }
-
-        *buf = '-';
-        return buf + 1;
-    }
-
-    conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_module);
-
-    if (buf == NULL) {
-        return (u_char *) (conf->name.len + 1 + 32);
-    }
-
-    buf = ngx_cpymem(buf, conf->name.data, conf->name.len);
-
-    *buf++ = '=';
-
-    return buf + ngx_snprintf((char *) buf, 33, "%08X%08X%08X%08X",
-                              ctx->uid_got[0], ctx->uid_got[1],
-                              ctx->uid_got[2], ctx->uid_got[3]);
-}
-
-
-static u_char *ngx_http_userid_log_uid_set(ngx_http_request_t *r, u_char *buf,
-                                           uintptr_t data)
-{
-    if (buf == NULL) {
-        return (u_char *) 1;
-    }
-
-    *buf = '-';
-
-    return buf + 1;
-}
-
-
-static u_char *ngx_http_userid_log_uid_time(ngx_http_request_t *r, u_char *buf,
-                                            uintptr_t data)
-{
-    ngx_http_userid_ctx_t   *ctx;
-
-    ctx = ngx_http_get_module_ctx(r, ngx_http_userid_module);
-
-    if (ctx == NULL || ctx->tv.tv_sec == 0) {
-        *buf = '-';
-        return buf + 1;
-    }
-
-    return buf + ngx_snprintf((char *) buf, TIME_T_LEN + 5,
-                              "%ld.%03ld",
-                              ctx->tv.tv_sec, ctx->tv.tv_usec / 1000);
-}
-
-
-static ngx_int_t ngx_http_userid_pre_conf(ngx_conf_t *cf)
-{
-    ngx_http_log_op_name_t  *op;
-
-    for (op = ngx_http_userid_log_fmt_ops; op->name.len; op++) { /* void */ }
-    op->op = NULL;
-
-    op = ngx_http_log_fmt_ops;
-
-    for (op = ngx_http_log_fmt_ops; op->op; op++) {
-        if (op->name.len == 0) {
-            op = (ngx_http_log_op_name_t *) op->op;
-        }
-    }
-
-    op->op = (ngx_http_log_op_pt) ngx_http_userid_log_fmt_ops;
-
-    return NGX_OK;
-}
-
-
-static void *ngx_http_userid_create_conf(ngx_conf_t *cf)
-{   
-    ngx_http_userid_conf_t  *conf;
-
-    if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_userid_conf_t)))) {
-        return NGX_CONF_ERROR;
-    }
-
-    /* set by ngx_pcalloc():
-
-    conf->enable = 0;
-
-    conf->name.len = 0;
-    conf->name.date = NULL;
-    conf->domain.len = 0;
-    conf->domain.date = NULL;
-    conf->path.len = 0;
-    conf->path.date = NULL;
-
-    */
-
-
-    return conf;
-}   
-
-
-static char *ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent,
-                                        void *child)
-{
-    ngx_http_userid_conf_t *prev = parent;
-    ngx_http_userid_conf_t *conf = child;
-
-    ngx_conf_merge_bitmask_value(conf->enable, prev->enable,
-                                 (NGX_CONF_BITMASK_SET
-                                  |NGX_HTTP_USERID_OFF));
-
-    ngx_conf_merge_str_value(conf->name, prev->name, "uid");
-    ngx_conf_merge_str_value(conf->domain, prev->domain, ".");
-    ngx_conf_merge_str_value(conf->path, prev->path, "/");
-
-    return NGX_CONF_OK;
-}   
-
-
-static ngx_int_t ngx_http_userid_init(ngx_cycle_t *cycle)
-{
-    ngx_http_handler_pt        *h;
-    ngx_http_core_main_conf_t  *cmcf;
-
-    cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
-
-    h = ngx_push_array(&cmcf->phases[NGX_HTTP_MISC_PHASE].handlers);
-    if (h == NULL) {
-        return NGX_ERROR;
-    }
-
-    *h = ngx_http_userid_handler;
-
-    return NGX_OK;
-}
--- a/src/http/ngx_http_log_handler.c	Fri Aug 27 15:40:59 2004 +0000
+++ b/src/http/ngx_http_log_handler.c	Sun Aug 29 03:55:41 2004 +0000
@@ -13,6 +13,8 @@
                                  uintptr_t data);
 static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf,
                                  uintptr_t data);
+static u_char *ngx_http_log_msec(ngx_http_request_t *r, u_char *buf,
+                                 uintptr_t data);
 static u_char *ngx_http_log_request(ngx_http_request_t *r, u_char *buf,
                                     uintptr_t data);
 static u_char *ngx_http_log_status(ngx_http_request_t *r, u_char *buf,
@@ -106,6 +108,7 @@
     { ngx_string("pipe"), 1, ngx_http_log_pipe },
     { ngx_string("time"), sizeof("28/Sep/1970:12:00:00") - 1,
                           ngx_http_log_time },
+    { ngx_string("msec"), TIME_T_LEN + 4, ngx_http_log_msec },
     { ngx_string("request"), 0, ngx_http_log_request },
     { ngx_string("status"), 3, ngx_http_log_status },
     { ngx_string("length"), NGX_OFF_T_LEN, ngx_http_log_length },
@@ -225,6 +228,18 @@
 }
 
 
+static u_char *ngx_http_log_msec(ngx_http_request_t *r, u_char *buf,
+                                 uintptr_t data)
+{
+    struct timeval  tv;
+
+    ngx_gettimeofday(&tv);
+
+    return buf + ngx_snprintf((char *) buf, TIME_T_LEN + 5, "%ld.%03ld",
+                              tv.tv_sec, tv.tv_usec / 1000);
+}
+
+
 static u_char *ngx_http_log_request(ngx_http_request_t *r, u_char *buf,
                                     uintptr_t data)
 {