changeset 415:3c56e834be46

nginx-0.0.10-2004-09-05-23:54:02 import
author Igor Sysoev <igor@sysoev.ru>
date Sun, 05 Sep 2004 19:54:02 +0000
parents 388a842cbbe1
children b9bd635011de
files auto/modules auto/options src/core/ngx_array.h src/core/ngx_conf_file.c src/core/ngx_cycle.c src/core/ngx_list.h src/core/ngx_log.c src/http/modules/ngx_http_gzip_filter.c src/http/modules/ngx_http_headers_filter.c src/http/modules/ngx_http_range_filter.c src/http/modules/ngx_http_static_handler.c src/http/modules/ngx_http_status_handler.c src/http/modules/ngx_http_userid_filter.c src/http/modules/proxy/ngx_http_proxy_upstream.c src/http/ngx_http_core_module.c src/http/ngx_http_header_filter.c src/http/ngx_http_log_handler.c src/http/ngx_http_request.c src/http/ngx_http_request.h src/http/ngx_http_special_response.c src/imap/ngx_imap.c src/imap/ngx_imap_handler.c src/imap/ngx_imap_proxy.c src/imap/ngx_imap_proxy_handler.c
diffstat 22 files changed, 285 insertions(+), 167 deletions(-) [+]
line wrap: on
line diff
--- a/auto/modules
+++ b/auto/modules
@@ -126,11 +126,15 @@ if [ -r $OBJS/auto ]; then
     . $OBJS/auto
 fi
 
-modules="$CORE_MODULES $EVENT_MODULES $HTTP_MODULES $HTTP_FILTER_MODULES \
-         $HTTP_HEADERS_FILTER_MODULE \
-         $HTTP_COPY_FILTER_MODULE \
-         $HTTP_RANGE_BODY_FILTER_MODULE \
-         $HTTP_NOT_MODIFIED_FILTER_MODULE"
+modules="$CORE_MODULES $EVENT_MODULES"
+
+if [ $HTTP = YES ]; then
+    modules="$modules $HTTP_MODULES $HTTP_FILTER_MODULES \
+             $HTTP_HEADERS_FILTER_MODULE \
+             $HTTP_COPY_FILTER_MODULE \
+             $HTTP_RANGE_BODY_FILTER_MODULE \
+             $HTTP_NOT_MODIFIED_FILTER_MODULE"
+fi
 
 
 echo "#include <ngx_config.h>"                > $NGX_MODULES_C
--- a/auto/options
+++ b/auto/options
@@ -29,6 +29,7 @@ EVENT_AIO=NO
 
 USE_THREADS=NO
 
+HTTP=YES
 HTTP_CHARSET=YES
 HTTP_GZIP=YES
 HTTP_SSL=NO
@@ -70,7 +71,6 @@ do
         --prefix=*)                      PREFIX="$value"            ;;
         --sbin-path=*)                   SBIN_PATH="$value"         ;;
         --conf-path=*)                   CONF_PATH="$value"         ;;
-        --http-log-path=*)               HTTP_LOG_PATH="$value"     ;;
         --error-log-path=*)              ERROR_LOG_PATH="$value"    ;;
         --pid-path=*)                    PID_PATH="$value"          ;;
 
@@ -88,6 +88,9 @@ do
         --with-threads=*)                USE_THREADS="$value"       ;;
         --with-threads)                  USE_THREADS="pthreads"     ;;
 
+        --without-http)                  HTTP=NO                    ;;
+        --http-log-path=*)               HTTP_LOG_PATH="$value"     ;;
+
         --with-http_ssl_module)          HTTP_SSL=YES               ;;
         --without-http_charset_module)   HTTP_CHARSET=NO            ;;
         --without-http_gzip_module)      HTTP_GZIP=NO               ;;
--- a/src/core/ngx_array.h
+++ b/src/core/ngx_array.h
@@ -20,6 +20,23 @@ void ngx_destroy_array(ngx_array_t *a);
 void *ngx_push_array(ngx_array_t *a);
 
 
+ngx_inline static ngx_int_t ngx_init_array0(ngx_array_t *array, ngx_pool_t *pool,
+                                           ngx_uint_t n, size_t size)
+{
+    if (!(array->elts = ngx_palloc(pool, n * size))) {
+        return NGX_ERROR;
+    }
+
+    array->nelts = 0;
+    array->size = size;
+    array->nalloc = n;
+    array->pool = pool;
+
+    return NGX_OK;
+}
+
+
+
 #define ngx_init_array(a, p, n, s, rc)                                       \
     ngx_test_null(a.elts, ngx_palloc(p, n * s), rc);                         \
     a.nelts = 0; a.size = s; a.nalloc = n; a.pool = p;
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -590,10 +590,6 @@ ngx_open_file_t *ngx_conf_open_file(ngx_
                 i = 0;
             }
 
-#if 0
-        file = cycle->open_files.elts;
-        for (i = 0; i < cycle->open_files.nelts; i++) {
-#endif
             if (name->len != file[i].name.len) {
                 continue;
             }
@@ -612,6 +608,9 @@ ngx_open_file_t *ngx_conf_open_file(ngx_
 
     if (name) {
         file->name = *name;
+    } else {
+        file->name.len = 0;
+        file->name.data = NULL;
     }
 
     return file;
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -24,6 +24,8 @@ ngx_tls_key_t          ngx_core_tls_key;
 static ngx_connection_t  dumb;
 /* STUB */
 
+static ngx_str_t  error_log = ngx_string(NGX_ERROR_LOG_PATH);
+
 
 ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle)
 {
@@ -79,31 +81,12 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t 
         n = 20;
     }
 
-    cycle->open_files.part.elts = ngx_palloc(pool, n * sizeof(ngx_open_file_t));
-    if (cycle->open_files.part.elts == NULL) {
+    if (ngx_init_list(&cycle->open_files, pool, n, sizeof(ngx_open_file_t))
+                                                                  == NGX_ERROR)
+    {
         ngx_destroy_pool(pool);
         return NULL;
     }
-    cycle->open_files.part.nelts = 0;
-    cycle->open_files.part.next = NULL;
-    cycle->open_files.last = &cycle->open_files.part;
-    cycle->open_files.size = sizeof(ngx_open_file_t);
-    cycle->open_files.nalloc = n;
-    cycle->open_files.pool = pool;
-
-
-#if 0
-    n = old_cycle->open_files.nelts ? old_cycle->open_files.nelts : 20;
-    cycle->open_files.elts = ngx_pcalloc(pool, n * sizeof(ngx_open_file_t));
-    if (cycle->open_files.elts == NULL) {
-        ngx_destroy_pool(pool);
-        return NULL;
-    }
-    cycle->open_files.nelts = 0;
-    cycle->open_files.size = sizeof(ngx_open_file_t);
-    cycle->open_files.nalloc = n;
-    cycle->open_files.pool = pool;
-#endif
 
 
     if (!(cycle->new_log = ngx_log_create_errlog(cycle, NULL))) {
@@ -111,6 +94,8 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t 
         return NULL;
     }
 
+    cycle->new_log->file->name = error_log;
+
 
     n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10;
     cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t));
@@ -221,11 +206,6 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t 
                 i = 0;
             }
 
-#if 0
-        file = cycle->open_files.elts;
-        for (i = 0; i < cycle->open_files.nelts; i++) {
-#endif
-
             if (file[i].name.data == NULL) {
                 continue;
             }
@@ -234,7 +214,9 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t 
                                        NGX_FILE_RDWR,
                                        NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND);
 
+#if 0
             log->log_level = NGX_LOG_DEBUG_ALL;
+#endif
             ngx_log_debug3(NGX_LOG_DEBUG_CORE, log, 0,
                            "log: %0X %d \"%s\"",
                            &file[i], file[i].fd, file[i].name.data);
@@ -270,6 +252,10 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t 
     cycle->log = cycle->new_log;
     pool->log = cycle->new_log;
 
+    if (cycle->log->log_level == 0) {
+        cycle->log->log_level = NGX_LOG_ERR;
+    }
+
     if (!failed) {
         if (old_cycle->listening.nelts) {
             ls = old_cycle->listening.elts;
@@ -335,7 +321,7 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t 
 
 #if !(WIN32)
 
-    if (!failed && !ngx_test_config) {
+    if (!failed && !ngx_test_config && cycle->log->file->fd != STDERR_FILENO) {
 
         ngx_log_debug3(NGX_LOG_DEBUG_CORE, log, 0,
                        "dup2: %0X %d \"%s\"",
@@ -369,11 +355,6 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t 
                 i = 0;
             }
 
-#if 0
-        file = cycle->open_files.elts;
-        for (i = 0; i < cycle->open_files.nelts; i++) {
-#endif
-
             if (file[i].fd == NGX_INVALID_FILE) {
                 continue;
             }
@@ -456,11 +437,6 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t 
             i = 0;
         }
 
-#if 0
-    file = old_cycle->open_files.elts;
-    for (i = 0; i < old_cycle->open_files.nelts; i++) {
-#endif
-
         if (file[i].fd == NGX_INVALID_FILE) {
             continue;
         }
@@ -639,11 +615,6 @@ void ngx_reopen_files(ngx_cycle_t *cycle
             i = 0;
         }
 
-#if 0
-    file = cycle->open_files.elts;
-    for (i = 0; i < cycle->open_files.nelts; i++) {
-#endif
-
         if (file[i].name.data == NULL) {
             continue;
         }
@@ -715,9 +686,11 @@ void ngx_reopen_files(ngx_cycle_t *cycle
 
 #if !(WIN32)
 
-    if (dup2(cycle->log->file->fd, STDERR_FILENO) == -1) {
-        ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
-                      "dup2(STDERR) failed");
+    if (cycle->log->file->fd != STDERR_FILENO) {
+        if (dup2(cycle->log->file->fd, STDERR_FILENO) == -1) {
+            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
+                          "dup2(STDERR) failed");
+        }
     }
 
 #endif
--- a/src/core/ngx_list.h
+++ b/src/core/ngx_list.h
@@ -24,22 +24,47 @@ typedef struct {
 } ngx_list_t;
 
 
-#define ngx_init_list(l, p, n, s, rc)                                        \
-    if (!(l.part.elts = ngx_palloc(p, n * s))) {                             \
-        return rc;                                                           \
-    }                                                                        \
-    l.part.nelts = 0; l.part.next = NULL;                                    \
-    l.last = &l.part; l.size = s; l.nalloc = n; l.pool = p;
+ngx_inline static ngx_int_t ngx_init_list(ngx_list_t *list, ngx_pool_t *pool,
+                                          ngx_uint_t n, size_t size)
+{
+    if (!(list->part.elts = ngx_palloc(pool, n * size))) {
+        return NGX_ERROR;
+    }
+
+    list->part.nelts = 0;
+    list->part.next = NULL;
+    list->last = &list->part;
+    list->size = size;
+    list->nalloc = n;
+    list->pool = pool;
+
+    return NGX_OK;
+}
 
 
-#define ngx_iterate_list(p, i)                                               \
-            for ( ;; i++) {                                                  \
-                if (i >= p->nelts) {                                         \
-                    if (p->next == NULL) {                                   \
-                        break;                                               \
-                    }                                                        \
-                    p = p->next; i = 0;                                      \
-                }
+/*
+ *
+ *  the iteration through the list:
+ *
+ *  part = &list.part;
+ *  data = part->elts;
+ *
+ *  for (i = 0 ;; i++) {
+ *
+ *      if (i >= part->nelts) {
+ *          if (part->next == NULL) {
+ *              break;
+ *          }
+ *
+ *          part = part->next;
+ *          data = part->elts;
+ *          i = 0;
+ *      }
+ *
+ *      ...  data[i] ...
+ *
+ *  }
+ */
 
 
 void *ngx_push_list(ngx_list_t *list);
--- a/src/core/ngx_log.c
+++ b/src/core/ngx_log.c
@@ -37,8 +37,8 @@ ngx_module_t  ngx_errlog_module = {
 };
 
 
+static ngx_log_t        ngx_log;
 static ngx_open_file_t  ngx_stderr;
-static ngx_log_t        ngx_log;
 
 
 static const char *err_levels[] = {
@@ -296,8 +296,13 @@ ngx_log_t *ngx_log_create_errlog(ngx_cyc
         name = NULL;
     }
 
-    ngx_test_null(log, ngx_pcalloc(cycle->pool, sizeof(ngx_log_t)), NULL);
-    ngx_test_null(log->file, ngx_conf_open_file(cycle, name), NULL);
+    if (!(log = ngx_pcalloc(cycle->pool, sizeof(ngx_log_t)))) {
+        return NULL;
+    }
+
+    if (!(log->file = ngx_conf_open_file(cycle, name))) {
+        return NULL;
+    }
 
     return log;
 }
@@ -363,7 +368,9 @@ static char *ngx_set_error_log(ngx_conf_
     value = cf->args->elts;
 
     if (value[1].len == 6 && ngx_strcmp(value[1].data, "stderr") == 0) {
-        cf->cycle->new_log->file = &ngx_stderr;
+        cf->cycle->new_log->file->fd = ngx_stderr.fd;
+        cf->cycle->new_log->file->name.len = 0;
+        cf->cycle->new_log->file->name.data = NULL;
 
     } else {
         cf->cycle->new_log->file->name = value[1];
--- a/src/http/modules/ngx_http_gzip_filter.c
+++ b/src/http/modules/ngx_http_gzip_filter.c
@@ -297,8 +297,7 @@ static ngx_int_t ngx_http_gzip_header_fi
                         sizeof(ngx_http_gzip_ctx_t), NGX_ERROR);
     ctx->request = r;
 
-    r->headers_out.content_encoding =
-                    ngx_http_add_header(&r->headers_out, ngx_http_headers_out);
+    r->headers_out.content_encoding = ngx_push_list(&r->headers_out.headers);
     if (r->headers_out.content_encoding == NULL) {
         return NGX_ERROR;
     }
--- a/src/http/modules/ngx_http_headers_filter.c
+++ b/src/http/modules/ngx_http_headers_filter.c
@@ -75,15 +75,13 @@ static ngx_int_t ngx_http_headers_filter
 
     if (conf->expires != NGX_HTTP_EXPIRES_OFF) {
 
-        expires = ngx_http_add_header(&r->headers_out, ngx_http_headers_out);
-        if (expires == NULL) {
+        if (!(expires = ngx_push_list(&r->headers_out.headers))) {
             return NGX_ERROR;
         }
 
         r->headers_out.expires = expires;
 
-        cc = ngx_http_add_header(&r->headers_out, ngx_http_headers_out);
-        if (cc == NULL) {
+        if (!(cc = ngx_push_list(&r->headers_out.headers))) {
             return NGX_ERROR;
         }
 
--- a/src/http/modules/ngx_http_range_filter.c
+++ b/src/http/modules/ngx_http_range_filter.c
@@ -123,9 +123,8 @@ static ngx_int_t ngx_http_range_header_f
         || ngx_strncasecmp(r->headers_in.range->value.data, "bytes=", 6) != 0)
     {
 
-        if (!(r->headers_out.accept_ranges =
-                   ngx_http_add_header(&r->headers_out, ngx_http_headers_out)))
-        {
+        r->headers_out.accept_ranges = ngx_push_list(&r->headers_out.headers);
+        if (r->headers_out.accept_ranges == NULL) {
             return NGX_ERROR;
         }
 
@@ -245,18 +244,19 @@ static ngx_int_t ngx_http_range_header_f
         r->headers_out.status = rc;
         r->headers_out.ranges.nelts = 0;
 
-        if (!(r->headers_out.content_range =
-                   ngx_http_add_header(&r->headers_out, ngx_http_headers_out)))
-        {
+        r->headers_out.content_range = ngx_push_list(&r->headers_out.headers);
+        if (r->headers_out.content_range == NULL) {
             return NGX_ERROR;
         }
 
         r->headers_out.content_range->key.len = sizeof("Content-Range") - 1;
         r->headers_out.content_range->key.data = (u_char *) "Content-Range";
 
-        ngx_test_null(r->headers_out.content_range->value.data,
-                      ngx_palloc(r->pool, 8 + 20 + 1),
-                      NGX_ERROR);
+        r->headers_out.content_range->value.data =
+                                               ngx_palloc(r->pool, 8 + 20 + 1);
+        if (r->headers_out.content_range->value.data == NULL) {
+            return NGX_ERROR;
+        }
 
         r->headers_out.content_range->value.len =
                 ngx_snprintf((char *) r->headers_out.content_range->value.data,
@@ -276,9 +276,9 @@ static ngx_int_t ngx_http_range_header_f
 
         if (r->headers_out.ranges.nelts == 1) {
 
-            if (!(r->headers_out.content_range =
-                   ngx_http_add_header(&r->headers_out, ngx_http_headers_out)))
-            {
+            r->headers_out.content_range =
+                                        ngx_push_list(&r->headers_out.headers);
+            if (r->headers_out.content_range == NULL) {
                 return NGX_ERROR;
             }
 
--- a/src/http/modules/ngx_http_static_handler.c
+++ b/src/http/modules/ngx_http_static_handler.c
@@ -341,8 +341,7 @@ static ngx_int_t ngx_http_static_handler
         *last++ = '/';
         *last = '\0';
 
-        if (!(r->headers_out.location =
-                   ngx_http_add_header(&r->headers_out, ngx_http_headers_out)))
+        if (!(r->headers_out.location = ngx_push_list(&r->headers_out.headers)))
         {
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
         }
--- a/src/http/modules/ngx_http_status_handler.c
+++ b/src/http/modules/ngx_http_status_handler.c
@@ -70,8 +70,7 @@ static ngx_int_t ngx_http_status_handler
         return rc;
     }
 
-    if (!(r->headers_out.content_type =
-                   ngx_http_add_header(&r->headers_out, ngx_http_headers_out)))
+    if (!(r->headers_out.content_type = ngx_push_list(&r->headers_out.headers)))
     {
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     } 
--- a/src/http/modules/ngx_http_userid_filter.c
+++ b/src/http/modules/ngx_http_userid_filter.c
@@ -196,25 +196,22 @@ static ngx_int_t ngx_http_userid_get_uid
                                          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;
+    u_char            *start, *last, *end;
+    ngx_uint_t         i;
+    ngx_str_t          src, dst;
+    ngx_table_elt_t  **cookies;
 
-    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);
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                       "cookie: \"%s\"", cookies[i]->value.data);
 
-        end = headers[cookies[i]].value.data + headers[cookies[i]].value.len;
+        end = cookies[i]->value.data + cookies[i]->value.len;
 
-        for (start = headers[cookies[i]].value.data; start < end; /* void */) {
+        for (start = cookies[i]->value.data; start < end; /* void */) {
 
-            if (conf->name.len >= headers[cookies[i]].value.len
+            if (conf->name.len >= cookies[i]->value.len
                 || ngx_strncmp(start, conf->name.data, conf->name.len) != 0)
             {
                 start += conf->name.len;
@@ -241,7 +238,7 @@ static ngx_int_t ngx_http_userid_get_uid
             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);
+                              cookies[i]->value.data);
                 break;
             }
 
@@ -258,7 +255,7 @@ static ngx_int_t ngx_http_userid_get_uid
             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);
+                              cookies[i]->value.data);
                 break;
             }
 
@@ -384,8 +381,7 @@ static ngx_int_t ngx_http_userid_set_uid
     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) {
+    if (!(set_cookie = ngx_push_list(&r->headers_out.headers))) {
         return NGX_ERROR;
     }
 
--- a/src/http/modules/proxy/ngx_http_proxy_upstream.c
+++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c
@@ -113,6 +113,7 @@ static ngx_chain_t *ngx_http_proxy_creat
     ngx_uint_t                       i;
     ngx_buf_t                       *b;
     ngx_chain_t                     *chain;
+    ngx_list_part_t                 *part;
     ngx_table_elt_t                 *header;
     ngx_http_request_t              *r;
     ngx_http_proxy_upstream_conf_t  *uc;
@@ -165,8 +166,20 @@ static ngx_chain_t *ngx_http_proxy_creat
     }
 
 
-    header = r->headers_in.headers.elts;
-    for (i = 0; i < r->headers_in.headers.nelts; i++) {
+    part = &r->headers_in.headers.part;
+    header = part->elts;
+
+    for (i = 0; /* void */; i++) {
+
+        if (i >= part->nelts) {
+            if (part->next == NULL) {
+                break;
+            }
+
+            part = part->next;
+            header = part->elts;
+            i = 0;
+        }
 
         if (&header[i] == r->headers_in.host) {
             continue;
@@ -274,7 +287,20 @@ static ngx_chain_t *ngx_http_proxy_creat
     }
 
 
-    for (i = 0; i < r->headers_in.headers.nelts; i++) {
+    part = &r->headers_in.headers.part;
+    header = part->elts;
+
+    for (i = 0; /* void */; i++) {
+
+        if (i >= part->nelts) {
+            if (part->next == NULL) {
+                break;
+            }
+
+            part = part->next;
+            header = part->elts;
+            i = 0;
+        }
 
         if (&header[i] == r->headers_in.host) {
             continue;
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -531,8 +531,7 @@ ngx_int_t ngx_http_find_location_config(
 
 
     if (rc == NGX_HTTP_LOCATION_AUTO_REDIRECT) {
-        if (!(r->headers_out.location =
-                   ngx_http_add_header(&r->headers_out, ngx_http_headers_out)))
+        if (!(r->headers_out.location = ngx_push_list(&r->headers_out.headers)))
         {
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
         }
@@ -674,8 +673,7 @@ ngx_int_t ngx_http_set_content_type(ngx_
     ngx_http_type_t           *type;
     ngx_http_core_loc_conf_t  *clcf;
 
-    if (!(r->headers_out.content_type =
-                   ngx_http_add_header(&r->headers_out, ngx_http_headers_out)))
+    if (!(r->headers_out.content_type = ngx_push_list(&r->headers_out.headers)))
     {
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
--- a/src/http/ngx_http_header_filter.c
+++ b/src/http/ngx_http_header_filter.c
@@ -92,12 +92,13 @@ static ngx_str_t http_codes[] = {
 
 static ngx_int_t ngx_http_header_filter(ngx_http_request_t *r)
 {
-    u_char            *p;
-    size_t             len;
-    ngx_uint_t         status, i;
-    ngx_buf_t         *b;
-    ngx_chain_t       *ln;
-    ngx_table_elt_t   *header;
+    u_char           *p;
+    size_t            len;
+    ngx_uint_t        status, i;
+    ngx_buf_t        *b;
+    ngx_chain_t      *ln;
+    ngx_list_part_t  *part;
+    ngx_table_elt_t  *header;
 
     if (r->http_version < NGX_HTTP_VERSION_10) {
         return NGX_OK;
@@ -205,8 +206,26 @@ static ngx_int_t ngx_http_header_filter(
         len += sizeof("Connection: closed" CRLF) - 1;
     }
 
+    part = &r->headers_out.headers.part;
+    header = part->elts;
+
+    for (i = 0; /* void */; i++) {
+
+        if (i >= part->nelts) {
+            if (part->next == NULL) {
+                break;
+            }
+
+            part = part->next;
+            header = part->elts;
+            i = 0;
+        }
+
+#if 0
     header = r->headers_out.headers.elts;
     for (i = 0; i < r->headers_out.headers.nelts; i++) {
+#endif
+
         if (header[i].key.len == 0) {
             continue;
         }
@@ -321,7 +340,25 @@ static ngx_int_t ngx_http_header_filter(
                              sizeof("Connection: close" CRLF) - 1);
     }
 
+    part = &r->headers_out.headers.part;
+    header = part->elts;
+
+    for (i = 0; /* void */; i++) {
+
+        if (i >= part->nelts) {
+            if (part->next == NULL) {
+                break;
+            }
+
+            part = part->next;
+            header = part->elts;
+            i = 0;
+        }
+
+#if 0
     for (i = 0; i < r->headers_out.headers.nelts; i++) {
+#endif
+
         if (header[i].key.len == 0) {
             continue;
         }
--- a/src/http/ngx_http_log_handler.c
+++ b/src/http/ngx_http_log_handler.c
@@ -94,7 +94,7 @@ ngx_module_t  ngx_http_log_module = {
 };
 
 
-static ngx_str_t http_access_log = ngx_string("access.log");
+static ngx_str_t http_access_log = ngx_string(NGX_HTTP_LOG_PATH);
 
 
 static ngx_str_t ngx_http_combined_fmt =
@@ -339,12 +339,26 @@ static u_char *ngx_http_log_unknown_head
 {
     ngx_uint_t        i;
     ngx_str_t        *s;
+    ngx_list_part_t  *part;
     ngx_table_elt_t  *h;
 
     s = (ngx_str_t *) data;
 
-    h = r->headers_in.headers.elts;
-    for (i = 0; i < r->headers_in.headers.nelts; i++) {
+    part = &r->headers_in.headers.part;
+    h = part->elts;
+
+    for (i = 0; /* void */; i++) {
+
+        if (i >= part->nelts) {
+            if (part->next == NULL) {
+                break;
+            }
+
+            part = part->next;
+            h = part->elts;
+            i = 0;
+        }
+
         if (h[i].key.len != s->len) {
             continue;
         }
@@ -547,12 +561,26 @@ static u_char *ngx_http_log_unknown_head
 {
     ngx_uint_t        i;
     ngx_str_t        *s;
+    ngx_list_part_t  *part;
     ngx_table_elt_t  *h;
 
     s = (ngx_str_t *) data;
 
-    h = r->headers_out.headers.elts;
-    for (i = 0; i < r->headers_out.headers.nelts; i++) {
+    part = &r->headers_out.headers.part;
+    h = part->elts;
+
+    for (i = 0; /* void */; i++) {
+
+        if (i >= part->nelts) {
+            if (part->next == NULL) {
+                break;
+            }
+
+            part = part->next;
+            h = part->elts;
+            i = 0;
+        }
+
         if (h[i].key.len != s->len) {
             continue;
         }
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -40,6 +40,7 @@ static char *client_header_errors[] = {
 
     "client %s sent invalid header, URL: %s",
     "client %s sent too long header line, URL: %s",
+    "client %s sent too many headers, URL: %s",
     "client %s sent HTTP/1.1 request without \"Host\" header, URL: %s",
     "client %s sent invalid \"Content-Length\" header, URL: %s",
     "client %s sent POST method without \"Content-Length\" header, URL: %s",
@@ -309,6 +310,16 @@ static void ngx_http_init_request(ngx_ev
     r->cleanup.pool = r->pool;
 
 
+    if (ngx_init_list(&r->headers_out.headers, r->pool, 2,
+                                         sizeof(ngx_table_elt_t)) == NGX_ERROR)
+    {
+        ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+        ngx_http_close_connection(c);
+        return;
+    }
+
+
+#if 0
     /* init the r->headers_out.headers table */
 
     r->headers_out.headers.elts = ngx_pcalloc(r->pool,
@@ -322,6 +333,7 @@ static void ngx_http_init_request(ngx_ev
     r->headers_out.headers.nalloc = 20;
     r->headers_out.headers.size = sizeof(ngx_table_elt_t);
     r->headers_out.headers.pool = r->pool;
+#endif
 
 
     r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
@@ -607,37 +619,23 @@ static void ngx_http_process_request_lin
         }
 
 
-        /* init the r->headers_in.headers table */
-
-        r->headers_in.headers.elts = ngx_pcalloc(r->pool,
-                                                 20 * sizeof(ngx_table_elt_t));
-        if (r->headers_in.headers.elts == NULL) {
+        if (ngx_init_list(&r->headers_in.headers, r->pool, 2,
+                                         sizeof(ngx_table_elt_t)) == NGX_ERROR)
+        {
             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
             ngx_http_close_connection(c);
             return;
         }
 
-        /* r->headers_in.headers.nelts = 0; */
-        r->headers_in.headers.size = sizeof(ngx_table_elt_t);
-        r->headers_in.headers.nalloc = 20;
-        r->headers_in.headers.pool = r->pool;
-
-
-        /* init the r->headers_in.cookies array */
-
-        r->headers_in.cookies.elts = ngx_pcalloc(r->pool,
-                                                 5 * sizeof(ngx_uint_t));
-        if (r->headers_in.cookies.elts == NULL) {
+
+        if (ngx_init_array0(&r->headers_in.cookies, r->pool, 5,
+                                       sizeof(ngx_table_elt_t *)) == NGX_ERROR)
+        {
             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
             ngx_http_close_connection(c);
             return;
         }
 
-        /* r->headers_in.cookies.nelts = 0; */
-        r->headers_in.cookies.size = sizeof(ngx_uint_t);
-        r->headers_in.cookies.nalloc = 5;
-        r->headers_in.cookies.pool = r->pool;
-
 
         ctx = c->log->data;
         ctx->action = "reading client request headers";
@@ -731,8 +729,7 @@ static void ngx_http_process_request_hea
 {
     ssize_t                    n;
     ngx_int_t                  rc, i, offset;
-    ngx_uint_t                *cookie;
-    ngx_table_elt_t           *h;
+    ngx_table_elt_t           *h, **cookie;
     ngx_connection_t          *c;
     ngx_http_request_t        *r;
     ngx_http_core_srv_conf_t  *cscf;
@@ -761,14 +758,21 @@ static void ngx_http_process_request_hea
             }
         }
 
+        if (r->headers_n > 100) {
+            ngx_http_client_error(r, NGX_HTTP_PARSE_TOO_MANY_HEADERS,
+                                  NGX_HTTP_BAD_REQUEST);
+            return;
+        }
+
         rc = ngx_http_parse_header_line(r, r->header_in);
 
         if (rc == NGX_OK) {
 
             /* a header line has been parsed successfully */
 
-            h = ngx_http_add_header(&r->headers_in, ngx_http_headers_in);
-            if (h == NULL) {
+            r->headers_n++;
+
+            if (!(h = ngx_push_list(&r->headers_in.headers))) {
                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                 ngx_http_close_connection(c);
                 return;
@@ -809,7 +813,7 @@ static void ngx_http_process_request_hea
                     return;
                 }
 
-                *cookie = r->headers_in.headers.nelts - 1;
+                *cookie = h;
 
             } else {
 
@@ -1369,7 +1373,7 @@ ngx_int_t ngx_http_discard_body(ngx_http
 
 static void ngx_http_read_discarded_body_event(ngx_event_t *rev)
 {
-    int                  rc;
+    ngx_int_t            rc;
     ngx_connection_t    *c;
     ngx_http_request_t  *r;
 
@@ -1446,7 +1450,7 @@ static ngx_int_t ngx_http_read_discarded
 
 static void ngx_http_set_keepalive(ngx_http_request_t *r)
 {
-    int                        len;
+    size_t                     len;
     ngx_buf_t                 *b;
     ngx_event_t               *rev, *wev;
     ngx_connection_t          *c;
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -28,11 +28,12 @@
 #define NGX_HTTP_PARSE_HEADER_ERROR        14
 #define NGX_HTTP_PARSE_INVALID_HEADER      14
 #define NGX_HTTP_PARSE_TOO_LONG_HEADER     15
-#define NGX_HTTP_PARSE_NO_HOST_HEADER      16
-#define NGX_HTTP_PARSE_INVALID_CL_HEADER   17
-#define NGX_HTTP_PARSE_POST_WO_CL_HEADER   18
-#define NGX_HTTP_PARSE_HTTP_TO_HTTPS       19
-#define NGX_HTTP_PARSE_INVALID_HOST        20
+#define NGX_HTTP_PARSE_TOO_MANY_HEADERS    16
+#define NGX_HTTP_PARSE_NO_HOST_HEADER      17
+#define NGX_HTTP_PARSE_INVALID_CL_HEADER   18
+#define NGX_HTTP_PARSE_POST_WO_CL_HEADER   19
+#define NGX_HTTP_PARSE_HTTP_TO_HTTPS       20
+#define NGX_HTTP_PARSE_INVALID_HOST        21
 
 
 #define NGX_HTTP_OK                        200
@@ -114,7 +115,7 @@ typedef struct {
 
 
 typedef struct {
-    ngx_table_t       headers;   /* it must be first field */
+    ngx_list_t        headers;
 
     ngx_table_elt_t  *host;
     ngx_table_elt_t  *connection;
@@ -158,7 +159,10 @@ typedef struct {
 
 
 typedef struct {
+    ngx_list_t        headers;
+#if 0
     ngx_table_t       headers;   /* it must be first field */
+#endif
 
     ngx_uint_t        status;
     ngx_str_t         status_line;
@@ -307,6 +311,8 @@ struct ngx_http_request_s {
     unsigned             filter_need_temporary:1;
     unsigned             filter_allow_ranges:1;
 
+    ngx_uint_t           headers_n;
+
     /* used to parse HTTP headers */
     ngx_int_t            state;
     u_char              *uri_start;
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -283,7 +283,7 @@ ngx_int_t ngx_http_special_response_hand
         }
 
         if (!(r->headers_out.content_type =
-                   ngx_http_add_header(&r->headers_out, ngx_http_headers_out)))
+                                       ngx_push_list(&r->headers_out.headers)))
         {
             return NGX_ERROR;
         }
rename from src/imap/ngx_imap_proxy.c
rename to src/imap/ngx_imap.c
rename from src/imap/ngx_imap_proxy_handler.c
rename to src/imap/ngx_imap_handler.c
--- a/src/imap/ngx_imap_proxy_handler.c
+++ b/src/imap/ngx_imap_handler.c
@@ -4,10 +4,10 @@
 #include <ngx_event.h>
 
 
-void ngx_imap_proxy_init_connection(ngx_connection_t *c)
+void ngx_imap_init_connection(ngx_connection_t *c)
 {
     ngx_log_debug0(NGX_LOG_DEBUG_IMAP, c->log, 0,
-                   "imap proxy init connection");
+                   "imap init connection");
 
     if (ngx_close_socket(c->fd) == -1) {