diff src/http/modules/ngx_http_userid_filter.c @ 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 src/http/modules/ngx_http_userid_handler.c@d6e2b445c1b8
children 48b9ad5ca1fc
line wrap: on
line diff
copy from src/http/modules/ngx_http_userid_handler.c
copy to src/http/modules/ngx_http_userid_filter.c
--- a/src/http/modules/ngx_http_userid_handler.c
+++ b/src/http/modules/ngx_http_userid_filter.c
@@ -4,16 +4,18 @@
 #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
+#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   version;
     ngx_int_t   service;
 
     ngx_str_t   name;
@@ -29,20 +31,20 @@ typedef struct {
 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 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 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);
@@ -51,11 +53,21 @@ static char *ngx_http_userid_merge_conf(
 static ngx_int_t ngx_http_userid_init(ngx_cycle_t *cycle);
 
 
-static ngx_conf_enum_t  ngx_http_userid_mask[] = {
+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_string("logonly"), NGX_HTTP_USERID_LOGONLY },
-    { ngx_string("time"), NGX_HTTP_USERID_TIME },
     { ngx_null_string, 0 }
 };
 
@@ -63,11 +75,11 @@ static ngx_conf_enum_t  ngx_http_userid_
 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_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_mask},
+      ngx_http_userid_state},
 
     { ngx_string("userid_service"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
@@ -98,7 +110,7 @@ static ngx_command_t  ngx_http_userid_co
       NULL},
 
     { ngx_string("userid_expires"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      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),
@@ -108,7 +120,7 @@ static ngx_command_t  ngx_http_userid_co
 };
 
 
-ngx_http_module_t  ngx_http_userid_module_ctx = {
+ngx_http_module_t  ngx_http_userid_filter_module_ctx = {
     ngx_http_userid_pre_conf,              /* pre conf */
 
     NULL,                                  /* create main configuration */
@@ -122,9 +134,9 @@ ngx_http_module_t  ngx_http_userid_modul
 };
 
 
-ngx_module_t  ngx_http_userid_module = {
+ngx_module_t  ngx_http_userid_filter_module = {
     NGX_MODULE,
-    &ngx_http_userid_module_ctx,           /* module context */
+    &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 */
@@ -135,47 +147,43 @@ ngx_module_t  ngx_http_userid_module = {
 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)
+static ngx_int_t ngx_http_userid_filter(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);
+    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);
+    }
 
-    if (conf->enable & NGX_HTTP_USERID_OFF) {
+    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;
     }
 
-    ctx = ngx_http_get_module_ctx(r, ngx_http_userid_module);
+    rc = ngx_http_userid_set_uid(r, ctx, conf);
 
-    if (ctx) {
-        return NGX_OK;
+    if (rc != NGX_OK) {
+        return rc;
     }
 
-    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;
+    return ngx_http_next_header_filter(r);
 }
 
 
@@ -184,8 +192,6 @@ static ngx_int_t ngx_http_userid_get_uid
                                          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;
@@ -242,29 +248,19 @@ static ngx_int_t ngx_http_userid_get_uid
 
             src.len = 22;
             src.data = start;
-
-            rc = ngx_decode_base64(r->pool, &src, &dst);
+            dst.data = (u_char *) ctx->uid_got;
 
-            if (rc == NGX_ABORT) {
-                return NGX_HTTP_INTERNAL_SERVER_ERROR;
-            }
-
-            if (rc == NGX_ERROR) {
+            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;
             }
 
-            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]);
+                           ctx->uid_got[0], ctx->uid_got[1],
+                           ctx->uid_got[2], ctx->uid_got[3]);
 
             return NGX_OK;
         }
@@ -274,13 +270,109 @@ static ngx_int_t ngx_http_userid_get_uid
 }
 
 
+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_module);
+    ctx = ngx_http_get_module_ctx(r, ngx_http_userid_filter_module);
 
     if (ctx == NULL || ctx->uid_got[3] == 0) {
         if (buf == NULL) {
@@ -291,7 +383,7 @@ static u_char *ngx_http_userid_log_uid_g
         return buf + 1;
     }
 
-    conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_module);
+    conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module);
 
     if (buf == NULL) {
         return (u_char *) (conf->name.len + 1 + 32);
@@ -310,31 +402,33 @@ static u_char *ngx_http_userid_log_uid_g
 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;
-    }
+    ngx_http_userid_ctx_t   *ctx;
+    ngx_http_userid_conf_t  *conf;
 
-    *buf = '-';
-
-    return buf + 1;
-}
+    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;
+        }
 
-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);
+    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]);
 }
 
 
@@ -369,8 +463,6 @@ static void *ngx_http_userid_create_conf
 
     /* set by ngx_pcalloc():
 
-    conf->enable = 0;
-
     conf->name.len = 0;
     conf->name.date = NULL;
     conf->domain.len = 0;
@@ -380,6 +472,8 @@ static void *ngx_http_userid_create_conf
 
     */
 
+    conf->enable = NGX_CONF_UNSET;
+    conf->expires = NGX_CONF_UNSET;
 
     return conf;
 }   
@@ -391,31 +485,22 @@ static char *ngx_http_userid_merge_conf(
     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_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_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;
+    ngx_http_next_header_filter = ngx_http_top_header_filter;
+    ngx_http_top_header_filter = ngx_http_userid_filter;
 
     return NGX_OK;
 }