nginx-0.3.10-RELEASE import

    *) Change: the "valid_referers" directive and the "$invalid_referer"
       variable were moved to the new ngx_http_referer_module from the
       ngx_http_rewrite_module.

    *) Change: the "$apache_bytes_sent" variable name was changed to
       "$body_bytes_sent".

    *) Feature: the "$sent_http_..." variables.

    *) Feature: the "if" directive supports the "=" and "!=" operations.

    *) Feature: the "proxy_pass" directive supports the HTTPS protocol.

    *) Feature: the "proxy_set_body" directive.

    *) Feature: the "post_action" directive.

    *) Feature: the ngx_http_empty_gif_module.

    *) Feature: the "worker_cpu_affinity" directive for Linux.

    *) Bugfix: the "rewrite" directive did not unescape URI part in
       redirect, now it is unescaped except the %00-%25 and %7F-%FF
       characters.

    *) Bugfix: nginx could not be built by the icc 9.0 compiler.

    *) Bugfix: if the SSI was enabled for zero size static file, then the
       chunked response was encoded incorrectly.
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index 90620cd..4986675 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -503,7 +503,7 @@
 {
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
                    "http script args");
-    
+
     e->args = e->pos;
     e->ip += sizeof(uintptr_t);
 }
@@ -664,6 +664,7 @@
 void
 ngx_http_script_regex_end_code(ngx_http_script_engine_t *e)
 {
+    u_char                            *dst, *src;
     ngx_http_request_t                *r;
     ngx_http_script_regex_end_code_t  *code;
 
@@ -678,7 +679,18 @@
 
     if (code->redirect) {
 
-        if (code->add_args && r->args.len) { 
+        dst = e->buf.data;
+        src = e->buf.data;
+
+        ngx_unescape_uri(&dst, &src, e->pos - e->buf.data);
+
+        if (src < e->pos) {
+            dst = ngx_copy(dst, src, e->pos - src);
+        }
+
+        e->pos = dst;
+
+        if (code->add_args && r->args.len) {
             *e->pos++ = (u_char) (code->args ? '&' : '?');
             e->pos = ngx_copy(e->pos, r->args.data, r->args.len);
         }
@@ -697,7 +709,7 @@
             return;
         }
 
-        r->headers_out.location->hash = 1; 
+        r->headers_out.location->hash = 1;
         r->headers_out.location->key.len = sizeof("Location") - 1;
         r->headers_out.location->key.data = (u_char *) "Location";
         r->headers_out.location->value = e->buf;
@@ -706,7 +718,7 @@
         return;
     }
 
-    if (e->args) { 
+    if (e->args) {
         e->buf.len = e->args - e->buf.data;
 
         if (code->add_args && r->args.len) {
@@ -755,9 +767,9 @@
 
 void
 ngx_http_script_return_code(ngx_http_script_engine_t *e)
-{   
+{
     ngx_http_script_return_code_t  *code;
-    
+
     code = (ngx_http_script_return_code_t *) e->ip;
 
     e->status = code->status;
@@ -798,13 +810,69 @@
     }
 
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
-                   "http script if false");
+                   "http script if: false");
 
     e->ip += code->next;
 }
 
 
 void
+ngx_http_script_equal_code(ngx_http_script_engine_t *e)
+{
+    ngx_http_variable_value_t  *val, *res;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+                   "http script equal");
+
+    e->sp--;
+    val = e->sp;
+    res = e->sp - 1;
+
+    e->ip += sizeof(uintptr_t);
+
+    if (val->len == res->len && ngx_strncmp(val->data, res->data, res->len)
+        == 0)
+    {
+        *res = ngx_http_variable_true_value;
+        return;
+    }
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+                   "http script equal: no");
+
+    *res = ngx_http_variable_null_value;
+}
+
+
+void
+ngx_http_script_not_equal_code(ngx_http_script_engine_t *e)
+{
+    ngx_http_variable_value_t  *val, *res;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+                   "http script not equal");
+
+    e->sp--;
+    val = e->sp;
+    res = e->sp - 1;
+
+    e->ip += sizeof(uintptr_t);
+
+    if (val->len == res->len && ngx_strncmp(val->data, res->data, res->len)
+        == 0)
+    {
+        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+                       "http script not equal: no");
+
+        *res = ngx_http_variable_null_value;
+        return;
+    }
+
+    *res = ngx_http_variable_true_value;
+}
+
+
+void
 ngx_http_script_complex_value_code(ngx_http_script_engine_t *e)
 {
     size_t                                 len;
@@ -840,8 +908,8 @@
 
     e->pos = e->buf.data;
 
-    e->sp->data = e->buf.data;
     e->sp->len = e->buf.len;
+    e->sp->data = e->buf.data;
     e->sp++;
 }
 
@@ -855,11 +923,12 @@
 
     e->ip += sizeof(ngx_http_script_value_code_t);
 
-    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
-                   "http script value");
-
     e->sp->len = code->text_len;
     e->sp->data = (u_char *) code->text_data;
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+                   "http script value: \"%V\"", e->sp);
+
     e->sp++;
 }
 
@@ -914,8 +983,7 @@
         return;
     }
 
-    e->sp->data = (u_char *) "";
-    e->sp->len = 0;
+    *e->sp = ngx_http_variable_null_value;
     e->sp++;
 }