nginx-0.1.2-RELEASE import

    *) Feature: the --user=USER, --group=GROUP, and --with-ld-opt=OPTIONS
       options in configure.

    *) Feature: the server_name directive supports *.domain.tld.

    *) Bugfix: the portability improvements.

    *) Bugfix: if configuration file was set in command line, the
       reconfiguration was impossible; the bug had appeared in 0.1.1.

    *) Bugfix: proxy module may get caught in an endless loop when sendfile
       is not used.

    *) Bugfix: with sendfile the response was not recoded according to the
       charset module directives; the bug had appeared in 0.1.1.

    *) Bugfix: very seldom bug in the kqueue processing.

    *) Bugfix: the gzip module compressed the proxied responses that was
       already compressed.
diff --git a/src/http/modules/ngx_http_charset_filter.c b/src/http/modules/ngx_http_charset_filter.c
index d22a86b..f2e85e5 100644
--- a/src/http/modules/ngx_http_charset_filter.c
+++ b/src/http/modules/ngx_http_charset_filter.c
@@ -12,7 +12,7 @@
 typedef struct {
     char       **tables;
     ngx_str_t    name;
-    unsigned     server;
+    ngx_uint_t   server;  /* unsigned     server:1; */
 } ngx_http_charset_t;
 
 
@@ -45,7 +45,7 @@
 } ngx_http_charset_ctx_t;
 
 
-static void ngx_charset_recode(ngx_buf_t *b, char *table);
+static ngx_uint_t ngx_charset_recode(ngx_buf_t *b, char *table);
 
 static char *ngx_charset_map_block(ngx_conf_t *cf, ngx_command_t *cmd,
                                    void *conf);
@@ -232,14 +232,31 @@
 }
 
 
-static void ngx_charset_recode(ngx_buf_t *b, char *table)
+static ngx_uint_t ngx_charset_recode(ngx_buf_t *b, char *table)
 {
-    u_char  *p, c;
+    u_char      *p;
+    ngx_uint_t   change;
+
+    change = 0;
 
     for (p = b->pos; p < b->last; p++) {
-        c = *p;
-        *p = table[c];
+        if (*p != table[*p]) {
+            change = 1;
+            break;
+        }
     }
+
+    if (change) {
+
+        while (p < b->last) {
+            *p = table[*p];
+            p++;
+        }
+
+        b->in_file = 0;
+    }
+
+    return change;
 }
 
 
@@ -419,7 +436,9 @@
         return NGX_ERROR;
     }
 
+    c->tables = NULL;
     c->name = *name;
+    c->server = 0;
 
     return i;
 }
diff --git a/src/http/modules/ngx_http_chunked_filter.c b/src/http/modules/ngx_http_chunked_filter.c
index 2112461..7881248 100644
--- a/src/http/modules/ngx_http_chunked_filter.c
+++ b/src/http/modules/ngx_http_chunked_filter.c
@@ -63,7 +63,7 @@
                                               ngx_chain_t *in)
 {
     u_char       *chunk;
-    size_t        size, len;
+    size_t        size;
     ngx_buf_t    *b;
     ngx_chain_t   out, tail, *cl, *tl, **ll;
 
@@ -98,6 +98,20 @@
     }
 
     if (size) {
+        if (!(b = ngx_calloc_buf(r->pool))) {
+            return NGX_ERROR;
+        }
+
+        if (!(chunk = ngx_palloc(r->pool, 11))) {
+            return NGX_ERROR;
+        }
+
+        b->temporary = 1;
+        b->pos = chunk;
+        b->last = ngx_sprintf(chunk, "%uxS" CRLF, size);
+
+        out.buf = b;
+#if 0
         ngx_test_null(chunk, ngx_palloc(r->pool, 11), NGX_ERROR);
         len = ngx_snprintf((char *) chunk, 11, SIZE_T_X_FMT CRLF, size);
 
@@ -107,6 +121,7 @@
         b->last = chunk + len;
 
         out.buf = b;
+#endif
     }
 
     if (cl->buf->last_buf) {
diff --git a/src/http/modules/ngx_http_gzip_filter.c b/src/http/modules/ngx_http_gzip_filter.c
index 4089ffb..bb3a1f0 100644
--- a/src/http/modules/ngx_http_gzip_filter.c
+++ b/src/http/modules/ngx_http_gzip_filter.c
@@ -837,26 +837,30 @@
         return buf + 1;
     }
 
-#if 0
-    return buf + ngx_snprintf((char *) buf, NGX_INT32_LEN + 4, "%.2f",
-                              (float) ctx->zin / ctx->zout);
-#endif
-
     /* we prefer do not use the FPU */
 
     zint = (ngx_uint_t) (ctx->zin / ctx->zout);
     zfrac = (ngx_uint_t) ((ctx->zin * 100 / ctx->zout) % 100);
 
-    if ((ctx->zin * 1000 / ctx->zout) %10 > 4) {
-        if (++zfrac > 99) {
+    if ((ctx->zin * 1000 / ctx->zout) % 10 > 4) {
+
+        /* the rounding, e.g., 2.125 to 2.13 */
+
+        zfrac++;
+
+        if (zfrac > 99) {
             zint++;
             zfrac = 0;
         }
     }
 
+    return ngx_sprintf(buf, "%ui.%02ui", zint, zfrac);
+
+#if 0
     return buf + ngx_snprintf((char *) buf, NGX_INT32_LEN + 4,
                               "%" NGX_UINT_T_FMT ".%02" NGX_UINT_T_FMT,
                               zint, zfrac);
+#endif
 }
 
 
diff --git a/src/http/modules/ngx_http_headers_filter.c b/src/http/modules/ngx_http_headers_filter.c
index f7fe52c..faf8192 100644
--- a/src/http/modules/ngx_http_headers_filter.c
+++ b/src/http/modules/ngx_http_headers_filter.c
@@ -134,10 +134,16 @@
                         return NGX_ERROR;
                     }
 
+                    cc->value.len = ngx_sprintf(cc->value.data, "max-age=%T",
+                                                conf->expires)
+                                    - cc->value.data;
+
+#if 0
                     cc->value.len = ngx_snprintf((char *) cc->value.data,
                                                sizeof("max-age=") + TIME_T_LEN,
                                                "max-age=" TIME_T_FMT,
                                                conf->expires);
+#endif
                 }
             }
         }
diff --git a/src/http/modules/ngx_http_range_filter.c b/src/http/modules/ngx_http_range_filter.c
index a08e25f..082fd3c 100644
--- a/src/http/modules/ngx_http_range_filter.c
+++ b/src/http/modules/ngx_http_range_filter.c
@@ -264,9 +264,14 @@
         }
 
         r->headers_out.content_range->value.len =
+                ngx_sprintf(r->headers_out.content_range->value.data,
+                            "bytes */%O", r->headers_out.content_length_n)
+                - r->headers_out.content_range->value.data;
+#if 0
                 ngx_snprintf((char *) r->headers_out.content_range->value.data,
                              8 + 20 + 1, "bytes */" OFF_T_FMT,
                              r->headers_out.content_length_n);
+#endif
 
         r->headers_out.content_length_n = -1;
         if (r->headers_out.content_length) {
@@ -297,12 +302,20 @@
             /* "Content-Range: bytes SSSS-EEEE/TTTT" header */
 
             r->headers_out.content_range->value.len =
+                         ngx_sprintf(r->headers_out.content_range->value.data,
+                                     "bytes %O-%O/%O",
+                                     range->start, range->end - 1,
+                                     r->headers_out.content_length_n)
+                         - r->headers_out.content_range->value.data;
+
+#if 0
                    ngx_snprintf((char *)
                                 r->headers_out.content_range->value.data,
                                 6 + 20 + 1 + 20 + 1 + 20 + 1,
                                 "bytes " OFF_T_FMT "-" OFF_T_FMT "/" OFF_T_FMT,
                                 range->start, range->end - 1,
                                 r->headers_out.content_length_n);
+#endif
 
             r->headers_out.content_length_n = range->end - range->start;
 
@@ -343,6 +356,15 @@
 
             if (r->headers_out.charset.len) {
                 ctx->boundary_header.len =
+                          ngx_sprintf(ctx->boundary_header.data,
+                                      CRLF "--%010ui" CRLF
+                                      "Content-Type: %s; charset=%s" CRLF
+                                      "Content-Range: bytes ",
+                                      boundary,
+                                      r->headers_out.content_type->value.data,
+                                      r->headers_out.charset.data)
+                          - ctx->boundary_header.data;
+#if 0
                          ngx_snprintf((char *) ctx->boundary_header.data, len,
                                       CRLF "--%010" NGX_UINT_T_FMT CRLF
                                       "Content-Type: %s; charset=%s" CRLF
@@ -350,17 +372,29 @@
                                       boundary,
                                       r->headers_out.content_type->value.data,
                                       r->headers_out.charset.data);
+#endif
 
                 r->headers_out.charset.len = 0;
 
             } else {
                 ctx->boundary_header.len =
+                          ngx_sprintf(ctx->boundary_header.data,
+                                      CRLF "--%010ui" CRLF
+                                      "Content-Type: %s" CRLF
+                                      "Content-Range: bytes ",
+                                      boundary,
+                                      r->headers_out.content_type->value.data)
+                          - ctx->boundary_header.data;
+
+#if 0
                          ngx_snprintf((char *) ctx->boundary_header.data, len,
                                       CRLF "--%010" NGX_UINT_T_FMT CRLF
                                       "Content-Type: %s" CRLF
                                       "Content-Range: bytes ",
                                       boundary,
                                       r->headers_out.content_type->value.data);
+
+#endif
             }
 
             ngx_test_null(r->headers_out.content_type->value.data,
@@ -370,12 +404,18 @@
             /* "Content-Type: multipart/byteranges; boundary=0123456789" */
 
             r->headers_out.content_type->value.len =
+                       ngx_sprintf(r->headers_out.content_type->value.data,
+                                   "multipart/byteranges; boundary=%010ui",
+                                   boundary)
+                       - r->headers_out.content_type->value.data;
+#if 0
                       ngx_snprintf((char *)
                                    r->headers_out.content_type->value.data,
                                    31 + 10 + 1,
                                    "multipart/byteranges; boundary=%010"
                                    NGX_UINT_T_FMT,
                                    boundary);
+#endif
 
             /* the size of the last boundary CRLF "--0123456789--" CRLF */
             len = 4 + 10 + 4;
@@ -389,11 +429,18 @@
                 /* the size of the range: "SSSS-EEEE/TTTT" CRLF CRLF */
 
                 range[i].content_range.len =
+                                 ngx_sprintf(range[i].content_range.data,
+                                             "%O-%O/%O" CRLF CRLF,
+                                             range[i].start, range[i].end - 1,
+                                             r->headers_out.content_length_n)
+                                 - range[i].content_range.data;
+#if 0
                   ngx_snprintf((char *) range[i].content_range.data,
                                20 + 1 + 20 + 1 + 20 + 5,
                                OFF_T_FMT "-" OFF_T_FMT "/" OFF_T_FMT CRLF CRLF,
                                range[i].start, range[i].end - 1,
                                r->headers_out.content_length_n);
+#endif
 
                 len += ctx->boundary_header.len + range[i].content_range.len
                                     + (size_t) (range[i].end - range[i].start);
diff --git a/src/http/modules/ngx_http_status_handler.c b/src/http/modules/ngx_http_status_handler.c
index 6206ac3..357afff 100644
--- a/src/http/modules/ngx_http_status_handler.c
+++ b/src/http/modules/ngx_http_status_handler.c
@@ -159,6 +159,9 @@
                   + 1 + (r->server_name ? cmcf->max_server_name_len : 1)
                   + 2;                                /* "\r\n" */
 
+            /* BUG: cmcf->max_server_name_len and "*.domain.tld" */
+
+
             if (r->request_line.len) {
                 len += 1 + 1 + r->request_line.len + 1;
             }
diff --git a/src/http/modules/ngx_http_userid_filter.c b/src/http/modules/ngx_http_userid_filter.c
index 5f8e452..bafdea8 100644
--- a/src/http/modules/ngx_http_userid_filter.c
+++ b/src/http/modules/ngx_http_userid_filter.c
@@ -367,7 +367,7 @@
 
     } else if (conf->expires) {
         p = ngx_cpymem(p, expires, sizeof("; expires=") - 1);
-        p += ngx_http_cookie_time(p, ngx_time() + conf->expires);
+        p = ngx_http_cookie_time(p, ngx_time() + conf->expires);
     }
 
     if (conf->domain.len > 1) {
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c
index f0794f3..5d61167 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -289,6 +289,8 @@
                          offsetof(ngx_http_proxy_headers_in_t, content_type) },
     { ngx_string("Content-Length"),
                        offsetof(ngx_http_proxy_headers_in_t, content_length) },
+    { ngx_string("Content-Encoding"),
+                     offsetof(ngx_http_proxy_headers_in_t, content_encoding) },
     { ngx_string("Last-Modified"),
                         offsetof(ngx_http_proxy_headers_in_t, last_modified) },
     { ngx_string("Location"),
@@ -400,7 +402,7 @@
 
 #if (HAVE_KQUEUE)
 
-    if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
+    if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
 
         if (!ev->pending_eof) {
             return;
@@ -1310,10 +1312,10 @@
 
 static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data)
 {
-#if __FreeBSD__
-
     ssize_t *np = data;
 
+#if (NGX_FREEBSD)
+
     if (*np >= ngx_freebsd_net_inet_tcp_sendspace) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                            "\"proxy_send_lowat\" must be less than %d "
@@ -1323,15 +1325,12 @@
         return NGX_CONF_ERROR;
     }
 
+#elif !(HAVE_SO_SNDLOWAT)
 
-#else
-
-#if 0
     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
                        "\"proxy_send_lowat\" is not supported, ignored");
 
     *np = 0;
-#endif
 
 #endif
 
diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.h b/src/http/modules/proxy/ngx_http_proxy_handler.h
index 728259c..3e721ba 100644
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.h
@@ -130,6 +130,7 @@
     ngx_table_elt_t                 *connection;
     ngx_table_elt_t                 *content_type;
     ngx_table_elt_t                 *content_length;
+    ngx_table_elt_t                 *content_encoding;
     ngx_table_elt_t                 *last_modified;
     ngx_table_elt_t                 *location;
     ngx_table_elt_t                 *accept_ranges;
diff --git a/src/http/modules/proxy/ngx_http_proxy_header.c b/src/http/modules/proxy/ngx_http_proxy_header.c
index 07722fc..cd5deeb 100644
--- a/src/http/modules/proxy/ngx_http_proxy_header.c
+++ b/src/http/modules/proxy/ngx_http_proxy_header.c
@@ -113,6 +113,11 @@
             continue;
         }
 
+        if (&h[i] == headers_in->content_encoding) {
+            r->headers_out.content_encoding = ho;
+            continue;
+        }
+
         if (&h[i] == headers_in->last_modified) {
             r->headers_out.last_modified = ho;
             /* TODO: update r->headers_out.last_modified_time */
diff --git a/src/http/modules/proxy/ngx_http_proxy_upstream.c b/src/http/modules/proxy/ngx_http_proxy_upstream.c
index be5d69a..88479da 100644
--- a/src/http/modules/proxy/ngx_http_proxy_upstream.c
+++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c
@@ -692,12 +692,14 @@
 
     /* rc == NGX_OK */
 
-#if 1 /* test only, see below about "post aio operation" */
+#if 0 /* test only, see below about "post aio operation" */
 
     if (c->read->ready) {
         /* post aio operation */
         ngx_http_proxy_process_upstream_status_line(c->read);
+#if 0
         return;
+#endif
     }
 
 #endif
@@ -718,7 +720,7 @@
 
 #if (HAVE_KQUEUE)
 
-    if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT)
+    if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT)
         && !p->request_sent
         && c->write->pending_eof)
     {
@@ -776,7 +778,7 @@
 
     ngx_add_timer(c->read, p->lcf->read_timeout);
 
-#if 0
+#if 1
     if (c->read->ready) {
 
         /* post aio operation */