nginx-0.3.22-RELEASE import

    *) Feature: the ngx_http_perl_module supports the $r->args and
       $r->unescape methods.

    *) Feature: the method $r->query_string of ngx_http_perl_module was
       canceled.

    *) Bugfix: segmentation fault was occurred if the "none" or "blocked"
       values was specified in the "valid_referers" directive; the bug had
       appeared in 0.3.18.
diff --git a/src/core/nginx.c b/src/core/nginx.c
index d30e127..a9a0dd9 100644
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -168,6 +168,8 @@
 
 ngx_uint_t  ngx_max_module;
 
+static char *ngx_null_environ = NULL;
+
 
 int ngx_cdecl
 main(int argc, char *const *argv)
@@ -232,6 +234,8 @@
         return 1;
     }
 
+    environ = &ngx_null_environ;
+
     ngx_max_module = 0;
     for (i = 0; ngx_modules[i]; i++) {
         ngx_modules[i]->index = ngx_max_module++;
diff --git a/src/core/nginx.h b/src/core/nginx.h
index ec125d6..a2c696f 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VER          "nginx/0.3.21"
+#define NGINX_VER          "nginx/0.3.22"
 
 #define NGINX_VAR          "NGINX"
 #define NGX_OLDPID_EXT     ".oldbin"
diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c
index 2bb335a..c99778d 100644
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -931,7 +931,7 @@
 
 
 void
-ngx_unescape_uri(u_char **dst, u_char **src, size_t size)
+ngx_unescape_uri(u_char **dst, u_char **src, size_t size, ngx_uint_t type)
 {
     u_char  *d, *s, ch, c, decoded;
     enum {
@@ -952,7 +952,7 @@
 
         switch (state) {
         case sw_usual:
-            if (ch == '?') {
+            if (ch == '?' && type == NGX_UNESCAPE_URI) {
                 *d++ = ch;
                 goto done;
             }
@@ -995,12 +995,18 @@
             if (ch >= '0' && ch <= '9') {
                 ch = (u_char) ((decoded << 4) + ch - '0');
 
-                if (ch > '%' && ch < 0x7f) {
-                    *d++ = ch;
+                if (type == NGX_UNESCAPE_URI) {
+                    if (ch > '%' && ch < 0x7f) {
+                        *d++ = ch;
+                        break;
+                    }
+
+                    *d++ = '%'; *d++ = *(s - 2); *d++ = *(s - 1);
+
                     break;
                 }
 
-                *d++ = '%'; *d++ = *(s - 2); *d++ = *(s - 1);
+                *d++ = ch;
 
                 break;
             }
@@ -1009,17 +1015,22 @@
             if (c >= 'a' && c <= 'f') {
                 ch = (u_char) ((decoded << 4) + c - 'a' + 10);
 
-                if (ch == '?') {
-                    *d++ = ch;
-                    goto done;
-                }
+                if (type == NGX_UNESCAPE_URI) {
+                    if (ch == '?') {
+                        *d++ = ch;
+                        goto done;
+                    }
 
-                if (ch > '%' && ch < 0x7f) {
-                    *d++ = ch;
+                    if (ch > '%' && ch < 0x7f) {
+                        *d++ = ch;
+                        break;
+                    }
+
+                    *d++ = '%'; *d++ = *(s - 2); *d++ = *(s - 1);
                     break;
                 }
 
-                *d++ = '%'; *d++ = *(s - 2); *d++ = *(s - 1);
+                *d++ = ch;
 
                 break;
             }
diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h
index 0192a30..d76a0f5 100644
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -144,13 +144,15 @@
 u_char * ngx_utf_cpystrn(u_char *dst, u_char *src, size_t n);
 
 
-#define NGX_ESCAPE_URI   0
-#define NGX_ESCAPE_ARGS  1
-#define NGX_ESCAPE_HTML  2
+#define NGX_ESCAPE_URI     0
+#define NGX_ESCAPE_ARGS    1
+#define NGX_ESCAPE_HTML    2
+
+#define NGX_UNESCAPE_URI   1
 
 uintptr_t ngx_escape_uri(u_char *dst, u_char *src, size_t size,
     ngx_uint_t type);
-void ngx_unescape_uri(u_char **dst, u_char **src, size_t size);
+void ngx_unescape_uri(u_char **dst, u_char **src, size_t size, ngx_uint_t type);
 
 
 #define  ngx_qsort                qsort