changeset 665:0b460e61bdcd default tip

Merge with nginx 1.0.0.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 25 Apr 2011 04:22:17 +0400
parents 06419a2298a9 (current diff) 00d13b6d4ebd (diff)
children
files .hgtags auto/modules src/mail/ngx_mail.h src/mail/ngx_mail_auth_http_module.c src/mail/ngx_mail_handler.c src/mail/ngx_mail_imap_handler.c src/mail/ngx_mail_pop3_handler.c src/mail/ngx_mail_proxy_module.c src/mail/ngx_mail_smtp_handler.c
diffstat 175 files changed, 13302 insertions(+), 4167 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Sun Sep 27 01:10:42 2009 +0400
+++ b/.hgtags	Mon Apr 25 04:22:17 2011 +0400
@@ -271,3 +271,49 @@
 0161f31978175e258b8bb4989262b2ccb5fa9207 NGINX_0_8_15
 005a70f9573bc6bcf760786cb0573a62f1e570f3 NGINX_0_8_16
 5938746e70c2ae3e83fb402c030635f5ab459251 PATCH_NGINX_MAIL_0_8
+4c5d2c627a6c0ad577b5e930782128fc7b082599 NGINX_0_8_17
+f7ec98e3caeb844c9401027b092837eee63dccab NGINX_0_8_18
+a52c99698e7f7001336116600d8bb40bdfdc59e0 NGINX_0_8_19
+0dc162a5f3e89e9d967f4aa30b2add942d895083 NGINX_0_8_20
+1dcf6adad48485e10aec666e0774634c318a9d76 NGINX_0_8_21
+c04fa65fe604240cbf3b29f4dddfc7683514fa5a NGINX_0_8_22
+2b9e388c61f18f47f2a26639c1bdf836db7ef41e NGINX_0_8_23
+40c366b3535c1c7c93baedb2ee910c1de0180e62 NGINX_0_8_24
+e19e5f54287869c93f4dc51035231772e5dca61c NGINX_0_8_25
+ab7d265273edb2eb721cb032870c23ffeda0ce60 NGINX_0_8_26
+697030d79811b68a1541986a16d39b8a9bd705c9 NGINX_0_8_27
+43e02819c5cf4e5124486eed8a338cfc2e868f18 NGINX_0_8_28
+5c576ea5dbd969cb73e9c6672723eeb11ddda2ac NGINX_0_8_29
+25255878df91eae733aead855caa35aaf8275671 NGINX_0_8_30
+2da4537168f879f528f09d0e0ce80abe68adf05e NGINX_0_8_31
+daf4847b43ff5f01a6cd52111fc8d747e2db0d72 NGINX_0_8_32
+7fa8dc2315bd08cb5329d94763ea7475d8c4d46d NGINX_0_8_33
+da3c99095432591583f4fde189906f6b860002f7 NGINX_0_8_34
+be4f34123024c582d06401144a678ed96f7963bc NGINX_0_8_35
+566e105a89f11e96c34277df2e12de7583dafc56 NGINX_0_8_36
+8246d8a2c2be92f925435369b414899f0db45492 NGINX_0_8_37
+ff463db0be31226ba236423b24e3d6d58cc78d7e NGINX_0_8_38
+7858d4f8dec4ba84e9448c5dd9c24aca7b371707 NGINX_0_8_39
+01f2313e34f1b0a22a7c7395e687ec3846b31b8a NGINX_0_8_40
+bc110f60c0de90e5a56424c85286e46321e0b884 NGINX_0_8_41
+4d3e880ce86c7593d874a5ea75b415bf52fa78ff NGINX_0_8_42
+c456a023113cfb4ce0dd5acede9b77b8277abb3c NGINX_0_8_43
+016632f0fb18481572e637dba5a82d0431b6fd80 NGINX_0_8_44
+53f5f04a64b8ff12526d81276be859efce6b9abc NGINX_0_8_45
+b6a5942a4e6a372aea8083d8d714748f02482cdd NGINX_0_8_46
+cde3626b2d0d4a784d9d33b41640672fa66ae24d NGINX_0_8_47
+09d5f308901fa05a6031c104b0ea8f8c19c1b2b1 NGINX_0_8_48
+3436cf38d59e5d8a3ac57414535a6bd7effa5936 NGINX_0_8_49
+6c96fdd2dfc3419755a0337ab50dd32123745ace NGINX_0_8_50
+be70f83b184f95fb120e072d0ab320507edc9d50 NGINX_0_8_51
+5dc296c4372ab4049b1a17259c894ad4f2a78e73 NGINX_0_8_52
+c5122335e41d714c25792bcd57a6c42396d04c35 NGINX_0_8_53
+428c6e58046a618a6edd6bc9fdc96f72c6ef6ae8 NGINX_0_9_0
+9ad199846233b1c040ba06934bfc104839917a01 NGINX_0_9_1
+3036c1836a244c5ba1ac6d43d88bd5ab685eb925 NGINX_0_9_2
+7ea1bba9a4f6fedf1df77201fa15abc0ef07639d NGINX_0_9_3
+ce857f6b74a730b814b13b64f205017721d2ff24 NGINX_0_9_4
+bb20316269e40c4aec209f67934ecac111fddeeb NGINX_0_9_5
+8214eaef3530da4aff945052fc2e99b0c097e21e NGINX_0_9_6
+b9763778e212fc338790a00c19a41fd0e68e1923 NGINX_0_9_7
+b4dcae568a2a9b258146c6dbd9c7f72fe1f3059c NGINX_1_0_0
--- a/CHANGES	Sun Sep 27 01:10:42 2009 +0400
+++ b/CHANGES	Mon Apr 25 04:22:17 2011 +0400
@@ -1,4 +1,796 @@
 
+Changes with nginx 1.0.0                                         12 Apr 2011
+
+    *) Bugfix: a cache manager might hog CPU after reload.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: an "image_filter crop" directive worked incorrectly coupled 
+       with an "image_filter rotate 180" directive.
+
+    *) Bugfix: a "satisfy any" directive disabled custom 401 error page.
+
+
+Changes with nginx 0.9.7                                         04 Apr 2011
+
+    *) Feature: now keepalive connections may be closed premature, if there 
+       are no free worker connections.
+       Thanks to Maxim Dounin.
+
+    *) Feature: the "rotate" parameter of the "image_filter" directive.
+       Thanks to Adam Bocim.
+
+    *) Bugfix: a case when a backend in "fastcgi_pass", "scgi_pass", or 
+       "uwsgi_pass" directives is given by expression and refers to a 
+       defined upstream.
+
+
+Changes with nginx 0.9.6                                         21 Mar 2011
+
+    *) Feature: the "map" directive supports regular expressions as value 
+       of the first parameter.
+
+    *) Feature: $time_iso8601 access_log variable.
+       Thanks to Michael Lustfield.
+
+
+Changes with nginx 0.9.5                                         21 Feb 2011
+
+    *) Change: now nginx uses a default listen backlog value -1 on 
+       Linux.
+       Thanks to Andrei Nigmatulin.
+
+    *) Feature: the "utf8" parameter of "geoip_country" and "geoip_city" 
+       directives.
+       Thanks to Denis F. Latypoff.
+
+    *) Bugfix: in a default "proxy_redirect" directive if "proxy_pass" 
+       directive has no URI part.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: an "error_page" directive did not work with nonstandard 
+       error codes; the bug had appeared in 0.8.53.
+       Thanks to Maxim Dounin.
+
+
+Changes with nginx 0.9.4                                         21 Jan 2011
+
+    *) Feature: the "server_name" directive supports the $hostname variable.
+
+    *) Feature: 494 code for "Request Header Too Large" error.
+
+
+Changes with nginx 0.9.3                                         13 Dec 2010
+
+    *) Bugfix: if there was a single server for given IPv6 address:port 
+       pair, then captures in regular expressions in a "server_name" 
+       directive did not work.
+
+    *) Bugfix: nginx could not be built on Solaris; the bug had appeared in 
+       0.9.0.
+
+
+Changes with nginx 0.9.2                                         06 Dec 2010
+
+    *) Feature: the "If-Unmodified-Since" client request header line 
+       support.
+
+    *) Workaround: fallback to accept() syscall if accept4() was not 
+       implemented; the issue had appeared in 0.9.0.
+
+    *) Bugfix: nginx could not be built on Cygwin; the bug had appeared in 
+       0.9.0.
+
+    *) Bugfix: for OpenSSL vulnerability CVE-2010-4180.
+       Thanks to Maxim Dounin.
+
+
+Changes with nginx 0.9.1                                         30 Nov 2010
+
+    *) Bugfix: "return CODE message" directives did not work; the bug had 
+       appeared in 0.9.0.
+
+
+Changes with nginx 0.9.0                                         29 Nov 2010
+
+    *) Feature: the "keepalive_disable" directive.
+
+    *) Feature: the "map" directive supports variables as value of a 
+       defined variable.
+
+    *) Feature: the "map" directive supports empty strings as value of the 
+       first parameter.
+
+    *) Feature: the "map" directive supports expressions as the first 
+       parameter.
+
+    *) Feature: nginx(8) manual page.
+       Thanks to Sergey Osokin.
+
+    *) Feature: Linux accept4() support.
+       Thanks to Simon Liu.
+
+    *) Workaround: elimination of Linux linker warning about "sys_errlist" 
+       and "sys_nerr"; the warning had appeared in 0.8.35.
+
+    *) Bugfix: a segmentation fault might occur in a worker process, if the 
+       "auth_basic" directive was used.
+       Thanks to Michail Laletin.
+
+    *) Bugfix: compatibility with ngx_http_eval_module; the bug had 
+       appeared in 0.8.42.
+
+
+Changes with nginx 0.8.53                                        18 Oct 2010
+
+    *) Feature: now the "error_page" directive allows to change a status 
+       code in a redirect.
+
+    *) Feature: the "gzip_disable" directive supports special "degradation" 
+       mask.
+
+    *) Bugfix: a socket leak might occurred if file AIO was used.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: if the first server had no "listen" directive and there was 
+       no explicit default server, then a next server with a "listen" 
+       directive became the default server; the bug had appeared in 0.8.21.
+
+
+Changes with nginx 0.8.52                                        28 Sep 2010
+
+    *) Bugfix: nginx used SSL mode for a listen socket if any listen option 
+       was set; the bug had appeared in 0.8.51.
+
+
+Changes with nginx 0.8.51                                        27 Sep 2010
+
+    *) Change: the "secure_link_expires" directive has been canceled.
+
+    *) Change: a logging level of resolver errors has been lowered from 
+       "alert" to "error".
+
+    *) Feature: now a listen socket "ssl" parameter may be set several 
+       times.
+
+
+Changes with nginx 0.8.50                                        02 Sep 2010
+
+    *) Feature: the "secure_link", "secure_link_md5", and 
+       "secure_link_expires" directives of the ngx_http_secure_link_module.
+
+    *) Feature: the -q switch.
+       Thanks to Gena Makhomed.
+
+    *) Bugfix: worker processes may got caught in an endless loop during 
+       reconfiguration, if a caching was used; the bug had appeared in 
+       0.8.48.
+
+    *) Bugfix: in the "gzip_disable" directive.
+       Thanks to Derrick Petzold.
+
+    *) Bugfix: nginx/Windows could not send stop, quit, reopen, and reload 
+       signals to a process run in other session.
+
+
+Changes with nginx 0.8.49                                        09 Aug 2010
+
+    *) Feature: the "image_filter_jpeg_quality" directive supports 
+       variables.
+
+    *) Bugfix: a segmentation fault might occur in a worker process, if the 
+       $geoip_region_name variables was used; the bug had appeared in 
+       0.8.48.
+
+    *) Bugfix: errors intercepted by error_page were cached only for next 
+       request; the bug had appeared in 0.8.48.
+
+
+Changes with nginx 0.8.48                                        03 Aug 2010
+
+    *) Change: now the "server_name" directive default value is an empty 
+       name "".
+       Thanks to Gena Makhomed.
+
+    *) Change: now the "server_name_in_redirect" directive default value is 
+       "off".
+
+    *) Feature: the $geoip_dma_code, $geoip_area_code, and 
+       $geoip_region_name variables.
+       Thanks to Christine McGonagle.
+
+    *) Bugfix: the "proxy_pass", "fastcgi_pass", "uwsgi_pass", and 
+       "scgi_pass" directives were not inherited inside "limit_except" 
+       blocks.
+
+    *) Bugfix: the "proxy_cache_min_uses", "fastcgi_cache_min_uses" 
+       "uwsgi_cache_min_uses", and "scgi_cache_min_uses" directives did not 
+       work; the bug had appeared in 0.8.46.
+
+    *) Bugfix: the "fastcgi_split_path_info" directive used incorrectly 
+       captures, if only parts of an URI were captured.
+       Thanks to Yuriy Taraday and Frank Enderle.
+
+    *) Bugfix: the "rewrite" directive did not escape a ";" character 
+       during copying from URI to query string.
+       Thanks to Daisuke Murase.
+
+    *) Bugfix: the ngx_http_image_filter_module closed a connection, if an 
+       image was larger than "image_filter_buffer" size.
+
+
+Changes with nginx 0.8.47                                        28 Jul 2010
+
+    *) Bugfix: $request_time variable had invalid values for subrequests.
+
+    *) Bugfix: errors intercepted by error_page could not be cached.
+
+    *) Bugfix: a cache manager process may got caught in an endless loop, 
+       if max_size parameter was used; the bug had appeared in 0.8.46.
+
+
+Changes with nginx 0.8.46                                        19 Jul 2010
+
+    *) Change: now the "proxy_no_cache", "fastcgi_no_cache", 
+       "uwsgi_no_cache", and "scgi_no_cache" directives affect on a cached 
+       response saving only.
+
+    *) Feature: the "proxy_cache_bypass", "fastcgi_cache_bypass", 
+       "uwsgi_cache_bypass", and "scgi_cache_bypass" directives.
+
+    *) Bugfix: nginx did not free memory in cache keys zones if there was 
+       an error during working with backend: the memory was freed only 
+       after inactivity time or on memory low condition.
+
+
+Changes with nginx 0.8.45                                        13 Jul 2010
+
+    *) Feature: ngx_http_xslt_filter improvements.
+       Thanks to Laurence Rowe.
+
+    *) Bugfix: SSI response might be truncated after include with 
+       wait="yes"; the bug had appeared in 0.7.25.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: the "listen" directive did not support the "setfib=0" 
+       parameter.
+
+
+Changes with nginx 0.8.44                                        05 Jul 2010
+
+    *) Change: now nginx does not cache by default backend responses, if 
+       they have a "Set-Cookie" header line.
+
+    *) Feature: the "listen" directive supports the "setfib" parameter.
+       Thanks to Andrew Filonov.
+
+    *) Bugfix: the "sub_filter" directive might change character case on 
+       partial match.
+
+    *) Bugfix: compatibility with HP/UX.
+
+    *) Bugfix: compatibility with AIX xlC_r compiler.
+
+    *) Bugfix: nginx treated large SSLv2 packets as plain requests.
+       Thanks to Miroslaw Jaworski.
+
+
+Changes with nginx 0.8.43                                        30 Jun 2010
+
+    *) Feature: large geo ranges base loading speed-up.
+
+    *) Bugfix: an error_page redirection to "location /zero {return 204;}" 
+       without changing status code kept the error body; the bug had 
+       appeared in 0.8.42.
+
+    *) Bugfix: nginx might close IPv6 listen socket during 
+       reconfiguration.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: the $uid_set variable may be used at any request processing 
+       stage.
+
+
+Changes with nginx 0.8.42                                        21 Jun 2010
+
+    *) Change: now nginx tests locations given by regular expressions, if 
+       request was matched exactly by a location given by a prefix string. 
+       The previous behavior has been introduced in 0.7.1.
+
+    *) Feature: the ngx_http_scgi_module.
+       Thanks to Manlio Perillo.
+
+    *) Feature: a text answer may be added to a "return" directive.
+
+
+Changes with nginx 0.8.41                                        15 Jun 2010
+
+    *) Security: nginx/Windows worker might be terminated abnormally if a 
+       requested file name has invalid UTF-8 encoding.
+
+    *) Change: now nginx allows to use spaces in a request line.
+
+    *) Bugfix: the "proxy_redirect" directive changed incorrectly a backend 
+       "Refresh" response header line.
+       Thanks to Andrey Andreew and Max Sogin.
+
+    *) Bugfix: nginx did not support path without host name in 
+       "Destination" request header line.
+
+
+Changes with nginx 0.8.40                                        07 Jun 2010
+
+    *) Security: now nginx/Windows ignores default file stream name.
+       Thanks to Jose Antonio Vazquez Gonzalez.
+
+    *) Feature: the ngx_http_uwsgi_module.
+       Thanks to Roberto De Ioris.
+
+    *) Feature: a "fastcgi_param" directive with value starting with 
+       "HTTP_" overrides a client request header line.
+
+    *) Bugfix: the "If-Modified-Since", "If-Range", etc. client request 
+       header lines were passed to FastCGI-server while caching.
+
+    *) Bugfix: listen unix domain socket could not be changed during 
+       reconfiguration.
+       Thanks to Maxim Dounin.
+
+
+Changes with nginx 0.8.39                                        31 May 2010
+
+    *) Bugfix: an inherited "alias" directive worked incorrectly in 
+       inclusive location.
+
+    *) Bugfix: in "alias" with variables and "try_files" directives 
+       combination.
+
+    *) Bugfix: listen unix domain and IPv6 sockets did not inherit while 
+       online upgrade.
+       Thanks to Maxim Dounin.
+
+
+Changes with nginx 0.8.38                                        24 May 2010
+
+    *) Feature: the "proxy_no_cache" and "fastcgi_no_cache" directives.
+
+    *) Feature: now the "rewrite" directive does a redirect automatically 
+       if the $scheme variable is used.
+       Thanks to Piotr Sikora.
+
+    *) Bugfix: now "limit_req" delay directive conforms to the described 
+       algorithm.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: the $uid_got variable might not be used in the SSI and perl 
+       modules.
+
+
+Changes with nginx 0.8.37                                        17 May 2010
+
+    *) Feature: the ngx_http_split_clients_module.
+
+    *) Feature: the "map" directive supports keys more than 255 characters.
+
+    *) Bugfix: nginx ignored the "private" and "no-store" values in the 
+       "Cache-Control" backend response header line.
+
+    *) Bugfix: a "stub" parameter of an "include" SSI directive was not 
+       used, if empty response has 200 status code.
+
+    *) Bugfix: if a proxied or FastCGI request was internally redirected to 
+       another proxied or FastCGI location, then a segmentation fault might 
+       occur in a worker process; the bug had appeared in 0.8.33.
+       Thanks to Yichun Zhang.
+
+    *) Bugfix: IMAP connections may hang until they timed out while talking 
+       to Zimbra server.
+       Thanks to Alan Batie.
+
+
+Changes with nginx 0.8.36                                        22 Apr 2010
+
+    *) Bugfix: the ngx_http_dav_module handled incorrectly the DELETE, 
+       COPY, and MOVE methods for symlinks.
+
+    *) Bugfix: values of the $query_string, $arg_..., etc. variables cached 
+       in main request were used by the SSI module in subrequests.
+
+    *) Bugfix: a variable value was repeatedly encoded after each an "echo" 
+       SSI-command output; the bug had appeared in 0.6.14.
+
+    *) Bugfix: a worker process hung if a FIFO file was requested.
+       Thanks to Vicente Aguilar and Maxim Dounin.
+
+    *) Bugfix: OpenSSL-1.0.0 compatibility on 64-bit Linux.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: nginx could not be built --without-http-cache; the bug had 
+       appeared in 0.8.35.
+
+
+Changes with nginx 0.8.35                                        01 Apr 2010
+
+    *) Change: now the charset filter runs before the SSI filter.
+
+    *) Feature: the "chunked_transfer_encoding" directive.
+
+    *) Bugfix: an "&" character was not escaped when it was copied in 
+       arguments part in a rewrite rule.
+
+    *) Bugfix: nginx might be terminated abnormally while a signal 
+       processing or if the directive "timer_resolution" was used on 
+       platforms which do not support kqueue or eventport notification 
+       methods.
+       Thanks to George Xie and Maxim Dounin.
+
+    *) Bugfix: if temporary files and permanent storage area resided at 
+       different file systems, then permanent file modification times were 
+       incorrect.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: ngx_http_memcached_module might issue the error message 
+       "memcached sent invalid trailer".
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: nginx could not built zlib-1.2.4 library using the library 
+       sources.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: a segmentation fault occurred in a worker process, if there 
+       was large stderr output before FastCGI response; the bug had 
+       appeared in 0.8.34.
+       Thanks to Maxim Dounin.
+
+
+Changes with nginx 0.8.34                                        03 Mar 2010
+
+    *) Bugfix: nginx did not support all ciphers and digests used in client 
+       certificates.
+       Thanks to Innocenty Enikeew.
+
+    *) Bugfix: nginx cached incorrectly FastCGI responses if there was 
+       large stderr output before response.
+
+    *) Bugfix: nginx did not support HTTPS referrers.
+
+    *) Bugfix: nginx/Windows might not find file if path in configuration 
+       was given in other character case; the bug had appeared in 0.8.33.
+
+    *) Bugfix: the $date_local variable has an incorrect value, if the "%s" 
+       format was used.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: if ssl_session_cache was not set or was set to "none", then 
+       during client certificate verify the error "session id context 
+       uninitialized" might occur; the bug had appeared in 0.7.1.
+
+    *) Bugfix: a geo range returned default value if the range included two 
+       or more /16 networks and did not begin at /16 network boundary.
+
+    *) Bugfix: a block used in a "stub" parameter of an "include" SSI 
+       directive was output with "text/plain" MIME type.
+
+    *) Bugfix: $r->sleep() did not work; the bug had appeared in 0.8.11.
+
+
+Changes with nginx 0.8.33                                        01 Feb 2010
+
+    *) Security: now nginx/Windows ignores trailing spaces in URI.
+       Thanks to Dan Crowley, Core Security Technologies.
+
+    *) Security: now nginx/Windows ignores short files names.
+       Thanks to Dan Crowley, Core Security Technologies.
+
+    *) Change: now keepalive connections after POST requests are not 
+       disabled for MSIE 7.0+.
+       Thanks to Adam Lounds.
+
+    *) Workaround: now keepalive connections are disabled for Safari.
+       Thanks to Joshua Sierles.
+
+    *) Bugfix: if a proxied or FastCGI request was internally redirected to 
+       another proxied or FastCGI location, then $upstream_response_time 
+       variable may have abnormally large value; the bug had appeared in 
+       0.8.7.
+
+    *) Bugfix: a segmentation fault might occur in a worker process, while 
+       discarding a request body; the bug had appeared in 0.8.11.
+
+
+Changes with nginx 0.8.32                                        11 Jan 2010
+
+    *) Bugfix: UTF-8 encoding usage in the ngx_http_autoindex_module.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: regular expression named captures worked for two names only. 
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: now the "localhost" name is used in the "Host" request 
+       header line, if an unix domain socket is defined in the "auth_http" 
+       directive.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: nginx did not support chunked transfer encoding for 201 
+       responses.
+       Thanks to Julian Reich.
+
+    *) Bugfix: if the "expires modified" set date in the past, then a 
+       negative number was set in the "Cache-Control" response header line. 
+       Thanks to Alex Kapranoff.
+
+
+Changes with nginx 0.8.31                                        23 Dec 2009
+
+    *) Feature: now the "error_page" directive may redirect the 301 and 302 
+       responses.
+
+    *) Feature: the $geoip_city_continent_code, $geoip_latitude, and 
+       $geoip_longitude variables.
+       Thanks to Arvind Sundararajan.
+
+    *) Feature: now the ngx_http_image_filter_module deletes always EXIF 
+       and other application specific data if the data consume more than 5% 
+       of a JPEG file.
+
+    *) Bugfix: nginx closed a connection if a cached response had an empty 
+       body.
+       Thanks to Piotr Sikora.
+
+    *) Bugfix: nginx might not be built by gcc 4.x if the -O2 or higher 
+       optimization option was used.
+       Thanks to Maxim Dounin and Denis F. Latypoff.
+
+    *) Bugfix: regular expressions in location were always tested in 
+       case-sensitive mode; the bug had appeared in 0.8.25.
+
+    *) Bugfix: nginx cached a 304 response if there was the "If-None-Match" 
+       header line in a proxied request.
+       Thanks to Tim Dettrick and David Kostal.
+
+    *) Bugfix: nginx/Windows tried to delete a temporary file twice if the 
+       file should replace an already existent file.
+
+
+Changes with nginx 0.8.30                                        15 Dec 2009
+
+    *) Change: now the default buffer size of the 
+       "large_client_header_buffers" directive is 8K.
+       Thanks to Andrew Cholakian.
+
+    *) Feature: the conf/fastcgi.conf for simple FastCGI configurations.
+
+    *) Bugfix: nginx/Windows tried to rename a temporary file twice if the 
+       file should replace an already existent file.
+
+    *) Bugfix: of "double free or corruption" error issued if host could 
+       not be resolved; the bug had appeared in 0.8.22.
+       Thanks to Konstantin Svist.
+
+    *) Bugfix: in libatomic usage on some platforms.
+       Thanks to W-Mark Kubacki.
+
+
+Changes with nginx 0.8.29                                        30 Nov 2009
+
+    *) Change: now the "009" status code is written to an access log for 
+       proxied HTTP/0.9 responses.
+
+    *) Feature: the "addition_types", "charset_types", "gzip_types", 
+       "ssi_types", "sub_filter_types", and "xslt_types" directives support 
+       an "*" parameter.
+
+    *) Feature: GCC 4.1+ built-in atomic operations usage.
+       Thanks to W-Mark Kubacki.
+
+    *) Feature: the --with-libatomic[=DIR] option in the configure.
+       Thanks to W-Mark Kubacki.
+
+    *) Bugfix: listen unix domain socket had limited access rights.
+
+    *) Bugfix: cached HTTP/0.9 responses were handled incorrectly.
+
+    *) Bugfix: regular expression named captures given by "?P<...>" did not 
+       work in a "server_name" directive.
+       Thanks to Maxim Dounin.
+
+
+Changes with nginx 0.8.28                                        23 Nov 2009
+
+    *) Bugfix: nginx could not be built with the --without-pcre parameter; 
+       the bug had appeared in 0.8.25.
+
+
+Changes with nginx 0.8.27                                        17 Nov 2009
+
+    *) Bugfix: regular expressions did not work in nginx/Windows; the bug 
+       had appeared in 0.8.25.
+
+
+Changes with nginx 0.8.26                                        16 Nov 2009
+
+    *) Bugfix: in captures usage in "rewrite" directive; the bug had 
+       appeared in 0.8.25.
+
+    *) Bugfix: nginx could not be built without the --with-debug option; 
+       the bug had appeared in 0.8.25.
+
+
+Changes with nginx 0.8.25                                        16 Nov 2009
+
+    *) Change: now no message is written in an error log if a variable is 
+       not found by $r->variable() method.
+
+    *) Feature: the ngx_http_degradation_module.
+
+    *) Feature: regular expression named captures.
+
+    *) Feature: now URI part is not required a "proxy_pass" directive if 
+       variables are used.
+
+    *) Feature: now the "msie_padding" directive works for Chrome too.
+
+    *) Bugfix: a segmentation fault occurred in a worker process on low 
+       memory condition; the bug had appeared in 0.8.18.
+
+    *) Bugfix: nginx sent gzipped responses to clients those do not support 
+       gzip, if "gzip_static on" and "gzip_vary off"; the bug had appeared 
+       in 0.8.16.
+
+
+Changes with nginx 0.8.24                                        11 Nov 2009
+
+    *) Bugfix: nginx always added "Content-Encoding: gzip" response header 
+       line in 304 responses sent by ngx_http_gzip_static_module.
+
+    *) Bugfix: nginx could not be built without the --with-debug option; 
+       the bug had appeared in 0.8.23.
+
+    *) Bugfix: the "unix:" parameter of the "set_real_ip_from" directive 
+       inherited incorrectly from previous level.
+
+    *) Bugfix: in resolving empty name.
+
+
+Changes with nginx 0.8.23                                        11 Nov 2009
+
+    *) Security: now SSL/TLS renegotiation is disabled.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: listen unix domain socket did not inherit while online 
+       upgrade.
+
+    *) Bugfix: the "unix:" parameter of the "set_real_ip_from" directive 
+       did not without yet another directive with any IP address.
+
+    *) Bugfix: segmentation fault and infinite looping in resolver.
+
+    *) Bugfix: in resolver.
+       Thanks to Artem Bokhan.
+
+
+Changes with nginx 0.8.22                                        03 Nov 2009
+
+    *) Feature: the "proxy_bind", "fastcgi_bind", and "memcached_bind" 
+       directives.
+
+    *) Feature: the "access" and the "deny" directives support IPv6.
+
+    *) Feature: the "set_real_ip_from" directive supports IPv6 addresses in 
+       request headers.
+
+    *) Feature: the "unix:" parameter of the "set_real_ip_from" directive.
+
+    *) Bugfix: nginx did not delete unix domain socket after configuration 
+       testing.
+
+    *) Bugfix: nginx deleted unix domain socket while online upgrade.
+
+    *) Bugfix: the "!-x" operator did not work.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: a segmentation fault might occur in a worker process, if 
+       limit_rate was used in HTTPS server.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: a segmentation fault might occur in a worker process while 
+       $limit_rate logging.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: a segmentation fault might occur in a worker process, if 
+       there was no "listen" directive in "server" block; the bug had 
+       appeared in 0.8.21.
+
+
+Changes with nginx 0.8.21                                        26 Oct 2009
+
+    *) Feature: now the "-V" switch shows TLS SNI support.
+
+    *) Feature: the "listen" directive of the HTTP module supports unix 
+       domain sockets.
+       Thanks to Hongli Lai.
+
+    *) Feature: the "default_server" parameter of the "listen" directive.
+
+    *) Feature: now a "default" parameter is not required to set listen 
+       socket options.
+
+    *) Bugfix: nginx did not support dates in 2038 year on 32-bit platforms;
+
+    *) Bugfix: socket leak; the bug had appeared in 0.8.11.
+
+
+Changes with nginx 0.8.20                                        14 Oct 2009
+
+    *) Change: now default SSL ciphers are "HIGH:!ADH:!MD5".
+
+    *) Bugfix: the ngx_http_autoindex_module did not show the trailing 
+       slash in links to a directory; the bug had appeared in 0.7.15.
+
+    *) Bugfix: nginx did not close a log file set by the --error-log-path 
+       configuration option; the bug had appeared in 0.7.53.
+
+    *) Bugfix: nginx did not treat a comma as separator in the 
+       "Cache-Control" backend response header line.
+
+    *) Bugfix: nginx/Windows might not create temporary file, a cache file, 
+       or "proxy/fastcgi_store"d file if a worker had no enough access 
+       rights for top level directories.
+
+    *) Bugfix: the "Set-Cookie" and "P3P" FastCGI response header lines 
+       were not hidden while caching if no "fastcgi_hide_header" directives 
+       were used with any parameters.
+
+    *) Bugfix: nginx counted incorrectly disk cache size.
+
+
+Changes with nginx 0.8.19                                        06 Oct 2009
+
+    *) Change: now SSLv2 protocol is disabled by default.
+
+    *) Change: now default SSL ciphers are "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM".
+
+    *) Bugfix: a "limit_req" directive did not work; the bug had appeared 
+       in 0.8.18.
+
+
+Changes with nginx 0.8.18                                        06 Oct 2009
+
+    *) Feature: the "read_ahead" directive.
+
+    *) Feature: now several "perl_modules" directives may be used.
+
+    *) Feature: the "limit_req_log_level" and "limit_conn_log_level" 
+       directives.
+
+    *) Bugfix: now "limit_req" directive conforms to the leaky bucket 
+       algorithm.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: nginx did not work on Linux/sparc.
+       Thanks to Marcus Ramberg.
+
+    *) Bugfix: nginx sent '\0' in a "Location" response header line on 
+       MKCOL request.
+       Thanks to Xie Zhenye.
+
+    *) Bugfix: zero status code was logged instead of 499 status code; the 
+       bug had appeared in 0.8.11.
+
+    *) Bugfix: socket leak; the bug had appeared in 0.8.11.
+
+
+Changes with nginx 0.8.17                                        28 Sep 2009
+
+    *) Security: now "/../" are disabled in "Destination" request header 
+       line.
+
+    *) Change: now $host variable value is always low case.
+
+    *) Feature: the $ssl_session_id variable.
+
+    *) Bugfix: socket leak; the bug had appeared in 0.8.11.
+
+
 Changes with nginx 0.8.16                                        22 Sep 2009
 
     *) Feature: the "image_filter_transparency" directive.
@@ -533,7 +1325,7 @@
 
     *) Bugfix: the "try_files" directive might test incorrectly directories.
 
-    *) Bugfix: if there is the single server for given address:port pair, 
+    *) Bugfix: if there was a single server for given address:port pair, 
        then captures in regular expressions in a "server_name" directive 
        did not work.
 
@@ -887,7 +1679,7 @@
     *) Bugfix: the "http_503" parameter of the "proxy_next_upstream" or 
        "fastcgi_next_upstream" directives did not work.
 
-    *) Bugfix: nginx might send a "Transfer-Encoding: chunked" heaer line 
+    *) Bugfix: nginx might send a "Transfer-Encoding: chunked" header line 
        for HEAD requests.
 
     *) Bugfix: now accept threshold depends on worker_connections.
@@ -4296,7 +5088,7 @@
 Changes with nginx 0.1.10                                        26 Nov 2004
 
     *) Bugfix: if the request without arguments contains "//", "/./", 
-       "/../" or "%XX" then the lost character in the request line was 
+       "/../" or "%XX" then the last character in the request line was 
        lost; the bug had appeared in 0.1.9.
 
     *) Bugfix: the fix in 0.1.9 for the files bigger than 2G on Linux did 
--- a/CHANGES.ru	Sun Sep 27 01:10:42 2009 +0400
+++ b/CHANGES.ru	Mon Apr 25 04:22:17 2011 +0400
@@ -1,4 +1,809 @@
 
+Изменения в nginx 1.0.0                                           12.04.2011
+
+    *) Исправление: cache manager мог нагружать процессор после 
+       переконфигурации.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: директива "image_filter crop" неправильно работала в 
+       сочетании с "image_filter rotate 180".
+
+    *) Исправление: директива "satisfy any" запрещала выдачу 
+       пользовательской страницы для 401 кода.
+
+
+Изменения в nginx 0.9.7                                           04.04.2011
+
+    *) Добавление: теперь соединения в состоянии keepalive могут быть 
+       закрыты преждевременно, если у воркера нет свободных соединений.
+       Спасибо Максиму Дунину.
+
+    *) Добавление: параметр rotate директивы image_filter.
+       Спасибо Adam Bocim.
+
+    *) Исправление: ситуации, когда бэкенд в директивах fastcgi_pass, 
+       scgi_pass или uwsgi_pass задан выражением и ссылается на описанный 
+       upstream.
+
+
+Изменения в nginx 0.9.6                                           21.03.2011
+
+    *) Добавление: директива map поддерживает регулярные выражения в 
+       качестве значения первого параметра.
+
+    *) Добавление: переменная $time_iso8601 для access_log.
+       Спасибо Michael Lustfield.
+
+
+Изменения в nginx 0.9.5                                           21.02.2011
+
+    *) Изменение: теперь по умолчанию nginx использует значение -1 для 
+       listen backlog на Linux.
+       Спасибо Андрею Нигматулину.
+
+    *) Добавление: параметр utf8 в директивах geoip_country и 
+       geoip_city.
+       Спасибо Денису Латыпову.
+
+    *) Исправление: исправление в умолчательной директиве proxy_redirect, 
+       если в директиве proxy_pass не был описан URI.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: директива error_page не работала с нестандартными 
+       кодами ошибок; ошибка появилась в 0.8.53.
+       Спасибо Максиму Дунину.
+
+
+Изменения в nginx 0.9.4                                           21.01.2011
+
+    *) Добавление: директива server_name поддерживает переменную $hostname.
+
+    *) Добавление: 494 код для ошибки "Request Header Too Large".
+
+
+Изменения в nginx 0.9.3                                           13.12.2010
+
+    *) Исправление: если для пары IPv6-адрес:порт описан только один 
+       сервер, то выделения в регулярных выражениях в директиве server_name 
+       не работали.
+
+    *) Исправление: nginx не собирался под Solaris; ошибка появилась в 
+       0.9.0.
+
+
+Изменения в nginx 0.9.2                                           06.12.2010
+
+    *) Добавление: поддержка строки "If-Unmodified-Since" в заголовке 
+       запросе клиента.
+
+    *) Изменение: использование accept(), если accept4() не реализован; 
+       ошибка появилась в 0.9.0.
+
+    *) Исправление: nginx не собирался под Cygwin; ошибка появилась в 0.9.0.
+
+    *) Исправление: уязвимости в OpenSSL CVE-2010-4180.
+       Спасибо Максиму Дунину.
+
+
+Изменения в nginx 0.9.1                                           30.11.2010
+
+    *) Исправление: директивы вида "return CODE message" не работали; 
+       ошибка появилась в 0.9.0.
+
+
+Изменения в nginx 0.9.0                                           29.11.2010
+
+    *) Добавление: директива keepalive_disable.
+
+    *) Добавление: директива map поддерживает переменные в качестве 
+       значения определяемой переменной.
+
+    *) Добавление: директива map поддерживает пустые строки в качестве 
+       значения первого параметра.
+
+    *) Добавление: директива map поддерживает выражения в первом параметре.
+
+    *) Добавление: страница руководства nginx(8).
+       Спасибо Сергею Осокину.
+
+    *) Добавление: поддержка accept4() в Linux.
+       Спасибо Simon Liu.
+
+    *) Изменение: устранение предупреждения линкера о "sys_errlist" и 
+       "sys_nerr" под Linux; предупреждение появилось в 0.8.35.
+
+    *) Исправление: при использовании директивы auth_basic в рабочем 
+       процессе мог произойти segmentation fault.
+       Спасибо Михаилу Лалетину.
+
+    *) Исправление: совместимость с модулем ngx_http_eval_module; ошибка 
+       появилась в 0.8.42.
+
+
+Изменения в nginx 0.8.53                                          18.10.2010
+
+    *) Добавление: теперь директива error_page позволяет менять код статуса 
+       у редиректа.
+
+    *) Добавление: директива gzip_disable поддерживает специальную маску 
+       degradation.
+
+    *) Исправление: при использовании файлового AIO могла происходить 
+       утечка сокетов.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: если в первом сервере не была описана директива listen 
+       и нигде явно не описан сервер по умолчанию, то сервером по умолчанию 
+       становился следующий сервер с директивой listen; ошибка появилась в 
+       0.8.21.
+
+
+Изменения в nginx 0.8.52                                          28.09.2010
+
+    *) Исправление: nginx использовал режим SSL для listen сокета, если для 
+       него был установлен любой listen-параметр; ошибка появилась в 0.8.51.
+
+
+Изменения в nginx 0.8.51                                          27.09.2010
+
+    *) Изменение: директива secure_link_expires упразднена.
+
+    *) Изменение: уровень логгирования ошибок resolver'а понижен с уровня 
+       alert на error.
+
+    *) Добавление: теперь параметр "ssl" listen-сокета можно устанавливать 
+       несколько раз.
+
+
+Изменения в nginx 0.8.50                                          02.09.2010
+
+    *) Добавление: директивы secure_link, secure_link_md5 и 
+       secure_link_expires модуля ngx_http_secure_link_module.
+
+    *) Добавление: ключ -q.
+       Спасибо Геннадию Махомеду.
+
+    *) Исправление: при использовании кэширования рабочие процессы и могли 
+       зациклиться во время переконфигурации; ошибка появилась в 0.8.48.
+
+    *) Исправление: в директиве gzip_disable.
+       Спасибо Derrick Petzold.
+
+    *) Исправление: nginx/Windows не мог посылать сигналы stop, quit, 
+       reopen, reload процессу, запущенному в другой сессии.
+
+
+Изменения в nginx 0.8.49                                          09.08.2010
+
+    *) Добавление: директива image_filter_jpeg_quality поддерживает 
+       переменные.
+
+    *) Исправление: при использовании переменной $geoip_region_name в 
+       рабочем процессе мог произойти segmentation fault; ошибка появилась 
+       в 0.8.48.
+
+    *) Исправление: ошибки, перехваченные error_page, кэшировались только 
+       до следующего запроса; ошибка появилась в 0.8.48.
+
+
+Изменения в nginx 0.8.48                                          03.08.2010
+
+    *) Изменение: теперь по умолчанию директива server_name имеет значение 
+       пустое имя "".
+       Спасибо Геннадию Махомеду.
+
+    *) Изменение: теперь по умолчанию директива server_name_in_redirect 
+       имеет значение off.
+
+    *) Добавление: переменные $geoip_dma_code, $geoip_area_code и 
+       $geoip_region_name.
+       Спасибо Christine McGonagle.
+
+    *) Исправление: директивы proxy_pass, fastcgi_pass, uwsgi_pass и 
+       scgi_pass не наследовались в блоки limit_except.
+
+    *) Исправление: директивы proxy_cache_min_uses, fastcgi_cache_min_uses 
+       uwsgi_cache_min_uses и scgi_cache_min_uses не работали; ошибка 
+       появилась в 0.8.46.
+
+    *) Исправление: директива fastcgi_split_path_info неверно использовала 
+       выделения, если в выделения попадала только часть URI.
+       Спасибо Юрию Тарадаю и Frank Enderle.
+
+    *) Исправление: директива rewrite не экранировала символ ";" при 
+       копировании из URI в аргументы. 
+       Спасибо Daisuke Murase.
+
+    *) Исправление: модуль ngx_http_image_filter_module закрывал 
+       соединение, если изображение было больше размера image_filter_buffer.
+
+
+Изменения в nginx 0.8.47                                          28.07.2010
+
+    *) Исправление: переменная $request_time имела неверные значения для 
+       подзапросов.
+
+    *) Исправление: ошибки, перехваченные error_page, не кэшировались.
+
+    *) Исправление: если использовался параметр max_size, то cache manager 
+       мог зациклиться; ошибка появилась в 0.8.46.
+
+
+Изменения в nginx 0.8.46                                          19.07.2010
+
+    *) Изменение: директивы proxy_no_cache, fastcgi_no_cache, 
+       uwsgi_no_cache и scgi_no_cache теперь влияют только на сохранение 
+       закэшированного ответа.
+
+    *) Добавление: директивы proxy_cache_bypass, fastcgi_cache_bypass, 
+       uwsgi_cache_bypass и scgi_cache_bypass.
+
+    *) Исправление: nginx не освобождал память в keys_zone кэшей в случае 
+       ошибки работы с бэкендом: память освобождалась только по истечении 
+       времени неактивности или при недостатке памяти.
+
+
+Изменения в nginx 0.8.45                                          13.07.2010
+
+    *) Добавление: улучшения в модуле ngx_http_xslt_filter.
+       Спасибо Laurence Rowe.
+
+    *) Исправление: ответ SSI модуля мог передаваться не полностью после 
+       команды include с параметром wait="yes"; ошибка появилась в 0.7.25. 
+       Спасибо Максиму Дунину.
+
+    *) Исправление: директива listen не поддерживала параметр setfib=0.
+
+
+Изменения в nginx 0.8.44                                          05.07.2010
+
+    *) Изменение: теперь nginx по умолчанию не кэширует ответы бэкендов, в 
+       заголовке которых есть строка "Set-Cookie".
+
+    *) Добавление: директива listen поддерживает параметр setfib.
+       Спасибо Андрею Филонову.
+
+    *) Исправление: директива sub_filter могла изменять регистр букв при 
+       частичном совпадении.
+
+    *) Исправление: совместимость с HP/UX.
+
+    *) Исправление: совместимость с компилятором AIX xlC_r.
+
+    *) Исправление: nginx считал большие пакеты SSLv2 как обычные текстовые 
+       запросы.
+       Спасибо Miroslaw Jaworski.
+
+
+Изменения в nginx 0.8.43                                          30.06.2010
+
+    *) Добавление: ускорение загрузки больших баз geo-диапазонов.
+
+    *) Исправление: перенаправление ошибки в "location /zero {return 204;}" 
+       без изменения кода ответа оставляло тело ошибки; ошибка появилась в 
+       0.8.42.
+
+    *) Исправление: nginx мог закрывать IPv6 listen сокет во время 
+       переконфигурации.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: переменную $uid_set можно использовать на любой стадии 
+       обработки запроса.
+
+
+Изменения в nginx 0.8.42                                          21.06.2010
+
+    *) Изменение: теперь nginx проверяет location'ы, заданные регулярными 
+       выражениями, если запрос полностью совпал с location'ом, заданным 
+       строкой префикса. Предыдущее поведение появилось в 0.7.1.
+
+    *) Добавление: модуль ngx_http_scgi_module.
+       Спасибо Manlio Perillo.
+
+    *) Добавление: в директиве return можно добавлять текст ответа.
+
+
+Изменения в nginx 0.8.41                                          15.06.2010
+
+    *) Безопасность: рабочий процесс nginx/Windows мог завершаться аварийно 
+       при запросе файла с неверной кодировкой UTF-8.
+
+    *) Изменение: теперь nginx разрешает использовать пробелы в строке 
+       запроса.
+
+    *) Исправление: директива proxy_redirect неправильно изменяла строку 
+       "Refresh" в заголовке ответа бэкенда.
+       Спасибо Андрею Андрееву и Максиму Согину.
+
+    *) Исправление: nginx не поддерживал путь без имени хоста в строке 
+       "Destination" в заголовке запроса.
+
+
+Изменения в nginx 0.8.40                                          07.06.2010
+
+    *) Безопасность: теперь nginx/Windows игнорирует имя потока файла по 
+       умолчанию.
+       Спасибо Jose Antonio Vazquez Gonzalez.
+
+    *) Добавление: модуль ngx_http_uwsgi_module.
+       Спасибо Roberto De Ioris.
+
+    *) Добавление: директива fastcgi_param со значением, начинающимся со 
+       строки "HTTP_", изменяет строку заголовка в запросе клиента.
+
+    *) Исправление: строки "If-Modified-Since", "If-Range" и им подобные в 
+       заголовке запроса клиента передавались FastCGI-серверу при 
+       кэшировании.
+
+    *) Исправление: listen unix domain сокет нельзя было изменить во время 
+       переконфигурации.
+       Спасибо Максиму Дунину.
+
+
+Изменения в nginx 0.8.39                                          31.05.2010
+
+    *) Исправление: наследуемая директива alias неправильно работала во 
+       вложенном location'е.
+
+    *) Исправление: в комбинации директив alias с переменными и try_files;
+
+    *) Исправление: listen unix domain и IPv6 сокеты не наследовались во 
+       время обновления без перерыва.
+       Спасибо Максиму Дунину.
+
+
+Изменения в nginx 0.8.38                                          24.05.2010
+
+    *) Добавление: директивы proxy_no_cache и fastcgi_no_cache.
+
+    *) Добавление: теперь при использовании переменной $scheme в директиве 
+       rewrite автоматически делается редирект.
+       Спасибо Piotr Sikora.
+
+    *) Исправление: теперь задержки в директиве limit_req соответствует 
+       описанному алгоритму.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: переменную $uid_got нельзя было использовать в SSI и 
+       перловом модулях.
+
+
+Изменения в nginx 0.8.37                                          17.05.2010
+
+    *) Добавление: модуль ngx_http_split_clients_module.
+
+    *) Добавление: директива map поддерживает ключи больше 255 символов.
+
+    *) Исправление: nginx игнорировал значения "private" и "no-store" в 
+       строке "Cache-Control" в заголовке ответа бэкенда.
+
+    *) Исправление: параметр stub в SSI-директиве include не использовался, 
+       если пустой ответ имел код 200.
+
+    *) Исправление: если проксированный или FastCGI запрос внутренне 
+       перенаправлялся в другой проксированный или FastCGI location, то в 
+       рабочем процессе мог произойти segmentation fault; ошибка появилась 
+       в 0.8.33.
+       Спасибо Yichun Zhang.
+
+    *) Исправление: соединения IMAP к серверу Zimbra могло зависнуть до 
+       таймаута.
+       Спасибо Alan Batie.
+
+
+Изменения в nginx 0.8.36                                          22.04.2010
+
+    *) Исправление: модуль ngx_http_dav_module неправильно обрабатывал 
+       методы DELETE, COPY и MOVE для симлинков.
+
+    *) Исправление: модуль SSI в подзапросах использовал закэшированные в 
+       основном запросе значения переменных $query_string, $arg_... и им 
+       подобных.
+
+    *) Исправление: значение переменной повторно экранировалось после 
+       каждого вывода SSI-команды echo; ошибка появилась в 0.6.14.
+
+    *) Исправление: рабочий процесс зависал при запросе файла FIFO.
+       Спасибо Vicente Aguilar и Максиму Дунину.
+
+    *) Исправление: совместимость с OpenSSL-1.0.0 на 64-битном Linux.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: nginx не собирался с параметром --without-http-cache; 
+       ошибка появилась в 0.8.35.
+
+
+Изменения в nginx 0.8.35                                          01.04.2010
+
+    *) Изменение: теперь charset-фильтр работает до SSI-фильтра.
+
+    *) Добавление: директива chunked_transfer_encoding.
+
+    *) Исправление: символ "&" при копировании в аргументы в правилах 
+       rewrite не экранировался.
+
+    *) Исправление: nginx мог завершаться аварийно во время обработки 
+       сигнала или при использовании директивы timer_resolution на 
+       платформах, не поддерживающих методы kqueue или eventport.
+       Спасибо George Xie и Максиму Дунину.
+
+    *) Исправление: если временные файлы и постоянное место хранения 
+       располагались на разных файловых системах, то у постоянных файлов 
+       время изменения было неверным.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: модуль ngx_http_memcached_module мог выдавать ошибку 
+       "memcached sent invalid trailer".
+       Спасибо Максиму Дунину.
+
+    *) Исправление: nginx не мог собрать библиотеку zlib-1.2.4 из исходных 
+       текстов.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: в рабочем процессе происходил segmentation fault, если 
+       перед ответом FastCGI-сервера было много вывода в stderr; ошибка 
+       появилась в 0.8.34.
+       Спасибо Максиму Дунину.
+
+
+Изменения в nginx 0.8.34                                          03.03.2010
+
+    *) Исправление: nginx не поддерживал все шифры, используемые в 
+       клиентских сертификатах.
+       Спасибо Иннокентию Еникееву.
+
+    *) Исправление: nginx неправильно кэшировал FastCGI-ответы, если перед 
+       ответом было много вывода в stderr.
+
+    *) Исправление: nginx не поддерживал HTTPS-рефереры.
+
+    *) Исправление: nginx/Windows мог не находить файлы, если путь в 
+       конфигурации был задан в другом регистре; ошибка появилась в 0.8.33.
+
+    *) Исправление: переменная $date_local выдавала неверное время, если 
+       использовался формат "%s".
+       Спасибо Максиму Дунину.
+
+    *) Исправление: если ssl_session_cache не был установлен или установлен 
+       в none, то при проверке клиентского сертификаты могла происходить 
+       ошибка "session id context uninitialized"; ошибка появилась в 0.7.1.
+
+    *) Исправление: geo-диапазон возвращал значение по умолчанию, если 
+       диапазон включал в себя одну и более сетей размером /16 и не 
+       начинался на границе сети размером /16.
+
+    *) Исправление: блок, используемый в параметре stub в SSI-директиве 
+       include, выводился с MIME-типом "text/plain".
+
+    *) Исправление: $r->sleep() не работал; ошибка появилась в 0.8.11.
+
+
+Изменения в nginx 0.8.33                                          01.02.2010
+
+    *) Безопасность: теперь nginx/Windows игнорирует пробелы в конце URI. 
+       Спасибо Dan Crowley, Core Security Technologies.
+
+    *) Безопасность: теперь nginx/Windows игнорирует короткие имена файлов. 
+       Спасибо Dan Crowley, Core Security Technologies.
+
+    *) Изменение: теперь keepalive соединения после запросов POST не 
+       запрещаются для MSIE 7.0+.
+       Спасибо Adam Lounds.
+
+    *) Изменение: теперь keepalive соединения запрещены для Safari.
+       Спасибо Joshua Sierles.
+
+    *) Исправление: если проксированный или FastCGI запрос внутренне 
+       перенаправлялся в другой проксированный или FastCGI location, то 
+       переменная $upstream_response_time могла иметь ненормально большое 
+       значение; ошибка появилась в 0.8.7.
+
+    *) Исправление: в рабочем процессе мог произойти segmentation fault при 
+       отбрасывания тела запроса; ошибка появилась в 0.8.11.
+
+
+Изменения в nginx 0.8.32                                          11.01.2010
+
+    *) Исправление: ошибки при использовании кодировки UTF-8 в 
+       ngx_http_autoindex_module.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: именованные выделения в регулярных выражениях работали 
+       только для двух переменных.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: теперь в строке заголовка запроса "Host" используется 
+       имя "localhost", если в директиве auth_http указан unix domain 
+       сокет.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: nginx не поддерживал передачу chunk'ами для 201-ых 
+       ответов.
+       Спасибо Julian Reich.
+
+    *) Исправление: если директива "expires modified" выставляла дату в 
+       прошлом, то в строке заголовка ответа "Cache-Control" выдавалось 
+       отрицательное число.
+       Спасибо Алексею Капранову.
+
+
+Изменения в nginx 0.8.31                                          23.12.2009
+
+    *) Добавление: теперь директива error_page может перенаправлять ответы 
+       со статусом 301 и 302.
+
+    *) Добавление: переменные $geoip_city_continent_code, $geoip_latitude и 
+       $geoip_longitude.
+       Спасибо Arvind Sundararajan.
+
+    *) Добавление: модуль ngx_http_image_filter_module теперь всегда 
+       удаляет EXIF и другие данные, если они занимают больше 5% в 
+       JPEG-файле.
+
+    *) Исправление: nginx закрывал соединение при запросе закэшированного 
+       ответа с пустым телом.
+       Спасибо Piotr Sikora.
+
+    *) Исправление: nginx мог не собираться gcc 4.x при использовании 
+       оптимизации -O2 и выше.
+       Спасибо Максиму Дунину и Денису Латыпову.
+
+    *) Исправление: регулярные выражения в location всегда тестировались с 
+       учётом регистра; ошибка появилась в 0.8.25.
+
+    *) Исправление: nginx кэшировал 304 ответ, если в заголовке 
+       проксируемого запроса была строка "If-None-Match".
+       Спасибо Tim Dettrick и David Kostal.
+
+    *) Исправление: nginx/Windows пытался дважды удалить временный файл при 
+       перезаписи уже существующего файла.
+
+
+Изменения в nginx 0.8.30                                          15.12.2009
+
+    *) Изменение: теперь по умолчанию размер буфера директивы 
+       large_client_header_buffers равен 8K.
+       Спасибо Andrew Cholakian.
+
+    *) Добавление: файл conf/fastcgi.conf для простых конфигураций FastCGI.
+
+    *) Исправление: nginx/Windows пытался дважды переименовать временный 
+       файл при перезаписи уже существующего файла.
+
+    *) Исправление: ошибки double free or corruption, возникающей, если имя 
+       хоста не было найдено; ошибка появилась в 0.8.22.
+       Спасибо Константину Свисту.
+
+    *) Исправление: в использовании libatomic на некоторых платформах.
+       Спасибо W-Mark Kubacki.
+
+
+Изменения в nginx 0.8.29                                          30.11.2009
+
+    *) Изменение: теперь для проксируемых ответов HTTP/0.9 в лог пишется 
+       код ответа "009".
+
+    *) Добавление: директивы addition_types, charset_types, gzip_types, 
+       ssi_types, sub_filter_types и xslt_types поддерживают параметр "*".
+
+    *) Добавление: использование встроенных атомарных операций GCC 4.1+.
+       Спасибо W-Mark Kubacki.
+
+    *) Добавление: параметр --with-libatomic[=DIR] в configure.
+       Спасибо W-Mark Kubacki.
+
+    *) Исправление: listen unix domain сокет имели ограниченные права 
+       доступа.
+
+    *) Исправление: закэшированные ответы ответов HTTP/0.9 неправильно 
+       обрабатывались.
+
+    *) Исправление: именованные выделения в регулярных выражениях, заданные 
+       как "?P<...>", не работали в директиве server_name.
+       Спасибо Максиму Дунину.
+
+
+Изменения в nginx 0.8.28                                          23.11.2009
+
+    *) Исправление: nginx не собирался с параметром --without-pcre; ошибка 
+       появилась в 0.8.25.
+
+
+Изменения в nginx 0.8.27                                          17.11.2009
+
+    *) Исправление: регулярные выражения не работали в nginx/Windows; 
+       ошибка появилась в 0.8.25.
+
+
+Изменения в nginx 0.8.26                                          16.11.2009
+
+    *) Исправление: ошибки при использовании выделений в директиве rewrite; 
+       ошибка появилась в 0.8.25.
+
+    *) Исправление: nginx не собирался без параметра --with-debug; ошибка 
+       появилась в 0.8.25.
+
+
+Изменения в nginx 0.8.25                                          16.11.2009
+
+    *) Изменение: теперь в лог ошибок не пишется сообщение, если переменная 
+       не найдена с помощью метода $r->variable().
+
+    *) Добавление: модуль ngx_http_degradation_module.
+
+    *) Добавление: именованные выделения в регулярных выражениях.
+
+    *) Добавление: теперь при использовании переменных в директиве 
+       proxy_pass не требуется задавать URI.
+
+    *) Добавление: теперь директива msie_padding работает и для Chrome.
+
+    *) Исправление: в рабочем процессе происходил segmentation fault при 
+       недостатке памяти; ошибка появилась в 0.8.18.
+
+    *) Исправление: nginx передавал сжатые ответы клиентам, не 
+       поддерживающим сжатие, при настройках gzip_static on и gzip_vary 
+       off; ошибка появилась в 0.8.16.
+
+
+Изменения в nginx 0.8.24                                          11.11.2009
+
+    *) Исправление: nginx всегда добавлял строку "Content-Encoding: gzip" в 
+       заголовок 304-ых ответов модуля ngx_http_gzip_static_module.
+
+    *) Исправление: nginx не собирался без параметра --with-debug; ошибка 
+       появилась в 0.8.23.
+
+    *) Исправление: параметр "unix:" в директиве set_real_ip_from 
+       неправильно наследовался с предыдущего уровня.
+
+    *) Исправление: в resolver'е при определении пустого имени.
+
+
+Изменения в nginx 0.8.23                                          11.11.2009
+
+    *) Безопасность: теперь SSL/TLS renegotiation запрещён.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: listen unix domain сокет не наследовался во время 
+       обновления без перерыва.
+
+    *) Исправление: параметр "unix:" в директиве set_real_ip_from не 
+       работал без ещё одной директивы с любым IP-адресом.
+
+    *) Исправление: segmentation fault и зацикливания в resolver'е.
+
+    *) Исправление: в resolver'е.
+       Спасибо Артёму Бохану.
+
+
+Изменения в nginx 0.8.22                                          03.11.2009
+
+    *) Добавление: директивы proxy_bind, fastcgi_bind и memcached_bind.
+
+    *) Добавление: директивы access и deny поддерживают IPv6.
+
+    *) Добавление: директива set_real_ip_from поддерживает IPv6 адреса в 
+       заголовках запроса.
+
+    *) Добавление: параметр "unix:" в директиве set_real_ip_from.
+
+    *) Исправление: nginx не удалял unix domain сокет после тестирования 
+       конфигурации.
+
+    *) Исправление: nginx удалял unix domain сокет во время обновления без 
+       перерыва.
+
+    *) Исправление: оператор "!-x" не работал.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: в рабочем процессе мог произойти segmentation fault при 
+       использовании limit_rate в HTTPS сервере.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: при записи в лог переменной $limit_rate в рабочем 
+       процессе происходил segmentation fault.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: в рабочем процессе мог произойти segmentation fault, 
+       если внутри блока server не было директивы listen; ошибка появилась 
+       в 0.8.21.
+
+
+Изменения в nginx 0.8.21                                          26.10.2009
+
+    *) Добавление: теперь ключ -V показывает статус поддержки TLS SNI.
+
+    *) Добавление: директива listen модуля HTTP поддерживает unix domain 
+       сокеты.
+       Спасибо Hongli Lai.
+
+    *) Добавление: параметр "default_server" в директиве listen.
+
+    *) Добавление: теперь параметр "default" не обязателен для установки 
+       параметров listen-сокета.
+
+    *) Исправление: nginx не поддерживал даты в 2038 году на 32-битных 
+       платформах;
+
+    *) Исправление: утечки сокетов; ошибка появилась в 0.8.11.
+
+
+Изменения в nginx 0.8.20                                          14.10.2009
+
+    *) Изменение: теперь по умолчанию используются следующие шифры SSL: 
+       "HIGH:!ADH:!MD5".
+
+    *) Исправление: модуль ngx_http_autoindex_module не показывал последний 
+       слэш для линков на каталоги; ошибка появилась в 0.7.15.
+
+    *) Исправление: nginx не закрывал лог, заданный параметром конфигурации 
+       --error-log-path; ошибка появилась в 0.7.53.
+
+    *) Исправление: nginx не считал запятую разделителем в строке 
+       "Cache-Control" в заголовке ответа бэкенда.
+
+    *) Исправление: nginx/Windows мог не создать временный файл, файл в 
+       кэше или файл с помощью директив proxy/fastcgi_store, если рабочий 
+       процесс не имел достаточно прав для работы с каталогами верхнего 
+       уровня.
+
+    *) Исправление: строки "Set-Cookie" и "P3P" в заголовке ответа 
+       FastCGI-сервера не скрывались при кэшировании, если не 
+       использовались директивы fastcgi_hide_header с любыми параметрами.
+
+    *) Исправление: nginx неверно считал размер кэша на диске.
+
+
+Изменения в nginx 0.8.19                                          06.10.2009
+
+    *) Изменение: теперь протокол SSLv2 по умолчанию запрещён.
+
+    *) Изменение: теперь по умолчанию используются следующие шифры SSL: 
+       "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM".
+
+    *) Исправление: директива limit_req не работала; ошибка появилась в 
+       0.8.18.
+
+
+Изменения в nginx 0.8.18                                          06.10.2009
+
+    *) Добавление: директива read_ahead.
+
+    *) Добавление: теперь можно использовать несколько директив 
+       perl_modules.
+
+    *) Добавление: директивы limit_req_log_level и limit_conn_log_level.
+
+    *) Исправление: теперь директива limit_req соответствует алгоритму 
+       leaky bucket.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: nginx не работал на Linux/sparc.
+       Спасибо Marcus Ramberg.
+
+    *) Исправление: nginx слал символ '\0' в строке "Location" в заголовке 
+       в ответе на запрос MKCOL.
+       Спасибо Xie Zhenye.
+
+    *) Исправление: вместо кода ответа 499 в лог записывался код 0; ошибка 
+       появилась в 0.8.11.
+
+    *) Исправление: утечки сокетов; ошибка появилась в 0.8.11.
+
+
+Изменения в nginx 0.8.17                                          28.09.2009
+
+    *) Безопасность: теперь символы "/../" запрещены в строке "Destination" 
+       в заголовке запроса.
+
+    *) Изменение: теперь значение переменной $host всегда в нижнем регистре.
+
+    *) Добавление: переменная $ssl_session_id.
+
+    *) Исправление: утечки сокетов; ошибка появилась в 0.8.11.
+
+
 Изменения в nginx 0.8.16                                          22.09.2009
 
     *) Добавление: директива image_filter_transparency.
@@ -157,7 +962,7 @@
        Спасибо Максиму Дунину.
 
     *) Исправление: в обработке строк "Last-Modified" и "Accept-Ranges" в 
-       заголовке ответа бэкенда; ошибка появилась в 0.7.44
+       заголовке ответа бэкенда; ошибка появилась в 0.7.44.
        Спасибо Максиму Дунину.
 
     *) Исправление: ошибки "[alert] zero size buf" при получении пустых 
@@ -1336,7 +2141,7 @@
 
     *) Исправление: nginx неверно определял длину строки кэша на 
        Pentium 4.
-       Спасибо Gena Makhomed.
+       Спасибо Геннадию Махомеду.
 
     *) Исправление: в проксированных подзапросах и подзапросах к 
        FastCGI-серверу вместо метода GET использовался оригинальный метод 
@@ -1604,7 +2409,7 @@
        Спасибо Андрею Нигматулину.
 
     *) Исправление: ngx_http_memcached_module не устанавливал 
-       upstream_response_time.
+       $upstream_response_time.
        Спасибо Максиму Дунину.
 
     *) Исправление: рабочий процесс мог зациклиться при использовании 
--- a/LICENSE	Sun Sep 27 01:10:42 2009 +0400
+++ b/LICENSE	Mon Apr 25 04:22:17 2011 +0400
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2002-2009 Igor Sysoev
+ * Copyright (C) 2002-2011 Igor Sysoev
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
--- a/auto/cc/conf	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/cc/conf	Mon Apr 25 04:22:17 2011 +0400
@@ -104,7 +104,7 @@
 fi
 
 CFLAGS="$CFLAGS $NGX_CC_OPT"
-
+NGX_TEST_LD_OPT="$NGX_LD_OPT"
 
 if [ "$NGX_PLATFORM" != win32 ]; then
 
@@ -125,16 +125,21 @@
         fi
     fi
 
-    ngx_feature="gcc variadic macros"
-    ngx_feature_name="NGX_HAVE_GCC_VARIADIC_MACROS"
+
+    ngx_feature="gcc builtin atomic operations"
+    ngx_feature_name=NGX_HAVE_GCC_ATOMIC
     ngx_feature_run=yes
-    ngx_feature_incs="#include <stdio.h>
-#define var(dummy, args...)  sprintf(args)"
+    ngx_feature_incs=
     ngx_feature_path=
     ngx_feature_libs=
-    ngx_feature_test="char  buf[30]; buf[0] = '0';
-                      var(0, buf, \"%d\", 1);
-                      if (buf[0] != '1') return 1"
+    ngx_feature_test="long  n = 0;
+                      if (!__sync_bool_compare_and_swap(&n, 0, 1))
+                          return 1;
+                      if (__sync_fetch_and_add(&n, 1) != 1)
+                          return 1;
+                      if (n != 2)
+                          return 1;
+                      __sync_synchronize();"
     . auto/feature
 
 
@@ -155,6 +160,19 @@
      fi
 
 
+    ngx_feature="gcc variadic macros"
+    ngx_feature_name="NGX_HAVE_GCC_VARIADIC_MACROS"
+    ngx_feature_run=yes
+    ngx_feature_incs="#include <stdio.h>
+#define var(dummy, args...)  sprintf(args)"
+    ngx_feature_path=
+    ngx_feature_libs=
+    ngx_feature_test="char  buf[30]; buf[0] = '0';
+                      var(0, buf, \"%d\", 1);
+                      if (buf[0] != '1') return 1"
+    . auto/feature
+
+
 #    ngx_feature="inline"
 #    ngx_feature_name=
 #    ngx_feature_run=no
--- a/auto/cc/gcc	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/cc/gcc	Mon Apr 25 04:22:17 2011 +0400
@@ -51,8 +51,6 @@
 #NGX_GCC_OPT="-Os"
 NGX_GCC_OPT="-O"
 
-CFLAGS="$CFLAGS $NGX_GCC_OPT"
-
 #CFLAGS="$CFLAGS -fomit-frame-pointer"
 
 case $CPU in
@@ -90,7 +88,6 @@
         # build 32-bit UltraSparc binary
         CPU_OPT="-m32"
         CORE_LINK="$CORE_LINK -m32"
-        CC_AUX_FLAGS="$CC_AUX_FLAGS -m32"
         NGX_CPU_CACHE_LINE=64
     ;;
 
@@ -98,7 +95,6 @@
         # build 64-bit UltraSparc binary
         CPU_OPT="-m64"
         CORE_LINK="$CORE_LINK -m64"
-        CC_AUX_FLAGS="$CC_AUX_FLAGS -m64"
         NGX_CPU_CACHE_LINE=64
     ;;
 
@@ -108,12 +104,12 @@
         CPU_OPT="$CPU_OPT -falign-functions=32 -falign-labels=32"
         CPU_OPT="$CPU_OPT -falign-loops=32 -falign-jumps=32"
         CORE_LINK="$CORE_LINK -m64"
-        CC_AUX_FLAGS="$CC_AUX_FLAGS -m64"
         NGX_CPU_CACHE_LINE=128
     ;;
 
 esac
 
+CC_AUX_FLAGS="$CC_AUX_FLAGS $CPU_OPT"
 
 case "$NGX_GCC_VER" in
     2.7*)
--- a/auto/feature	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/feature	Mon Apr 25 04:22:17 2011 +0400
@@ -39,7 +39,7 @@
 
 
 ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS $ngx_feature_inc_path \
-          -o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_LD_OPT $ngx_feature_libs"
+          -o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_TEST_LD_OPT $ngx_feature_libs"
 
 ngx_feature_inc_path=
 
@@ -65,6 +65,24 @@
             fi
         ;;
 
+        value)
+            # /bin/sh is used to intercept "Killed" or "Abort trap" messages
+            if /bin/sh -c $NGX_AUTOTEST >/dev/null 2>&1; then
+                echo " found"
+                ngx_found=yes
+
+                cat << END >> $NGX_AUTO_CONFIG_H
+
+#ifndef $ngx_feature_name
+#define $ngx_feature_name  `$NGX_AUTOTEST`
+#endif
+
+END
+            else
+                echo " found but is not working"
+            fi
+        ;;
+
         bug)
             # /bin/sh is used to intercept "Killed" or "Abort trap" messages
             if /bin/sh -c $NGX_AUTOTEST >/dev/null 2>&1; then
--- a/auto/install	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/install	Mon Apr 25 04:22:17 2011 +0400
@@ -74,6 +74,13 @@
 
 cat << END                                                    >> $NGX_MAKEFILE
 
+manpage:
+	sed -e "s|%%PREFIX%%|$NGX_PREFIX|" \\
+		-e "s|%%PID_PATH%%|$NGX_PID_PATH|" \\
+		-e "s|%%CONF_PATH%%|$NGX_CONF_PATH|" \\
+		-e "s|%%ERROR_LOG_PATH%%|$NGX_ERROR_LOG_PATH|" \\
+		< man/nginx.8 > $NGX_OBJS/nginx.8
+
 install:	$NGX_OBJS${ngx_dirsep}nginx${ngx_binext} \
 		$NGX_INSTALL_PERL_MODULES
 	test -d '\$(DESTDIR)$NGX_PREFIX' || mkdir -p '\$(DESTDIR)$NGX_PREFIX'
@@ -101,6 +108,20 @@
 	cp conf/fastcgi_params \
 		'\$(DESTDIR)$NGX_CONF_PREFIX/fastcgi_params.default'
 
+	test -f '\$(DESTDIR)$NGX_CONF_PREFIX/fastcgi.conf' \
+		|| cp conf/fastcgi.conf '\$(DESTDIR)$NGX_CONF_PREFIX'
+	cp conf/fastcgi.conf '\$(DESTDIR)$NGX_CONF_PREFIX/fastcgi.conf.default'
+
+	test -f '\$(DESTDIR)$NGX_CONF_PREFIX/uwsgi_params' \
+		|| cp conf/uwsgi_params '\$(DESTDIR)$NGX_CONF_PREFIX'
+	cp conf/uwsgi_params \
+		'\$(DESTDIR)$NGX_CONF_PREFIX/uwsgi_params.default'
+
+	test -f '\$(DESTDIR)$NGX_CONF_PREFIX/scgi_params' \
+		|| cp conf/scgi_params '\$(DESTDIR)$NGX_CONF_PREFIX'
+	cp conf/scgi_params \
+		'\$(DESTDIR)$NGX_CONF_PREFIX/scgi_params.default'
+
 	test -f '\$(DESTDIR)$NGX_CONF_PATH' \
 		|| cp conf/nginx.conf '\$(DESTDIR)$NGX_CONF_PATH'
 	cp conf/nginx.conf '\$(DESTDIR)$NGX_CONF_PREFIX/nginx.conf.default'
@@ -132,6 +153,7 @@
 
 build:
 	\$(MAKE) -f $NGX_MAKEFILE
+	\$(MAKE) -f $NGX_MAKEFILE manpage
 
 install:
 	\$(MAKE) -f $NGX_MAKEFILE install
@@ -144,19 +166,4 @@
 	test -f $NGX_PID_PATH.oldbin
 
 	kill -QUIT \`cat $NGX_PID_PATH.oldbin\`
-
-upgrade1:
-	# upgrade 0.1.x to 0.2+
-
-	$NGX_SBIN_PATH -t
-
-	cp $NGX_PID_PATH $NGX_PID_PATH.oldbin
-
-	kill -USR2 \`cat $NGX_PID_PATH\`
-	sleep 1
-	test -f $NGX_PID_PATH.oldbin
-
-	cp $NGX_PID_PATH $NGX_PID_PATH.newbin
-
-	kill -QUIT \`cat $NGX_PID_PATH.oldbin\`
 END
--- a/auto/lib/conf	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/lib/conf	Mon Apr 25 04:22:17 2011 +0400
@@ -70,6 +70,11 @@
 if [ $HTTP_GEOIP = YES ]; then
     . auto/lib/geoip/conf
 fi
+
 if [ $NGX_GOOGLE_PERFTOOLS = YES ]; then
     . auto/lib/google-perftools/conf
 fi
+
+if [ $NGX_LIBATOMIC != NO ]; then
+    . auto/lib/libatomic/conf
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/auto/lib/libatomic/conf	Mon Apr 25 04:22:17 2011 +0400
@@ -0,0 +1,42 @@
+
+# Copyright (C) Igor Sysoev
+
+
+if [ $NGX_LIBATOMIC != YES ]; then
+
+    have=NGX_HAVE_LIBATOMIC . auto/have
+    CORE_INCS="$CORE_INCS $NGX_LIBATOMIC/src"
+    LINK_DEPS="$LINK_DEPS $NGX_LIBATOMIC/src/libatomic_ops.a"
+    CORE_LIBS="$CORE_LIBS $NGX_LIBATOMIC/src/libatomic_ops.a"
+
+else
+
+    ngx_feature="atomic_ops library"
+    ngx_feature_name=NGX_HAVE_LIBATOMIC
+    ngx_feature_run=yes
+    ngx_feature_incs="#define AO_REQUIRE_CAS
+                      #include <atomic_ops.h>"
+    ngx_feature_path=
+    ngx_feature_libs="-latomic_ops"
+    ngx_feature_test="long  n = 0;
+                      if (!AO_compare_and_swap(&n, 0, 1))
+                          return 1;
+                      if (AO_fetch_and_add(&n, 1) != 1)
+                          return 1;
+                      if (n != 2)
+                          return 1;
+                      AO_nop();"
+    . auto/feature
+
+    if [ $ngx_found = yes ]; then
+        CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
+    else
+
+cat << END
+
+$0: error: libatomic_ops library was not found.
+
+END
+        exit 1
+    fi
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/auto/lib/libatomic/make	Mon Apr 25 04:22:17 2011 +0400
@@ -0,0 +1,13 @@
+
+# Copyright (C) Igor Sysoev
+
+
+    cat << END                                            >> $NGX_MAKEFILE
+
+$NGX_LIBATOMIC/src/libatomic_ops.a:	$NGX_LIBATOMIC/Makefile
+	cd $NGX_LIBATOMIC && make
+
+$NGX_LIBATOMIC/Makefile:	$NGX_MAKEFILE
+	cd $NGX_LIBATOMIC && ./configure
+
+END
--- a/auto/lib/make	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/lib/make	Mon Apr 25 04:22:17 2011 +0400
@@ -22,6 +22,10 @@
     . auto/lib/zlib/make
 fi
 
+if [ $NGX_LIBATOMIC != NO -a $NGX_LIBATOMIC != YES ]; then
+    . auto/lib/libatomic/make
+fi
+
 if [ $USE_PERL = YES ]; then
     . auto/lib/perl/make
 fi
--- a/auto/lib/md5/conf	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/lib/md5/conf	Mon Apr 25 04:22:17 2011 +0400
@@ -94,8 +94,10 @@
             CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
             MD5=YES
             MD5_LIB=$ngx_md5_lib
-        else
+        fi
+    fi
 
+    if [ $MD5 != YES ]; then
 cat << END
 
 $0: error: the HTTP cache module requires md5 functions
@@ -105,9 +107,7 @@
 --with-http_ssl_module --with-openssl=<path> options.
 
 END
-            exit 1
-        fi
-
+        exit 1
     fi
 
 fi
--- a/auto/lib/openssl/conf	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/lib/openssl/conf	Mon Apr 25 04:22:17 2011 +0400
@@ -19,54 +19,45 @@
 
             # libeay32.lib requires gdi32.lib
             CORE_LIBS="$CORE_LIBS gdi32.lib"
+            # OpenSSL 1.0.0 requires crypt32.lib
+            CORE_LIBS="$CORE_LIBS crypt32.lib"
         ;;
 
         *)
             have=NGX_OPENSSL . auto/have
             have=NGX_SSL . auto/have
 
-            CORE_INCS="$CORE_INCS $OPENSSL/openssl/include"
-            CORE_DEPS="$CORE_DEPS $OPENSSL/openssl/include/openssl/ssl.h"
-            CORE_LIBS="$CORE_LIBS $OPENSSL/openssl/lib/libssl.a"
-            CORE_LIBS="$CORE_LIBS $OPENSSL/openssl/lib/libcrypto.a"
+            CORE_INCS="$CORE_INCS $OPENSSL/.openssl/include"
+            CORE_DEPS="$CORE_DEPS $OPENSSL/.openssl/include/openssl/ssl.h"
+            CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libssl.a"
+            CORE_LIBS="$CORE_LIBS $OPENSSL/.openssl/lib/libcrypto.a"
             CORE_LIBS="$CORE_LIBS $NGX_LIBDL"
         ;;
     esac
 
 else
 
-    case "$NGX_PLATFORM" in
-
-        win32)
-            have=NGX_OPENSSL . auto/have
-            have=NGX_SSL . auto/have
-            OPENSSL=YES
+    if [ "$NGX_PLATFORM" != win32 ]; then
 
-            CORE_INCS="$CORE_INCS c:/openssl/include"
-            CORE_LIBS="$CORE_LIBS c:/openssl/ssleay32.lib"
-            CORE_LIBS="$CORE_LIBS c:/openssl/libeay32.lib"
-
-            # libeay32.lib requires gdi32.lib
-            CORE_LIBS="$CORE_LIBS gdi32.lib"
-        ;;
+        OPENSSL=NO
 
-        *)
-            OPENSSL=NO
+        ngx_feature="OpenSSL library"
+        ngx_feature_name="NGX_OPENSSL"
+        ngx_feature_run=no
+        ngx_feature_incs="#include <openssl/ssl.h>"
+        ngx_feature_path=
+        ngx_feature_libs="-lssl -lcrypto"
+        ngx_feature_test="SSL_library_init()"
+        . auto/feature
 
-            ngx_feature="OpenSSL library"
-            ngx_feature_name="NGX_OPENSSL"
-            ngx_feature_run=no
-            ngx_feature_incs="#include <openssl/ssl.h>"
-            ngx_feature_path=
-            ngx_feature_libs="-lssl -lcrypto"
-            ngx_feature_test="SSL_library_init()"
-            . auto/feature
+        if [ $ngx_found = yes ]; then
+            have=NGX_SSL . auto/have
+            CORE_LIBS="$CORE_LIBS $ngx_feature_libs $NGX_LIBDL"
+            OPENSSL=YES
+        fi
+    fi
 
-            if [ $ngx_found = yes ]; then
-                have=NGX_SSL . auto/have
-                CORE_LIBS="$CORE_LIBS $ngx_feature_libs $NGX_LIBDL"
-                OPENSSL=YES
-            else
+    if [ $OPENSSL != YES ]; then
 
 cat << END
 
@@ -76,10 +67,7 @@
 with nginx by using --with-openssl=<path> option.
 
 END
-                exit 1
-            fi
-        ;;
-
-    esac
+        exit 1
+    fi
 
 fi
--- a/auto/lib/openssl/make	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/lib/openssl/make	Mon Apr 25 04:22:17 2011 +0400
@@ -46,18 +46,18 @@
         esac
 
         case $OPENSSL in
-            /*) ngx_prefix="$OPENSSL/openssl" ;;
-            *)  ngx_prefix="$PWD/$OPENSSL/openssl" ;;
+            /*) ngx_prefix="$OPENSSL/.openssl" ;;
+            *)  ngx_prefix="$PWD/$OPENSSL/.openssl" ;;
         esac
 
         cat << END                                            >> $NGX_MAKEFILE
 
-$OPENSSL/openssl/include/openssl/ssl.h:	$NGX_MAKEFILE
+$OPENSSL/.openssl/include/openssl/ssl.h:	$NGX_MAKEFILE
 	cd $OPENSSL \\
 	&& \$(MAKE) clean \\
 	&& ./config --prefix=$ngx_prefix no-shared $OPENSSL_OPT \\
 	&& \$(MAKE) \\
-	&& \$(MAKE) install
+	&& \$(MAKE) install LIBDIR=lib
 
 END
 
--- a/auto/lib/openssl/makefile.bcc	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/lib/openssl/makefile.bcc	Mon Apr 25 04:22:17 2011 +0400
@@ -5,8 +5,7 @@
 all:
 	cd $(OPENSSL)
 
-	perl Configure BC-32 no-shared --prefix=openssl -DNO_SYS_TYPES_H \
-		$(OPENSSL_OPT)
+	perl Configure BC-32 no-shared --prefix=openssl $(OPENSSL_OPT)
 
 	ms\do_nasm
 
--- a/auto/lib/openssl/makefile.msvc	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/lib/openssl/makefile.msvc	Mon Apr 25 04:22:17 2011 +0400
@@ -5,8 +5,7 @@
 all:
 	cd $(OPENSSL)
 
-	perl Configure VC-WIN32 no-shared --prefix=openssl -DNO_SYS_TYPES_H \
-		$(OPENSSL_OPT)
+	perl Configure VC-WIN32 no-shared --prefix=openssl $(OPENSSL_OPT)
 
 	ms\do_ms
 
--- a/auto/lib/pcre/conf	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/lib/pcre/conf	Mon Apr 25 04:22:17 2011 +0400
@@ -161,8 +161,10 @@
             CORE_INCS="$CORE_INCS $ngx_feature_path"
             CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
             PCRE=YES
-        else
+        fi
+    fi
 
+    if [ $PCRE != YES ]; then
 cat << END
 
 $0: error: the HTTP rewrite module requires the PCRE library.
@@ -171,9 +173,7 @@
 statically from the source with nginx by using --with-pcre=<path> option.
 
 END
-            exit 1
+        exit 1
+    fi
 
-        fi
-
-    fi
 fi
--- a/auto/lib/zlib/conf	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/lib/zlib/conf	Mon Apr 25 04:22:17 2011 +0400
@@ -57,8 +57,10 @@
             CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
             ZLIB=YES
             ngx_found=no
-        else
+        fi
+    fi
 
+    if [ $ZLIB != YES ]; then
 cat << END
 
 $0: error: the HTTP gzip module requires the zlib library.
@@ -67,8 +69,7 @@
 statically from the source with nginx by using --with-zlib=<path> option.
 
 END
-            exit 1
-        fi
+        exit 1
     fi
 
 fi
--- a/auto/lib/zlib/make	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/lib/zlib/make	Mon Apr 25 04:22:17 2011 +0400
@@ -53,7 +53,7 @@
 
 $ZLIB/libz.a:	$NGX_MAKEFILE
 	cd $ZLIB \\
-	&& \$(MAKE) clean \\
+	&& \$(MAKE) distclean \\
 	&& cp contrib/asm586/match.S . \\
 	&& CFLAGS="$ZLIB_OPT -DASMV" CC="\$(CC)" \\
 		./configure \\
@@ -70,7 +70,7 @@
 
 $ZLIB/libz.a:	$NGX_MAKEFILE
 	cd $ZLIB \\
-	&& \$(MAKE) clean \\
+	&& \$(MAKE) distclean \\
 	&& cp contrib/asm686/match.S . \\
 	&& CFLAGS="$ZLIB_OPT -DASMV" CC="\$(CC)" \\
 		./configure \\
@@ -103,7 +103,7 @@
 
 $ZLIB/libz.a:	$NGX_MAKEFILE
 	cd $ZLIB \\
-	&& \$(MAKE) clean \\
+	&& \$(MAKE) distclean \\
 	&& CFLAGS="$ZLIB_OPT" CC="\$(CC)" \\
 		./configure \\
 	&& \$(MAKE) libz.a
--- a/auto/modules	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/modules	Mon Apr 25 04:22:17 2011 +0400
@@ -102,10 +102,10 @@
 #     ngx_http_range_header_filter
 #     ngx_http_gzip_filter
 #     ngx_http_postpone_filter
+#     ngx_http_ssi_filter
 #     ngx_http_charset_filter
-#     ngx_http_ssi_filter
 #         ngx_http_xslt_filter
-#         ngx_http_image_filter_filter
+#         ngx_http_image_filter
 #         ngx_http_sub_filter
 #         ngx_http_addition_filter
 #         ngx_http_userid_filter
@@ -131,12 +131,6 @@
     HTTP_SRCS="$HTTP_SRCS $HTTP_POSTPONE_FILTER_SRCS"
 fi
 
-if [ $HTTP_CHARSET = YES ]; then
-    have=NGX_HTTP_CHARSET . auto/have
-    HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_CHARSET_FILTER_MODULE"
-    HTTP_SRCS="$HTTP_SRCS $HTTP_CHARSET_SRCS"
-fi
-
 if [ $HTTP_SSI = YES ]; then
     have=NGX_HTTP_SSI . auto/have
     HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_SSI_FILTER_MODULE"
@@ -144,6 +138,11 @@
     HTTP_SRCS="$HTTP_SRCS $HTTP_SSI_SRCS"
 fi
 
+if [ $HTTP_CHARSET = YES ]; then
+    HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_CHARSET_FILTER_MODULE"
+    HTTP_SRCS="$HTTP_SRCS $HTTP_CHARSET_SRCS"
+fi
+
 if [ $HTTP_XSLT = YES ]; then
     USE_LIBXSLT=YES
     HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_XSLT_FILTER_MODULE"
@@ -186,7 +185,6 @@
 fi
 
 if [ $HTTP_AUTOINDEX = YES ]; then
-    have=NGX_HTTP_AUTOINDEX . auto/have
     HTTP_MODULES="$HTTP_MODULES $HTTP_AUTOINDEX_MODULE"
     HTTP_SRCS="$HTTP_SRCS $HTTP_AUTOINDEX_SRCS"
 fi
@@ -194,13 +192,11 @@
 HTTP_MODULES="$HTTP_MODULES $HTTP_INDEX_MODULE"
 
 if [ $HTTP_RANDOM_INDEX = YES ]; then
-    have=NGX_HTTP_RANDOM_INDEX . auto/have
     HTTP_MODULES="$HTTP_MODULES $HTTP_RANDOM_INDEX_MODULE"
     HTTP_SRCS="$HTTP_SRCS $HTTP_RANDOM_INDEX_SRCS"
 fi
 
 if [ $HTTP_AUTH_BASIC = YES ]; then
-    have=NGX_HTTP_AUTH_BASIC . auto/have
     have=NGX_CRYPT . auto/have
     HTTP_MODULES="$HTTP_MODULES $HTTP_AUTH_BASIC_MODULE"
     HTTP_SRCS="$HTTP_SRCS $HTTP_AUTH_BASIC_SRCS"
@@ -208,7 +204,6 @@
 fi
 
 if [ $HTTP_ACCESS = YES ]; then
-    have=NGX_HTTP_ACCESS . auto/have
     HTTP_MODULES="$HTTP_MODULES $HTTP_ACCESS_MODULE"
     HTTP_SRCS="$HTTP_SRCS $HTTP_ACCESS_SRCS"
 fi
@@ -230,7 +225,6 @@
 fi
 
 if [ $HTTP_STATUS = YES ]; then
-    have=NGX_HTTP_STATUS . auto/have
     HTTP_MODULES="$HTTP_MODULES $HTTP_STATUS_MODULE"
     HTTP_SRCS="$HTTP_SRCS $HTTP_STATUS_SRCS"
 fi
@@ -242,24 +236,26 @@
 fi
 
 if [ $HTTP_GEOIP = YES ]; then
-    have=NGX_HTTP_GEOIP . auto/have
     HTTP_MODULES="$HTTP_MODULES $HTTP_GEOIP_MODULE"
     HTTP_SRCS="$HTTP_SRCS $HTTP_GEOIP_SRCS"
 fi
 
 if [ $HTTP_MAP = YES ]; then
-    have=NGX_HTTP_MAP . auto/have
     HTTP_MODULES="$HTTP_MODULES $HTTP_MAP_MODULE"
     HTTP_SRCS="$HTTP_SRCS $HTTP_MAP_SRCS"
 fi
 
+if [ $HTTP_SPLIT_CLIENTS = YES ]; then
+    HTTP_MODULES="$HTTP_MODULES $HTTP_SPLIT_CLIENTS_MODULE"
+    HTTP_SRCS="$HTTP_SRCS $HTTP_SPLIT_CLIENTS_SRCS"
+fi
+
 if [ $HTTP_REFERER = YES ]; then
     HTTP_MODULES="$HTTP_MODULES $HTTP_REFERER_MODULE"
     HTTP_SRCS="$HTTP_SRCS $HTTP_REFERER_SRCS"
 fi
 
 if [ $HTTP_REWRITE = YES -a $USE_PCRE != DISABLED ]; then
-    have=NGX_HTTP_REWRITE . auto/have
     USE_PCRE=YES
     HTTP_MODULES="$HTTP_MODULES $HTTP_REWRITE_MODULE"
     HTTP_SRCS="$HTTP_SRCS $HTTP_REWRITE_SRCS"
@@ -286,9 +282,18 @@
     HTTP_SRCS="$HTTP_SRCS $HTTP_FASTCGI_SRCS"
 fi
 
+if [ $HTTP_UWSGI = YES ]; then
+    HTTP_MODULES="$HTTP_MODULES $HTTP_UWSGI_MODULE"
+    HTTP_SRCS="$HTTP_SRCS $HTTP_UWSGI_SRCS"
+fi
+
+if [ $HTTP_SCGI = YES ]; then
+    HTTP_MODULES="$HTTP_MODULES $HTTP_SCGI_MODULE"
+    HTTP_SRCS="$HTTP_SRCS $HTTP_SCGI_SRCS"
+fi
+
 if [ $HTTP_PERL = YES ]; then
     USE_PERL=YES
-    have=NGX_HTTP_PERL . auto/have
     HTTP_MODULES="$HTTP_MODULES $HTTP_PERL_MODULE"
     HTTP_INCS="$HTTP_INCS $HTTP_PERL_INCS"
     HTTP_DEPS="$HTTP_DEPS $HTTP_PERL_DEPS"
@@ -316,6 +321,12 @@
     HTTP_SRCS="$HTTP_SRCS $HTTP_SECURE_LINK_SRCS"
 fi
 
+if [ $HTTP_DEGRADATION = YES ]; then
+    have=NGX_HTTP_DEGRADATION . auto/have
+    HTTP_MODULES="$HTTP_MODULES $HTTP_DEGRADATION_MODULE"
+    HTTP_SRCS="$HTTP_SRCS $HTTP_DEGRADATION_SRCS"
+fi
+
 if [ $HTTP_FLV = YES ]; then
     HTTP_MODULES="$HTTP_MODULES $HTTP_FLV_MODULE"
     HTTP_SRCS="$HTTP_SRCS $HTTP_FLV_SRCS"
--- a/auto/options	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/options	Mon Apr 25 04:22:17 2011 +0400
@@ -52,6 +52,8 @@
 NGX_HTTP_CLIENT_TEMP_PATH=
 NGX_HTTP_PROXY_TEMP_PATH=
 NGX_HTTP_FASTCGI_TEMP_PATH=
+NGX_HTTP_UWSGI_TEMP_PATH=
+NGX_HTTP_SCGI_TEMP_PATH=
 
 HTTP_CACHE=YES
 HTTP_CHARSET=YES
@@ -74,10 +76,13 @@
 HTTP_GEO=YES
 HTTP_GEOIP=NO
 HTTP_MAP=YES
+HTTP_SPLIT_CLIENTS=YES
 HTTP_REFERER=YES
 HTTP_REWRITE=YES
 HTTP_PROXY=YES
 HTTP_FASTCGI=YES
+HTTP_UWSGI=YES
+HTTP_SCGI=YES
 HTTP_PERL=NO
 HTTP_MEMCACHED=YES
 HTTP_LIMIT_ZONE=YES
@@ -85,6 +90,7 @@
 HTTP_EMPTY_GIF=YES
 HTTP_BROWSER=YES
 HTTP_SECURE_LINK=NO
+HTTP_DEGRADATION=NO
 HTTP_FLV=NO
 HTTP_GZIP_STATIC=NO
 HTTP_UPSTREAM_IP_HASH=YES
@@ -131,6 +137,8 @@
 NGX_GOOGLE_PERFTOOLS=NO
 NGX_CPP_TEST=NO
 
+NGX_LIBATOMIC=NO
+
 NGX_CPU_CACHE_LINE=
 
 opt=
@@ -181,6 +189,8 @@
         --http-client-body-temp-path=*)  NGX_HTTP_CLIENT_TEMP_PATH="$value" ;;
         --http-proxy-temp-path=*)        NGX_HTTP_PROXY_TEMP_PATH="$value" ;;
         --http-fastcgi-temp-path=*)      NGX_HTTP_FASTCGI_TEMP_PATH="$value" ;;
+        --http-uwsgi-temp-path=*)        NGX_HTTP_UWSGI_TEMP_PATH="$value" ;;
+        --http-scgi-temp-path=*)         NGX_HTTP_SCGI_TEMP_PATH="$value" ;;
 
         --with-http_ssl_module)          HTTP_SSL=YES               ;;
         --with-http_realip_module)       HTTP_REALIP=YES            ;;
@@ -194,6 +204,7 @@
         --with-http_gzip_static_module)  HTTP_GZIP_STATIC=YES       ;;
         --with-http_random_index_module) HTTP_RANDOM_INDEX=YES      ;;
         --with-http_secure_link_module)  HTTP_SECURE_LINK=YES       ;;
+        --with-http_degradation_module)  HTTP_DEGRADATION=YES       ;;
 
         --without-http_charset_module)   HTTP_CHARSET=NO            ;;
         --without-http_gzip_module)      HTTP_GZIP=NO               ;;
@@ -205,10 +216,13 @@
         --without-http_status_module)    HTTP_STATUS=NO             ;;
         --without-http_geo_module)       HTTP_GEO=NO                ;;
         --without-http_map_module)       HTTP_MAP=NO                ;;
+        --without-http_split_clients_module) HTTP_SPLIT_CLIENTS=NO  ;;
         --without-http_referer_module)   HTTP_REFERER=NO            ;;
         --without-http_rewrite_module)   HTTP_REWRITE=NO            ;;
         --without-http_proxy_module)     HTTP_PROXY=NO              ;;
         --without-http_fastcgi_module)   HTTP_FASTCGI=NO            ;;
+        --without-http_uwsgi_module)     HTTP_UWSGI=NO              ;;
+        --without-http_scgi_module)      HTTP_SCGI=NO               ;;
         --without-http_memcached_module) HTTP_MEMCACHED=NO          ;;
         --without-http_limit_zone_module) HTTP_LIMIT_ZONE=NO        ;;
         --without-http_limit_req_module) HTTP_LIMIT_REQ=NO         ;;
@@ -264,6 +278,9 @@
         --with-zlib-opt=*)               ZLIB_OPT="$value"          ;;
         --with-zlib-asm=*)               ZLIB_ASM="$value"          ;;
 
+        --with-libatomic)                NGX_LIBATOMIC=YES          ;;
+        --with-libatomic=*)              NGX_LIBATOMIC="$value"     ;;
+
         --test-build-devpoll)            NGX_TEST_BUILD_DEVPOLL=YES ;;
         --test-build-eventport)          NGX_TEST_BUILD_EVENTPORT=YES ;;
         --test-build-epoll)              NGX_TEST_BUILD_EPOLL=YES   ;;
@@ -322,6 +339,7 @@
   --with-http_gzip_static_module     enable ngx_http_gzip_static_module
   --with-http_random_index_module    enable ngx_http_random_index_module
   --with-http_secure_link_module     enable ngx_http_secure_link_module
+  --with-http_degradation_module     enable ngx_http_degradation_module
   --with-http_stub_status_module     enable ngx_http_stub_status_module
 
   --without-http_charset_module      disable ngx_http_charset_module
@@ -333,10 +351,13 @@
   --without-http_autoindex_module    disable ngx_http_autoindex_module
   --without-http_geo_module          disable ngx_http_geo_module
   --without-http_map_module          disable ngx_http_map_module
+  --without-http_split_clients_module disable ngx_http_split_clients_module
   --without-http_referer_module      disable ngx_http_referer_module
   --without-http_rewrite_module      disable ngx_http_rewrite_module
   --without-http_proxy_module        disable ngx_http_proxy_module
   --without-http_fastcgi_module      disable ngx_http_fastcgi_module
+  --without-http_uwsgi_module        disable ngx_http_uwsgi_module
+  --without-http_scgi_module         disable ngx_http_scgi_module
   --without-http_memcached_module    disable ngx_http_memcached_module
   --without-http_limit_zone_module   disable ngx_http_limit_zone_module
   --without-http_limit_req_module    disable ngx_http_limit_req_module
@@ -355,6 +376,8 @@
   --http-proxy-temp-path=PATH        set path to the http proxy temporary files
   --http-fastcgi-temp-path=PATH      set path to the http fastcgi temporary
                                      files
+  --http-uwsgi-temp-path=PATH        set path to the http uwsgi temporary files
+  --http-scgi-temp-path=PATH         set path to the http scgi temporary files
 
   --without-http                     disable HTTP server
   --without-http-cache               disable HTTP cache
@@ -397,6 +420,9 @@
                                      for specified CPU, the valid values:
                                      pentium, pentiumpro
 
+  --with-libatomic                   force libatomic_ops library usage
+  --with-libatomic=DIR               set path to libatomic_ops library sources
+
   --with-openssl=DIR                 set path to OpenSSL library sources
   --with-openssl-opt=OPTIONS         set additional options for OpenSSL building
 
@@ -441,6 +467,8 @@
 NGX_HTTP_CLIENT_TEMP_PATH=${NGX_HTTP_CLIENT_TEMP_PATH:-client_body_temp}
 NGX_HTTP_PROXY_TEMP_PATH=${NGX_HTTP_PROXY_TEMP_PATH:-proxy_temp}
 NGX_HTTP_FASTCGI_TEMP_PATH=${NGX_HTTP_FASTCGI_TEMP_PATH:-fastcgi_temp}
+NGX_HTTP_UWSGI_TEMP_PATH=${NGX_HTTP_UWSGI_TEMP_PATH:-uwsgi_temp}
+NGX_HTTP_SCGI_TEMP_PATH=${NGX_HTTP_SCGI_TEMP_PATH:-scgi_temp}
 
 case ".$NGX_PERL_MODULES" in
     ./*)
--- a/auto/os/features	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/os/features	Mon Apr 25 04:22:17 2011 +0400
@@ -172,6 +172,26 @@
 fi
 
 
+ngx_feature="F_READAHEAD"
+ngx_feature_name="NGX_HAVE_F_READAHEAD"
+ngx_feature_run=no
+ngx_feature_incs="#include <fcntl.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="fcntl(0, F_READAHEAD, 1);"
+. auto/feature
+
+
+ngx_feature="posix_fadvise()"
+ngx_feature_name="NGX_HAVE_POSIX_FADVISE"
+ngx_feature_run=no
+ngx_feature_incs="#include <fcntl.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="posix_fadvise(0, 0, 0, POSIX_FADV_SEQUENTIAL);"
+. auto/feature
+
+
 ngx_feature="O_DIRECT"
 ngx_feature_name="NGX_HAVE_O_DIRECT"
 ngx_feature_run=no
@@ -275,6 +295,24 @@
     fi
 fi
 
+ngx_feature="SO_SETFIB"
+ngx_feature_name="NGX_HAVE_SETFIB"
+ngx_feature_run=no
+ngx_feature_incs="#include <sys/socket.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="setsockopt(0, SOL_SOCKET, SO_SETFIB, NULL, 4)"
+. auto/feature
+
+
+ngx_feature="accept4()"
+ngx_feature_name="NGX_HAVE_ACCEPT4"
+ngx_feature_run=no
+ngx_feature_incs="#include <sys/socket.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="accept4(0, NULL, NULL, SOCK_NONBLOCK)"
+. auto/feature
 
 if [ $NGX_FILE_AIO = YES ]; then
 
--- a/auto/os/linux	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/os/linux	Mon Apr 25 04:22:17 2011 +0400
@@ -35,6 +35,12 @@
 fi
 
 
+# posix_fadvise64() had been implemented in 2.5.60
+
+if [ $version -lt 132412 ]; then
+    have=NGX_HAVE_POSIX_FADVISE . auto/nohave
+fi
+
 # epoll, EPOLLET version
 
 ngx_feature="epoll"
--- a/auto/sources	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/sources	Mon Apr 25 04:22:17 2011 +0400
@@ -387,6 +387,10 @@
 HTTP_MAP_SRCS=src/http/modules/ngx_http_map_module.c
 
 
+HTTP_SPLIT_CLIENTS_MODULE=ngx_http_split_clients_module
+HTTP_SPLIT_CLIENTS_SRCS=src/http/modules/ngx_http_split_clients_module.c
+
+
 HTTP_REFERER_MODULE=ngx_http_referer_module
 HTTP_REFERER_SRCS=src/http/modules/ngx_http_referer_module.c
 
@@ -408,6 +412,14 @@
 HTTP_FASTCGI_SRCS=src/http/modules/ngx_http_fastcgi_module.c
 
 
+HTTP_UWSGI_MODULE=ngx_http_uwsgi_module
+HTTP_UWSGI_SRCS=src/http/modules/ngx_http_uwsgi_module.c
+
+
+HTTP_SCGI_MODULE=ngx_http_scgi_module
+HTTP_SCGI_SRCS=src/http/modules/ngx_http_scgi_module.c
+
+
 HTTP_PERL_MODULE=ngx_http_perl_module
 HTTP_PERL_INCS=src/http/modules/perl
 HTTP_PERL_DEPS=src/http/modules/perl/ngx_http_perl_module.h
@@ -438,6 +450,10 @@
 HTTP_SECURE_LINK_SRCS=src/http/modules/ngx_http_secure_link_module.c
 
 
+HTTP_DEGRADATION_MODULE=ngx_http_degradation_module
+HTTP_DEGRADATION_SRCS=src/http/modules/ngx_http_degradation_module.c
+
+
 HTTP_FLV_MODULE=ngx_http_flv_module
 HTTP_FLV_SRCS=src/http/modules/ngx_http_flv_module.c
 
--- a/auto/summary	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/summary	Mon Apr 25 04:22:17 2011 +0400
@@ -38,7 +38,6 @@
     case $PCRE in
         YES)   echo "  + using system PCRE library" ;;
         NONE)  echo "  + PCRE library is not used" ;;
-        NO)    echo "  + PCRE library is not found" ;;
         *)     echo "  + using PCRE library: $PCRE" ;;
     esac
 fi
@@ -46,14 +45,12 @@
 case $OPENSSL in
     YES)   echo "  + using system OpenSSL library" ;;
     NONE)  echo "  + OpenSSL library is not used" ;;
-    NO)    echo "  + OpenSSL library is not found" ;;
     *)     echo "  + using OpenSSL library: $OPENSSL" ;;
 esac
 
 case $MD5 in
     YES)   echo "  + md5: using $MD5_LIB library" ;;
     NONE)  echo "  + md5 library is not used" ;;
-    NO)    echo "  + md5 library is not found" ;;
     *)     echo "  + using md5 library: $MD5" ;;
 esac
 
@@ -67,10 +64,15 @@
 case $ZLIB in
     YES)   echo "  + using system zlib library" ;;
     NONE)  echo "  + zlib library is not used" ;;
-    NO)    echo "  + zlib library is not found" ;;
     *)     echo "  + using zlib library: $ZLIB" ;;
 esac
 
+case $NGX_LIBATOMIC in
+    YES)   echo "  + using system libatomic_ops library" ;;
+    NO)    ;; # not used
+    *)     echo "  + using libatomic_ops library: $NGX_LIBATOMIC" ;;
+esac
+
 echo
 
 
@@ -91,7 +93,20 @@
 cat << END
   nginx http access log file: "$NGX_HTTP_LOG_PATH"
   nginx http client request body temporary files: "$NGX_HTTP_CLIENT_TEMP_PATH"
-  nginx http proxy temporary files: "$NGX_HTTP_PROXY_TEMP_PATH"
-  nginx http fastcgi temporary files: "$NGX_HTTP_FASTCGI_TEMP_PATH"
+END
+
+if [ $HTTP_PROXY = YES ]; then
+    echo "  nginx http proxy temporary files: \"$NGX_HTTP_PROXY_TEMP_PATH\""
+fi
 
-END
+if [ $HTTP_FASTCGI = YES ]; then
+    echo "  nginx http fastcgi temporary files: \"$NGX_HTTP_FASTCGI_TEMP_PATH\""
+fi
+
+if [ $HTTP_UWSGI = YES ]; then
+    echo "  nginx http uwsgi temporary files: \"$NGX_HTTP_UWSGI_TEMP_PATH\""
+fi
+
+if [ $HTTP_SCGI = YES ]; then
+    echo "  nginx http scgi temporary files: \"$NGX_HTTP_SCGI_TEMP_PATH\""
+fi
--- a/auto/unix	Sun Sep 27 01:10:42 2009 +0400
+++ b/auto/unix	Mon Apr 25 04:22:17 2011 +0400
@@ -109,28 +109,52 @@
 . auto/feature
 
 
-ngx_feature="strerror_r()"
-ngx_feature_name="NGX_HAVE_STRERROR_R"
-ngx_feature_run=yes
-ngx_feature_incs="#include <string.h>"
+ngx_feature="sys_nerr"
+ngx_feature_name="NGX_SYS_NERR"
+ngx_feature_run=value
+ngx_feature_incs='#include <stdio.h>'
 ngx_feature_path=
 ngx_feature_libs=
-ngx_feature_test="char buf[1024]; long n; n = strerror_r(1, buf, 1024);
-                  if (n < 0 || n > 1024) return 1;"
+ngx_feature_test='printf("%d", sys_nerr);'
 . auto/feature
 
 
-# GNU style strerror_r() returns not length, but pointer
+if [ $ngx_found = no ]; then
+
+    # Cygiwn defines _sys_nerr
+    ngx_feature="_sys_nerr"
+    ngx_feature_name="NGX_SYS_NERR"
+    ngx_feature_run=value
+    ngx_feature_incs='#include <errno.h>
+                      #include <stdio.h>'
+    ngx_feature_path=
+    ngx_feature_libs=
+    ngx_feature_test='printf("%d", _sys_nerr);'
+    . auto/feature
+fi
+
+
+if [ $ngx_found = no ]; then
 
-ngx_feature="gnu style strerror_r()"
-ngx_feature_name="NGX_HAVE_GNU_STRERROR_R"
-ngx_feature_run=yes
-ngx_feature_incs="#include <string.h>"
-ngx_feature_path=
-ngx_feature_libs=
-ngx_feature_test="char buf[1024]; long n; n = strerror_r(1, buf, 1024);
-                  if (n >= 0 && n < 1024) return 1;"
-. auto/feature
+    # Solaris has no sys_nerr
+    ngx_feature='maximum errno'
+    ngx_feature_name=NGX_SYS_NERR
+    ngx_feature_run=value
+    ngx_feature_incs='#include <errno.h>
+                      #include <stdio.h>'
+    ngx_feature_path=
+    ngx_feature_libs=
+    ngx_feature_test='int  n;
+                      for (n = 1; n < 1000; n++) {
+                          errno = 0;
+                          strerror(n);
+                          if (errno == EINVAL) {
+                              printf("%d", n);
+                              return 0;
+                          }
+                     }'
+    . auto/feature
+fi
 
 
 ngx_feature="localtime_r()"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/conf/fastcgi.conf	Mon Apr 25 04:22:17 2011 +0400
@@ -0,0 +1,24 @@
+
+fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
+fastcgi_param  QUERY_STRING       $query_string;
+fastcgi_param  REQUEST_METHOD     $request_method;
+fastcgi_param  CONTENT_TYPE       $content_type;
+fastcgi_param  CONTENT_LENGTH     $content_length;
+
+fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
+fastcgi_param  REQUEST_URI        $request_uri;
+fastcgi_param  DOCUMENT_URI       $document_uri;
+fastcgi_param  DOCUMENT_ROOT      $document_root;
+fastcgi_param  SERVER_PROTOCOL    $server_protocol;
+
+fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
+fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;
+
+fastcgi_param  REMOTE_ADDR        $remote_addr;
+fastcgi_param  REMOTE_PORT        $remote_port;
+fastcgi_param  SERVER_ADDR        $server_addr;
+fastcgi_param  SERVER_PORT        $server_port;
+fastcgi_param  SERVER_NAME        $server_name;
+
+# PHP only, required if PHP was built with --enable-force-cgi-redirect
+fastcgi_param  REDIRECT_STATUS    200;
--- a/conf/mime.types	Sun Sep 27 01:10:42 2009 +0400
+++ b/conf/mime.types	Mon Apr 25 04:22:17 2011 +0400
@@ -32,9 +32,9 @@
     application/vnd.ms-excel              xls;
     application/vnd.ms-powerpoint         ppt;
     application/vnd.wap.wmlc              wmlc;
-    application/vnd.wap.xhtml+xml         xhtml;
     application/vnd.google-earth.kml+xml  kml;
     application/vnd.google-earth.kmz      kmz;
+    application/x-7z-compressed           7z;
     application/x-cocoa                   cco;
     application/x-java-archive-diff       jardiff;
     application/x-java-jnlp-file          jnlp;
@@ -49,6 +49,7 @@
     application/x-tcl                     tcl tk;
     application/x-x509-ca-cert            der pem crt;
     application/x-xpinstall               xpi;
+    application/xhtml+xml                 xhtml;
     application/zip                       zip;
 
     application/octet-stream              bin exe dll;
@@ -60,6 +61,7 @@
 
     audio/midi                            mid midi kar;
     audio/mpeg                            mp3;
+    audio/ogg                             ogg;
     audio/x-realaudio                     ra;
 
     video/3gpp                            3gpp 3gp;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/conf/scgi_params	Mon Apr 25 04:22:17 2011 +0400
@@ -0,0 +1,15 @@
+
+scgi_param  REQUEST_METHOD     $request_method;
+scgi_param  REQUEST_URI        $request_uri;
+scgi_param  QUERY_STRING       $query_string;
+scgi_param  CONTENT_TYPE       $content_type;
+
+scgi_param  DOCUMENT_URI       $document_uri;
+scgi_param  DOCUMENT_ROOT      $document_root;
+scgi_param  SCGI               1;
+scgi_param  SERVER_PROTOCOL    $server_protocol;
+
+scgi_param  REMOTE_ADDR        $remote_addr;
+scgi_param  REMOTE_PORT        $remote_port;
+scgi_param  SERVER_PORT        $server_port;
+scgi_param  SERVER_NAME        $server_name;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/conf/uwsgi_params	Mon Apr 25 04:22:17 2011 +0400
@@ -0,0 +1,15 @@
+
+uwsgi_param  QUERY_STRING       $query_string;
+uwsgi_param  REQUEST_METHOD     $request_method;
+uwsgi_param  CONTENT_TYPE       $content_type;
+uwsgi_param  CONTENT_LENGTH     $content_length;
+
+uwsgi_param  REQUEST_URI        $request_uri;
+uwsgi_param  PATH_INFO          $document_uri;
+uwsgi_param  DOCUMENT_ROOT      $document_root;
+uwsgi_param  SERVER_PROTOCOL    $server_protocol;
+
+uwsgi_param  REMOTE_ADDR        $remote_addr;
+uwsgi_param  REMOTE_PORT        $remote_port;
+uwsgi_param  SERVER_PORT        $server_port;
+uwsgi_param  SERVER_NAME        $server_name;
--- a/configure	Sun Sep 27 01:10:42 2009 +0400
+++ b/configure	Mon Apr 25 04:22:17 2011 +0400
@@ -90,6 +90,10 @@
 . auto/define
 have=NGX_HTTP_FASTCGI_TEMP_PATH value="\"$NGX_HTTP_FASTCGI_TEMP_PATH\""
 . auto/define
+have=NGX_HTTP_UWSGI_TEMP_PATH value="\"$NGX_HTTP_UWSGI_TEMP_PATH\""
+. auto/define
+have=NGX_HTTP_SCGI_TEMP_PATH value="\"$NGX_HTTP_SCGI_TEMP_PATH\""
+. auto/define
 
 . auto/make
 . auto/lib/make
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/nginx.8	Mon Apr 25 04:22:17 2011 +0400
@@ -0,0 +1,201 @@
+.\"
+.\" Copyright (c) 2010 Sergey A. Osokin
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"
+.Dd November 14, 2010
+.Dt NGINX 8
+.Os
+.Sh NAME
+.Nm nginx
+.Nd "HTTP and reverse proxy server, mail proxy server"
+.Sh SYNOPSIS
+.Nm
+.Op Fl hqtvV?
+.Op Fl c Ar file
+.Op Fl g Ar directives
+.Op Fl p Ar prefix
+.Op Fl s Ar signal
+.Sh DESCRIPTION
+The
+.Nm
+(spelled
+.Dq engine x )
+is an HTTP and reverse proxy server, as well as a mail proxy server.
+The
+.Nm
+is known for its high performance, stability, rich feature set, simple
+configuration, and low resource consumption.
+.Pp
+The options are as follows:
+.Bl -tag -width ".Fl d Ar directives"
+.It Fl ?\& | h
+Print help.
+.It Fl c Ar file
+Use an alternative configuration
+.Ar file .
+.It Fl g Ar directives
+Set global configuration directives.
+See
+.Sx EXAMPLES
+for details.
+.It Fl p Ar prefix
+Set prefix path.
+Default value is
+.Pa %%PREFIX%% .
+.It Fl q
+Suppress non-error messages during configuration testing.
+.It Fl s Ar signal
+Send signal to the master process.
+The argument
+.Ar signal
+can be one of:
+.Cm stop , quit , reopen , reload .
+The following table shows the corresponding system signals.
+.Pp
+.Bl -tag -width ".It Cm reopen" -compact
+.It Cm stop
+.Dv SIGTERM
+.It Cm quit
+.Dv SIGQUIT
+.It Cm reopen
+.Dv SIGUSR1
+.It Cm reload
+.Dv SIGHUP
+.El
+.It Fl t
+Don't run, just test the configuration file.
+The
+.Nm
+checks configuration for correct syntax and then tries to open files
+referred in configuration.
+.It Fl v
+Print
+.Nm
+version.
+.It Fl V
+Print
+.Nm
+version, compiler version and
+.Pa configure
+script parameters.
+.El
+.Sh SIGNALS
+The master process of
+.Nm
+can handle the following signals.
+.Pp
+.Bl -tag -width ".It Dv SIGINT , SIGTERM" -compact
+.It Dv SIGINT , SIGTERM
+Shut down quickly.
+.It Dv SIGHUP
+Reload configuration, start the new worker process with a new
+configuration, gracefully shut down old worker processes.
+.It Dv SIGQUIT
+Shut down gracefully.
+.It Dv SIGUSR1
+Reopen log files.
+.It Dv SIGUSR2
+Upgrade
+.Nm
+executable on the fly.
+.It Dv SIGWINCH
+Shut down gracefully worker processes.
+.El
+.Pp
+While there's no need to explicitly control worker processes normally,
+they support some signals, too:
+.Pp
+.Bl -tag -width ".It Dv SIGINT , SIGTERM" -compact
+.It Dv SIGTERM
+Shut down quickly.
+.It Dv SIGQUIT
+Shut down gracefully.
+.It Dv SIGUSR1
+Reopen log files.
+.El
+.Sh DEBUGGING LOG
+To enable a debugging log, reconfigure
+.Nm
+to build with debugging:
+.Pp
+.Dl "./configure --with-debug ..."
+.Pp
+and then set the
+.Cm debug
+level of the
+.Va error_log :
+.Pp
+.Dl "error_log /path/to/log debug;"
+.Pp
+It is also possible to enable the debugging for some IP address:
+.Bd -literal -offset indent
+events {
+	debug_connection 127.0.0.1;
+}
+.Ed
+.Sh FILES
+.Bl -tag -width indent -compact
+.It Pa %%PID_PATH%%
+Contains the process ID of the
+.Nm
+listening for connections.
+The content of this file is not sensitive; it can be world-readable.
+.It Pa %%CONF_PATH%%
+Main configuration file.
+.It Pa %%ERROR_LOG_PATH%%
+Error log file.
+.El
+.Sh EXIT STATUS
+Exit status is 0 on success, or 1 if the command fails.
+.Sh EXAMPLES
+.Bd -literal
+nginx -t -c ~/mynginx.conf -g "pid /var/run/mynginx.pid; worker_processes 2;"
+.Ed
+Test configuration file
+.Pa ~/mynginx.conf
+with global directives for PID and quantity of worker processes.
+.Sh SEE ALSO
+.Xr nginx.conf 5
+.Sh HISTORY
+Development of
+.Nm
+started in 2002, with the first public release on October 4, 2004.
+.Sh AUTHORS
+.An Igor Sysoev Aq igor@sysoev.ru
+.Pp
+Documentation available on
+.Pa http://nginx.org/
+and
+.Pa http://sysoev.ru/nginx/ .
+.Pp
+This manual page was written by
+.An Sergey A. Osokin Aq osa@FreeBSD.org.ru
+as a result of compilation of many
+.Nm
+documents all over the world.
+.Sh BUGS
+Report to mailing list
+.Aq Li nginx@nginx.org
+if you found one.
--- a/src/core/nginx.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/nginx.c	Mon Apr 25 04:22:17 2011 +0400
@@ -110,7 +110,7 @@
 
     { ngx_string("worker_rlimit_core"),
       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_size_slot,
+      ngx_conf_set_off_slot,
       0,
       offsetof(ngx_core_conf_t, rlimit_core),
       NULL },
@@ -203,6 +203,10 @@
     ngx_cycle_t      *cycle, init_cycle;
     ngx_core_conf_t  *ccf;
 
+    if (ngx_strerror_init() != NGX_OK) {
+        return 1;
+    }
+
     if (ngx_get_options(argc, argv) != NGX_OK) {
         return 1;
     }
@@ -212,7 +216,7 @@
 
         if (ngx_show_help) {
             ngx_log_stderr(0,
-                "Usage: nginx [-?hvVt] [-s signal] [-c filename] "
+                "Usage: nginx [-?hvVtq] [-s signal] [-c filename] "
                              "[-p prefix] [-g directives]" CRLF CRLF
                 "Options:" CRLF
                 "  -?,-h         : this help" CRLF
@@ -220,6 +224,8 @@
                 "  -V            : show version and configure options then exit"
                                    CRLF
                 "  -t            : test configuration and exit" CRLF
+                "  -q            : suppress non-error messages "
+                                   "during configuration testing" CRLF
                 "  -s signal     : send signal to a master process: "
                                    "stop, quit, reopen, reload" CRLF
 #ifdef NGX_PREFIX
@@ -239,6 +245,13 @@
 #ifdef NGX_COMPILER
             ngx_log_stderr(0, "built by " NGX_COMPILER);
 #endif
+#if (NGX_SSL)
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+            ngx_log_stderr(0, "TLS SNI support enabled");
+#else
+            ngx_log_stderr(0, "TLS SNI support disabled");
+#endif
+#endif
             ngx_log_stderr(0, "configure arguments:" NGX_CONFIGURE);
         }
 
@@ -325,8 +338,11 @@
     }
 
     if (ngx_test_config) {
-        ngx_log_stderr(0, "configuration file %s test is successful",
-                       cycle->conf_file.data);
+        if (!ngx_quiet_mode) {
+            ngx_log_stderr(0, "configuration file %s test is successful",
+                           cycle->conf_file.data);
+        }
+
         return 0;
     }
 
@@ -373,6 +389,13 @@
         }
     }
 
+    if (log->file->fd != ngx_stderr) {
+        if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) {
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                          ngx_close_file_n " built-in log failed");
+        }
+    }
+
     ngx_use_stderr = 0;
 
     if (ngx_process == NGX_PROCESS_SINGLE) {
@@ -671,6 +694,10 @@
                 ngx_test_config = 1;
                 break;
 
+            case 'q':
+                ngx_quiet_mode = 1;
+                break;
+
             case 'p':
                 if (*p) {
                     ngx_prefix = p;
@@ -845,14 +872,11 @@
 #else
 
 #ifdef NGX_CONF_PREFIX
-        cycle->conf_prefix.len = sizeof(NGX_CONF_PREFIX) - 1;
-        cycle->conf_prefix.data = (u_char *) NGX_CONF_PREFIX;
+        ngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX);
 #else
-        cycle->conf_prefix.len = sizeof(NGX_PREFIX) - 1;
-        cycle->conf_prefix.data = (u_char *) NGX_PREFIX;
+        ngx_str_set(&cycle->conf_prefix, NGX_PREFIX);
 #endif
-        cycle->prefix.len = sizeof(NGX_PREFIX) - 1;
-        cycle->prefix.data = (u_char *) NGX_PREFIX;
+        ngx_str_set(&cycle->prefix, NGX_PREFIX);
 
 #endif
     }
@@ -862,8 +886,7 @@
         cycle->conf_file.data = ngx_conf_file;
 
     } else {
-        cycle->conf_file.len = sizeof(NGX_CONF_PATH) - 1;
-        cycle->conf_file.data = (u_char *) NGX_CONF_PATH;
+        ngx_str_set(&cycle->conf_file, NGX_CONF_PATH);
     }
 
     if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) {
@@ -905,7 +928,7 @@
     }
 
     /*
-     * set by pcalloc()
+     * set by ngx_pcalloc()
      *
      *     ccf->pid = NULL;
      *     ccf->oldpid = NULL;
@@ -922,7 +945,7 @@
     ccf->debug_points = NGX_CONF_UNSET;
 
     ccf->rlimit_nofile = NGX_CONF_UNSET;
-    ccf->rlimit_core = NGX_CONF_UNSET_SIZE;
+    ccf->rlimit_core = NGX_CONF_UNSET;
     ccf->rlimit_sigpending = NGX_CONF_UNSET;
 
     ccf->user = (ngx_uid_t) NGX_CONF_UNSET_UINT;
@@ -979,8 +1002,7 @@
 
 
     if (ccf->pid.len == 0) {
-        ccf->pid.len = sizeof(NGX_PID_PATH) - 1;
-        ccf->pid.data = (u_char *) NGX_PID_PATH;
+        ngx_str_set(&ccf->pid, NGX_PID_PATH);
     }
 
     if (ngx_conf_full_name(cycle, &ccf->pid, 0) != NGX_OK) {
@@ -1028,8 +1050,7 @@
 
 
     if (ccf->lock_file.len == 0) {
-        ccf->lock_file.len = sizeof(NGX_LOCK_PATH) - 1;
-        ccf->lock_file.data = (u_char *) NGX_LOCK_PATH;
+        ngx_str_set(&ccf->lock_file, NGX_LOCK_PATH);
     }
 
     if (ngx_conf_full_name(cycle, &ccf->lock_file, 0) != NGX_OK) {
--- a/src/core/nginx.h	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/nginx.h	Mon Apr 25 04:22:17 2011 +0400
@@ -8,8 +8,8 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define nginx_version         8016
-#define NGINX_VERSION      "0.8.16"
+#define nginx_version      1000000
+#define NGINX_VERSION      "1.0.0"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_conf_file.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_conf_file.c	Mon Apr 25 04:22:17 2011 +0400
@@ -261,7 +261,7 @@
         if (ngx_close_file(fd) == NGX_FILE_ERROR) {
             ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
                           ngx_close_file_n " %s failed",
-                          cf->conf_file->file.name.data);
+                          filename->data);
             return NGX_CONF_ERROR;
         }
 
@@ -507,7 +507,7 @@
             }
 
             if (len) {
-                ngx_memcpy(b->start, start, len);
+                ngx_memmove(b->start, start, len);
             }
 
             size = (ssize_t) (file_size - cf->conf_file->file.offset);
@@ -671,7 +671,8 @@
                 }
 
             } else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF
-                       || ch == ';' || ch == '{') {
+                       || ch == ';' || ch == '{')
+            {
                 last_space = 1;
                 found = 1;
             }
@@ -903,8 +904,7 @@
     ngx_open_file_t  *file;
 
 #if (NGX_SUPPRESS_WARN)
-    full.len = 0;
-    full.data = NULL;
+    ngx_str_null(&full);
 #endif
 
     if (name->len) {
@@ -1006,7 +1006,7 @@
 
 void ngx_cdecl
 ngx_conf_log_error(ngx_uint_t level, ngx_conf_t *cf, ngx_err_t err,
-    char *fmt, ...)
+    const char *fmt, ...)
 {
     u_char   errstr[NGX_MAX_CONF_ERRSTR], *p, *last;
     va_list  args;
--- a/src/core/ngx_conf_file.h	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_conf_file.h	Mon Apr 25 04:22:17 2011 +0400
@@ -322,7 +322,7 @@
     ngx_uint_t conf_prefix);
 ngx_open_file_t *ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name);
 void ngx_cdecl ngx_conf_log_error(ngx_uint_t level, ngx_conf_t *cf,
-    ngx_err_t err, char *fmt, ...);
+    ngx_err_t err, const char *fmt, ...);
 
 
 char *ngx_conf_set_flag_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
--- a/src/core/ngx_connection.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_connection.c	Mon Apr 25 04:22:17 2011 +0400
@@ -12,9 +12,13 @@
 ngx_os_io_t  ngx_io;
 
 
+static void ngx_drain_connections(void);
+
+
 ngx_listening_t *
 ngx_create_listening(ngx_conf_t *cf, void *sockaddr, socklen_t socklen)
 {
+    size_t            len;
     ngx_listening_t  *ls;
     struct sockaddr  *sa;
     u_char            text[NGX_SOCKADDR_STRLEN];
@@ -36,17 +40,8 @@
     ls->sockaddr = sa;
     ls->socklen = socklen;
 
-    ls->addr_text.len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1);
-
-    ls->addr_text.data = ngx_pnalloc(cf->pool, ls->addr_text.len);
-    if (ls->addr_text.data == NULL) {
-        return NULL;
-    }
-
-    ngx_memcpy(ls->addr_text.data, text, ls->addr_text.len);
-
-    ls->fd = (ngx_socket_t) -1;
-    ls->type = SOCK_STREAM;
+    len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1);
+    ls->addr_text.len = len;
 
     switch (ls->sockaddr->sa_family) {
 #if (NGX_HAVE_INET6)
@@ -54,6 +49,12 @@
          ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN;
          break;
 #endif
+#if (NGX_HAVE_UNIX_DOMAIN)
+    case AF_UNIX:
+         ls->addr_text_max_len = NGX_UNIX_ADDRSTRLEN;
+         len++;
+         break;
+#endif
     case AF_INET:
          ls->addr_text_max_len = NGX_INET_ADDRSTRLEN;
          break;
@@ -62,10 +63,24 @@
          break;
     }
 
+    ls->addr_text.data = ngx_pnalloc(cf->pool, len);
+    if (ls->addr_text.data == NULL) {
+        return NULL;
+    }
+
+    ngx_memcpy(ls->addr_text.data, text, len);
+
+    ls->fd = (ngx_socket_t) -1;
+    ls->type = SOCK_STREAM;
+
     ls->backlog = NGX_LISTEN_BACKLOG;
     ls->rcvbuf = -1;
     ls->sndbuf = -1;
 
+#if (NGX_HAVE_SETFIB)
+    ls->setfib = -1;
+#endif
+
     return ls;
 }
 
@@ -88,14 +103,12 @@
     ls = cycle->listening.elts;
     for (i = 0; i < cycle->listening.nelts; i++) {
 
-        /* AF_INET only */
-
-        ls[i].sockaddr = ngx_palloc(cycle->pool, sizeof(struct sockaddr_in));
+        ls[i].sockaddr = ngx_palloc(cycle->pool, NGX_SOCKADDRLEN);
         if (ls[i].sockaddr == NULL) {
             return NGX_ERROR;
         }
 
-        ls[i].socklen = sizeof(struct sockaddr_in);
+        ls[i].socklen = NGX_SOCKADDRLEN;
         if (getsockname(ls[i].fd, ls[i].sockaddr, &ls[i].socklen) == -1) {
             ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno,
                           "getsockname() of the inherited "
@@ -109,11 +122,20 @@
 #if (NGX_HAVE_INET6)
         case AF_INET6:
              ls[i].addr_text_max_len = NGX_INET6_ADDRSTRLEN;
+             len = NGX_INET6_ADDRSTRLEN + sizeof(":65535") - 1;
+             break;
+#endif
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+        case AF_UNIX:
+             ls[i].addr_text_max_len = NGX_UNIX_ADDRSTRLEN;
+             len = NGX_UNIX_ADDRSTRLEN;
              break;
 #endif
 
         case AF_INET:
              ls[i].addr_text_max_len = NGX_INET_ADDRSTRLEN;
+             len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
              break;
 
         default:
@@ -124,8 +146,6 @@
             continue;
         }
 
-        len = ls[i].addr_text_max_len + sizeof(":65535") - 1;
-
         ls[i].addr_text.data = ngx_pnalloc(cycle->pool, len);
         if (ls[i].addr_text.data == NULL) {
             return NGX_ERROR;
@@ -166,6 +186,25 @@
             ls[i].sndbuf = -1;
         }
 
+#if 0
+        /* SO_SETFIB is currently a set only option */
+
+#if (NGX_HAVE_SETFIB)
+
+        if (getsockopt(ls[i].setfib, SOL_SOCKET, SO_SETFIB,
+                       (void *) &ls[i].setfib, &olen)
+            == -1)
+        {
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+                          "getsockopt(SO_SETFIB) %V failed, ignored",
+                          &ls[i].addr_text);
+
+            ls[i].setfib = -1;
+        }
+
+#endif
+#endif
+
 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
 
         ngx_memzero(&af, sizeof(struct accept_filter_arg));
@@ -357,6 +396,29 @@
                 continue;
             }
 
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+            if (ls[i].sockaddr->sa_family == AF_UNIX) {
+                mode_t   mode;
+                u_char  *name;
+
+                name = ls[i].addr_text.data + sizeof("unix:") - 1;
+                mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+
+                if (chmod((char *) name, mode) == -1) {
+                    ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
+                                  "chmod() \"%s\" failed", name);
+                }
+
+                if (ngx_test_config) {
+                    if (ngx_delete_file(name) == -1) {
+                        ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
+                                      ngx_delete_file_n " %s failed", name);
+                    }
+                }
+            }
+#endif
+
             if (listen(s, ls[i].backlog) == -1) {
                 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
                               "listen() to %V, backlog %d failed",
@@ -437,6 +499,19 @@
             }
         }
 
+#if (NGX_HAVE_SETFIB)
+        if (ls[i].setfib != -1) {
+            if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SETFIB,
+                           (const void *) &ls[i].setfib, sizeof(int))
+                == -1)
+            {
+                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+                              "setsockopt(SO_SETFIB, %d) %V failed, ignored",
+                              ls[i].setfib, &ls[i].addr_text);
+            }
+        }
+#endif
+
 #if 0
         if (1) {
             int tcp_nodelay = 1;
@@ -604,6 +679,22 @@
                           ngx_close_socket_n " %V failed", &ls[i].addr_text);
         }
 
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+        if (ls[i].sockaddr->sa_family == AF_UNIX
+            && ngx_process <= NGX_PROCESS_MASTER
+            && ngx_new_binary == 0)
+        {
+            u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1;
+
+            if (ngx_delete_file(name) == -1) {
+                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
+                              ngx_delete_file_n " %s failed", name);
+            }
+        }
+
+#endif
+
         ls[i].fd = (ngx_socket_t) -1;
     }
 }
@@ -631,6 +722,11 @@
     c = ngx_cycle->free_connections;
 
     if (c == NULL) {
+        ngx_drain_connections();
+        c = ngx_cycle->free_connections;
+    }
+
+    if (c == NULL) {
         ngx_log_error(NGX_LOG_ALERT, log, 0,
                       "%ui worker_connections are not enough",
                       ngx_cycle->connection_n);
@@ -773,6 +869,8 @@
 
 #endif
 
+    ngx_reusable_connection(c, 0);
+
     log_error = c->log_error;
 
     ngx_free_connection(c);
@@ -812,6 +910,51 @@
 }
 
 
+void
+ngx_reusable_connection(ngx_connection_t *c, ngx_uint_t reusable)
+{
+    ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
+                   "reusable connection: %ui", reusable);
+
+    if (c->reusable) {
+        ngx_queue_remove(&c->queue);
+    }
+
+    c->reusable = reusable;
+
+    if (reusable) {
+        /* need cast as ngx_cycle is volatile */
+
+        ngx_queue_insert_head(
+            (ngx_queue_t *) &ngx_cycle->reusable_connections_queue, &c->queue);
+    }
+}
+
+
+static void
+ngx_drain_connections(void)
+{
+    ngx_int_t          i;
+    ngx_queue_t       *q;
+    ngx_connection_t  *c;
+
+    for (i = 0; i < 32; i++) {
+        if (ngx_queue_empty(&ngx_cycle->reusable_connections_queue)) {
+            break;
+        }
+
+        q = ngx_queue_last(&ngx_cycle->reusable_connections_queue);
+        c = ngx_queue_data(q, ngx_connection_t, queue);
+
+        ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0,
+                       "reusing connection");
+
+        c->close = 1;
+        c->read->handler(c->read);
+    }
+}
+
+
 ngx_int_t
 ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s,
     ngx_uint_t port)
@@ -858,7 +1001,6 @@
             return NGX_ERROR;
         }
 
-        c->local_socklen = len;
         ngx_memcpy(c->local_sockaddr, &sa, len);
     }
 
@@ -917,12 +1059,8 @@
             level = NGX_LOG_INFO;
             break;
 
-        case NGX_ERROR_ERR:
+        default:
             level = NGX_LOG_ERR;
-            break;
-
-        default:
-            level = NGX_LOG_ALERT;
         }
 
     } else {
--- a/src/core/ngx_connection.h	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_connection.h	Mon Apr 25 04:22:17 2011 +0400
@@ -69,6 +69,9 @@
     char               *accept_filter;
 #endif
 #endif
+#if (NGX_HAVE_SETFIB)
+    int                 setfib;
+#endif
 
 };
 
@@ -129,10 +132,11 @@
 #endif
 
     struct sockaddr    *local_sockaddr;
-    socklen_t           local_socklen;
 
     ngx_buf_t          *buffer;
 
+    ngx_queue_t         queue;
+
     ngx_atomic_uint_t   number;
 
     ngx_uint_t          requests;
@@ -148,6 +152,7 @@
     unsigned            destroyed:1;
 
     unsigned            idle:1;
+    unsigned            reusable:1;
     unsigned            close:1;
 
     unsigned            sendfile:1;
@@ -184,5 +189,6 @@
 ngx_connection_t *ngx_get_connection(ngx_socket_t s, ngx_log_t *log);
 void ngx_free_connection(ngx_connection_t *c);
 
+void ngx_reusable_connection(ngx_connection_t *c, ngx_uint_t reusable);
 
 #endif /* _NGX_CONNECTION_H_INCLUDED_ */
--- a/src/core/ngx_core.h	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_core.h	Mon Apr 25 04:22:17 2011 +0400
@@ -83,7 +83,9 @@
 #define CRLF   "\x0d\x0a"
 
 
-#define ngx_abs(value)   (((value) >= 0) ? (value) : - (value))
+#define ngx_abs(value)       (((value) >= 0) ? (value) : - (value))
+#define ngx_max(val1, val2)  ((val1 < val2) ? (val2) : (val1))
+#define ngx_min(val1, val2)  ((val1 > val2) ? (val2) : (val1))
 
 void ngx_cpuinfo(void);
 
--- a/src/core/ngx_cycle.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_cycle.c	Mon Apr 25 04:22:17 2011 +0400
@@ -24,6 +24,7 @@
 static ngx_event_t     ngx_cleaner_event;
 
 ngx_uint_t             ngx_test_config;
+ngx_uint_t             ngx_quiet_mode;
 
 #if (NGX_THREADS)
 ngx_tls_key_t          ngx_core_tls_key;
@@ -63,7 +64,7 @@
     tp = ngx_timeofday();
     tp->sec = 0;
 
-    ngx_time_update(0, 0);
+    ngx_time_update();
 
 
     log = old_cycle->log;
@@ -180,6 +181,9 @@
     cycle->listening.pool = pool;
 
 
+    ngx_queue_init(&cycle->reusable_connections_queue);
+
+
     cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *));
     if (cycle->conf_ctx == NULL) {
         ngx_destroy_pool(pool);
@@ -204,7 +208,7 @@
         return NULL;
     }
 
-    ngx_memcpy(cycle->hostname.data, hostname, cycle->hostname.len);
+    ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len);
 
 
     for (i = 0; ngx_modules[i]; i++) {
@@ -266,7 +270,7 @@
         return NULL;
     }
 
-    if (ngx_test_config) {
+    if (ngx_test_config && !ngx_quiet_mode) {
         ngx_log_stderr(0, "the configuration file %s syntax is ok",
                        cycle->conf_file.data);
     }
@@ -666,6 +670,24 @@
                           ngx_close_socket_n " listening socket on %V failed",
                           &ls[i].addr_text);
         }
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+        if (ls[i].sockaddr->sa_family == AF_UNIX) {
+            u_char  *name;
+
+            name = ls[i].addr_text.data + sizeof("unix:") - 1;
+
+            ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
+                          "deleting socket %s", name);
+
+            if (ngx_delete_file(name) == -1) {
+                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
+                              ngx_delete_file_n " %s failed", name);
+            }
+        }
+
+#endif
     }
 
 
@@ -835,6 +857,9 @@
 #if (NGX_HAVE_INET6)
     struct sockaddr_in6  *sin61, *sin62;
 #endif
+#if (NGX_HAVE_UNIX_DOMAIN)
+    struct sockaddr_un   *saun1, *saun2;
+#endif
 
     if (sa1->sa_family != sa2->sa_family) {
         return NGX_DECLINED;
@@ -847,7 +872,7 @@
         sin61 = (struct sockaddr_in6 *) sa1;
         sin62 = (struct sockaddr_in6 *) sa2;
 
-        if (sin61->sin6_port != sin61->sin6_port) {
+        if (sin61->sin6_port != sin62->sin6_port) {
             return NGX_DECLINED;
         }
 
@@ -858,6 +883,21 @@
         break;
 #endif
 
+#if (NGX_HAVE_UNIX_DOMAIN)
+    case AF_UNIX:
+       saun1 = (struct sockaddr_un *) sa1;
+       saun2 = (struct sockaddr_un *) sa2;
+
+       if (ngx_memcmp(&saun1->sun_path, &saun2->sun_path,
+                      sizeof(saun1->sun_path))
+           != 0)
+       {
+           return NGX_DECLINED;
+       }
+
+       break;
+#endif
+
     default: /* AF_INET */
 
         sin1 = (struct sockaddr_in *) sa1;
--- a/src/core/ngx_cycle.h	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_cycle.h	Mon Apr 25 04:22:17 2011 +0400
@@ -44,6 +44,8 @@
     ngx_connection_t         *free_connections;
     ngx_uint_t                free_connection_n;
 
+    ngx_queue_t               reusable_connections_queue;
+
     ngx_array_t               listening;
     ngx_array_t               pathes;
     ngx_list_t                open_files;
@@ -78,7 +80,7 @@
 
      ngx_int_t                rlimit_nofile;
      ngx_int_t                rlimit_sigpending;
-     size_t                   rlimit_core;
+     off_t                    rlimit_core;
 
      int                      priority;
 
@@ -130,6 +132,7 @@
 extern ngx_array_t            ngx_old_cycles;
 extern ngx_module_t           ngx_core_module;
 extern ngx_uint_t             ngx_test_config;
+extern ngx_uint_t             ngx_quiet_mode;
 #if (NGX_THREADS)
 extern ngx_tls_key_t          ngx_core_tls_key;
 #endif
--- a/src/core/ngx_file.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_file.c	Mon Apr 25 04:22:17 2011 +0400
@@ -183,7 +183,15 @@
     u_char     *p, ch;
     ngx_err_t   err;
 
-    for (p = dir + 1; *p; p++) {
+    err = 0;
+
+#if (NGX_WIN32)
+    p = dir + 3;
+#else
+    p = dir + 1;
+#endif
+
+    for ( /* void */ ; *p; p++) {
         ch = *p;
 
         if (ch != '/') {
@@ -194,7 +202,14 @@
 
         if (ngx_create_dir(dir, access) == NGX_FILE_ERROR) {
             err = ngx_errno;
-            if (err != NGX_EEXIST) {
+
+            switch (err) {
+            case NGX_EEXIST:
+                err = 0;
+            case NGX_EACCES:
+                break;
+
+            default:
                 return err;
             }
         }
@@ -202,7 +217,7 @@
         *p = '/';
     }
 
-    return 0;
+    return err;
 }
 
 
@@ -576,16 +591,10 @@
 #if (NGX_WIN32)
 
     if (err == NGX_EEXIST) {
-        if (ngx_win32_rename_file(src, to, ext->log) == NGX_OK) {
+        err = ngx_win32_rename_file(src, to, ext->log);
 
-            if (ngx_rename_file(src->data, to->data) != NGX_FILE_ERROR) {
-                return NGX_OK;
-            }
-
-            err = ngx_errno;
-
-        } else {
-            err = 0;
+        if (err == 0) {
+            return NGX_OK;
         }
     }
 
@@ -753,10 +762,12 @@
         size -= n;
     }
 
-    if (ngx_set_file_time(to, nfd, cf->time) != NGX_OK) {
-        ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
-                      ngx_set_file_time_n " \"%s\" failed", to);
-        goto failed;
+    if (cf->time != -1) {
+        if (ngx_set_file_time(to, nfd, cf->time) != NGX_OK) {
+            ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
+                          ngx_set_file_time_n " \"%s\" failed", to);
+            goto failed;
+        }
     }
 
     rc = NGX_OK;
@@ -814,8 +825,7 @@
     ngx_str_t   file, buf;
     ngx_dir_t   dir;
 
-    buf.len = 0;
-    buf.data = NULL;
+    ngx_str_null(&buf);
 
     ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0,
                    "walk tree \"%V\"", tree);
--- a/src/core/ngx_hash.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_hash.c	Mon Apr 25 04:22:17 2011 +0400
@@ -245,7 +245,7 @@
 
 
 #define NGX_HASH_ELT_SIZE(name)                                               \
-    (sizeof(void *) + ngx_align((name)->key.len + 1, sizeof(void *)))
+    (sizeof(void *) + ngx_align((name)->key.len + 2, sizeof(void *)))
 
 ngx_int_t
 ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts)
@@ -257,14 +257,6 @@
     ngx_hash_elt_t  *elt, **buckets;
 
     for (n = 0; n < nelts; n++) {
-        if (names[n].key.len >= 255) {
-            ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
-                          "the \"%V\" value to hash is to long: %uz bytes, "
-                          "the maximum length can be 255 bytes only",
-                          &names[n].key, names[n].key.len);
-            return NGX_ERROR;
-        }
-
         if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *))
         {
             ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
@@ -406,7 +398,7 @@
         elt = (ngx_hash_elt_t *) ((u_char *) buckets[key] + test[key]);
 
         elt->value = names[n].value;
-        elt->len = (u_char) names[n].key.len;
+        elt->len = (u_short) names[n].key.len;
 
         ngx_strlow(elt->name, names[n].key.data, names[n].key.len);
 
--- a/src/core/ngx_hash.h	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_hash.h	Mon Apr 25 04:22:17 2011 +0400
@@ -14,7 +14,7 @@
 
 typedef struct {
     void             *value;
-    u_char            len;
+    u_short           len;
     u_char            name[1];
 } ngx_hash_elt_t;
 
--- a/src/core/ngx_inet.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_inet.c	Mon Apr 25 04:22:17 2011 +0400
@@ -8,9 +8,6 @@
 #include <ngx_core.h>
 
 
-#if (NGX_HAVE_INET6)
-static size_t ngx_inet6_ntop(u_char *p, u_char *text, size_t len);
-#endif
 static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u);
 static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u);
 static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u);
@@ -59,6 +56,126 @@
 }
 
 
+#if (NGX_HAVE_INET6)
+
+ngx_int_t
+ngx_inet6_addr(u_char *p, size_t len, u_char *addr)
+{
+    u_char      c, *zero, *digit, *s, *d;
+    size_t      len4;
+    ngx_uint_t  n, nibbles, word;
+
+    if (len == 0) {
+        return NGX_ERROR;
+    }
+
+    zero = NULL;
+    digit = NULL;
+    len4 = 0;
+    nibbles = 0;
+    word = 0;
+    n = 8;
+
+    if (p[0] == ':') {
+        p++;
+        len--;
+    }
+
+    for (/* void */; len; len--) {
+        c = *p++;
+
+        if (c == ':') {
+            if (nibbles) {
+                digit = p;
+                len4 = len;
+                *addr++ = (u_char) (word >> 8);
+                *addr++ = (u_char) (word & 0xff);
+
+                if (--n) {
+                    nibbles = 0;
+                    word = 0;
+                    continue;
+                }
+
+            } else {
+                if (zero == NULL) {
+                    digit = p;
+                    len4 = len;
+                    zero = addr;
+                    continue;
+                }
+            }
+
+            return NGX_ERROR;
+        }
+
+        if (c == '.' && nibbles) {
+            if (n < 2) {
+                return NGX_ERROR;
+            }
+
+            word = ngx_inet_addr(digit, len4 - 1);
+            if (word == INADDR_NONE) {
+                return NGX_ERROR;
+            }
+
+            word = ntohl(word);
+            *addr++ = (u_char) ((word >> 24) & 0xff);
+            *addr++ = (u_char) ((word >> 16) & 0xff);
+            n--;
+            break;
+        }
+
+        if (++nibbles > 4) {
+            return NGX_ERROR;
+        }
+
+        if (c >= '0' && c <= '9') {
+            word = word * 16 + (c - '0');
+            continue;
+        }
+
+        c |= 0x20;
+
+        if (c >= 'a' && c <= 'f') {
+            word = word * 16 + (c - 'a') + 10;
+            continue;
+        }
+
+        return NGX_ERROR;
+    }
+
+    if (nibbles == 0 && zero == NULL) {
+        return NGX_ERROR;
+    }
+
+    *addr++ = (u_char) (word >> 8);
+    *addr++ = (u_char) (word & 0xff);
+
+    if (--n) {
+        if (zero) {
+            n *= 2;
+            s = addr - 1;
+            d = s + n;
+            while (s >= zero) {
+                *d-- = *s--;
+            }
+            ngx_memzero(zero, n);
+            return NGX_OK;
+        }
+
+    } else {
+        if (zero == NULL) {
+            return NGX_OK;
+        }
+    }
+
+    return NGX_ERROR;
+}
+
+#endif
+
+
 size_t
 ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len, ngx_uint_t port)
 {
@@ -68,6 +185,9 @@
     size_t                n;
     struct sockaddr_in6  *sin6;
 #endif
+#if (NGX_HAVE_UNIX_DOMAIN)
+    struct sockaddr_un   *saun;
+#endif
 
     switch (sa->sa_family) {
 
@@ -98,7 +218,7 @@
             text[n++] = '[';
         }
 
-        n = ngx_inet6_ntop((u_char *) &sin6->sin6_addr, &text[n], len);
+        n = ngx_inet6_ntop(sin6->sin6_addr.s6_addr, &text[n], len);
 
         if (port) {
             n = ngx_sprintf(&text[1 + n], "]:%d",
@@ -108,6 +228,17 @@
         return n;
 #endif
 
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+    case AF_UNIX:
+        saun = (struct sockaddr_un *) sa;
+
+        /* we do not include trailing zero in address length */
+
+        return ngx_snprintf(text, len, "unix:%s%Z", saun->sun_path) - text - 1;
+
+#endif
+
     default:
         return 0;
     }
@@ -144,7 +275,7 @@
 
 #if (NGX_HAVE_INET6)
 
-static size_t
+size_t
 ngx_inet6_ntop(u_char *p, u_char *text, size_t len)
 {
     u_char      *dst;
@@ -223,31 +354,47 @@
 #endif
 
 
-/* AF_INET only */
-
 ngx_int_t
 ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr)
 {
-    u_char     *addr, *mask, *last;
-    ngx_int_t   shift;
+    u_char      *addr, *mask, *last;
+    size_t       len;
+    ngx_int_t    shift;
+#if (NGX_HAVE_INET6)
+    ngx_int_t    rc;
+    ngx_uint_t   s, i;
+#endif
 
     addr = text->data;
     last = addr + text->len;
 
     mask = ngx_strlchr(addr, last, '/');
+    len = (mask ? mask : last) - addr;
 
-    cidr->u.in.addr = ngx_inet_addr(addr, (mask ? mask : last) - addr);
+    cidr->u.in.addr = ngx_inet_addr(addr, len);
+
+    if (cidr->u.in.addr != INADDR_NONE) {
+        cidr->family = AF_INET;
+
+        if (mask == NULL) {
+            cidr->u.in.mask = 0xffffffff;
+            return NGX_OK;
+        }
 
-    if (cidr->u.in.addr == INADDR_NONE) {
+#if (NGX_HAVE_INET6)
+    } else if (ngx_inet6_addr(addr, len, cidr->u.in6.addr.s6_addr) == NGX_OK) {
+        cidr->family = AF_INET6;
+
+        if (mask == NULL) {
+            ngx_memset(cidr->u.in6.mask.s6_addr, 0xff, 16);
+            return NGX_OK;
+        }
+
+#endif
+    } else {
         return NGX_ERROR;
     }
 
-    if (mask == NULL) {
-        cidr->family = AF_INET;
-        cidr->u.in.mask = 0xffffffff;
-        return NGX_OK;
-    }
-
     mask++;
 
     shift = ngx_atoi(mask, last - mask);
@@ -255,30 +402,108 @@
         return NGX_ERROR;
     }
 
-    cidr->family = AF_INET;
+    switch (cidr->family) {
 
-    if (shift == 0) {
+#if (NGX_HAVE_INET6)
+    case AF_INET6:
+        addr = cidr->u.in6.addr.s6_addr;
+        mask = cidr->u.in6.mask.s6_addr;
+        rc = NGX_OK;
+
+        for (i = 0; i < 16; i++) {
+
+            s = (shift > 8) ? 8 : shift;
+            shift -= s;
+
+            mask[i] = (u_char) (0 - (1 << (8 - s)));
 
-        /* the x86 compilers use the shl instruction that shifts by modulo 32 */
+            if (addr[i] != (addr[i] & mask[i])) {
+                rc = NGX_DONE;
+                addr[i] &= mask[i];
+            }
+        }
+
+        return rc;
+#endif
 
-        cidr->u.in.mask = 0;
+    default: /* AF_INET */
+
+        if (shift) {
+            cidr->u.in.mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift))));
 
-        if (cidr->u.in.addr == 0) {
+        } else {
+            /* x86 compilers use a shl instruction that shifts by modulo 32 */
+            cidr->u.in.mask = 0;
+        }
+
+        if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) {
             return NGX_OK;
         }
 
+        cidr->u.in.addr &= cidr->u.in.mask;
+
         return NGX_DONE;
     }
+}
+
+
+ngx_int_t
+ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text, size_t len)
+{
+    in_addr_t             inaddr;
+    ngx_uint_t            family;
+    struct sockaddr_in   *sin;
+#if (NGX_HAVE_INET6)
+    struct in6_addr       inaddr6;
+    struct sockaddr_in6  *sin6;
+
+    /*
+     * prevent MSVC8 waring:
+     *    potentially uninitialized local variable 'inaddr6' used
+     */
+    ngx_memzero(inaddr6.s6_addr, sizeof(struct in6_addr));
+#endif
+
+    inaddr = ngx_inet_addr(text, len);
+
+    if (inaddr != INADDR_NONE) {
+        family = AF_INET;
+        len = sizeof(struct sockaddr_in);
+
+#if (NGX_HAVE_INET6)
+    } else if (ngx_inet6_addr(text, len, inaddr6.s6_addr) == NGX_OK) {
+        family = AF_INET6;
+        len = sizeof(struct sockaddr_in6);
+
+#endif
+    } else {
+        return NGX_DECLINED;
+    }
 
-    cidr->u.in.mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift))));
-
-    if (cidr->u.in.addr == (cidr->u.in.addr & cidr->u.in.mask)) {
-        return NGX_OK;
+    addr->sockaddr = ngx_pcalloc(pool, len);
+    if (addr->sockaddr == NULL) {
+        return NGX_ERROR;
     }
 
-    cidr->u.in.addr &= cidr->u.in.mask;
+    addr->sockaddr->sa_family = (u_char) family;
+    addr->socklen = len;
+
+    switch (family) {
 
-    return NGX_DONE;
+#if (NGX_HAVE_INET6)
+    case AF_INET6:
+        sin6 = (struct sockaddr_in6 *) addr->sockaddr;
+        ngx_memcpy(sin6->sin6_addr.s6_addr, inaddr6.s6_addr, 16);
+        break;
+#endif
+
+    default: /* AF_INET */
+        sin = (struct sockaddr_in *) addr->sockaddr;
+        sin->sin_addr.s_addr = inaddr;
+        break;
+    }
+
+    return NGX_OK;
 }
 
 
@@ -351,7 +576,7 @@
     saun->sun_family = AF_UNIX;
     (void) ngx_cpystrn((u_char *) saun->sun_path, path, len);
 
-    u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t));
+    u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
     if (u->addrs == NULL) {
         return NGX_ERROR;
     }
@@ -509,22 +734,22 @@
         return NGX_OK;
     }
 
-    if (len++) {
-
-        p = ngx_alloc(len, pool->log);
-        if (p == NULL) {
-            return NGX_ERROR;
-        }
-
-        (void) ngx_cpystrn(p, host, len);
-
-        sin->sin_addr.s_addr = inet_addr((const char *) p);
+    if (len) {
+        sin->sin_addr.s_addr = ngx_inet_addr(host, len);
 
         if (sin->sin_addr.s_addr == INADDR_NONE) {
+            p = ngx_alloc(++len, pool->log);
+            if (p == NULL) {
+                return NGX_ERROR;
+            }
+
+            (void) ngx_cpystrn(p, host, len);
+
             h = gethostbyname((const char *) p);
 
+            ngx_free(p);
+
             if (h == NULL || h->h_addr_list[0] == NULL) {
-                ngx_free(p);
                 u->err = "host not found";
                 return NGX_ERROR;
             }
@@ -536,8 +761,6 @@
             u->wildcard = 1;
         }
 
-        ngx_free(p);
-
     } else {
         sin->sin_addr.s_addr = INADDR_ANY;
         u->wildcard = 1;
@@ -564,7 +787,6 @@
 ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u)
 {
 #if (NGX_HAVE_INET6)
-    int                   rc;
     u_char               *p, *host, *port, *last, *uri;
     size_t                len;
     ngx_int_t             n;
@@ -636,35 +858,10 @@
         return NGX_ERROR;
     }
 
-    u->host.len = len++;
+    u->host.len = len;
     u->host.data = host;
 
-    p = ngx_alloc(len, pool->log);
-    if (p == NULL) {
-        return NGX_ERROR;
-    }
-
-    (void) ngx_cpystrn(p, host, len);
-
-#if (NGX_WIN32)
-
-    rc = WSAStringToAddress((char *) p, AF_INET6, NULL,
-                            (SOCKADDR *) sin6, &u->socklen);
-    rc = !rc;
-
-    if (u->port) {
-        sin6->sin6_port = htons(u->port);
-    }
-
-#else
-
-    rc = inet_pton(AF_INET6, (const char *) p, &sin6->sin6_addr);
-
-#endif
-
-    ngx_free(p);
-
-    if (rc == 0) {
+    if (ngx_inet6_addr(host, len, sin6->sin6_addr.s6_addr) != NGX_OK) {
         u->err = "invalid IPv6 address";
         return NGX_ERROR;
     }
@@ -707,20 +904,20 @@
     struct hostent      *h;
     struct sockaddr_in  *sin;
 
-    host = ngx_alloc(u->host.len + 1, pool->log);
-    if (host == NULL) {
-        return NGX_ERROR;
-    }
-
-    (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
-
     /* AF_INET only */
 
     port = htons(u->port);
 
-    in_addr = inet_addr((char *) host);
+    in_addr = ngx_inet_addr(u->host.data, u->host.len);
 
     if (in_addr == INADDR_NONE) {
+        host = ngx_alloc(u->host.len + 1, pool->log);
+        if (host == NULL) {
+            return NGX_ERROR;
+        }
+
+        (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
+
         h = gethostbyname((char *) host);
 
         ngx_free(host);
@@ -739,14 +936,14 @@
 
         /* MP: ngx_shared_palloc() */
 
-        u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_peer_addr_t));
+        u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
         if (u->addrs == NULL) {
             return NGX_ERROR;
         }
 
         u->naddrs = i;
 
-        for (i = 0; h->h_addr_list[i] != NULL; i++) {
+        for (i = 0; i < u->naddrs; i++) {
 
             sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
             if (sin == NULL) {
@@ -775,11 +972,9 @@
 
     } else {
 
-        ngx_free(host);
-
         /* MP: ngx_shared_palloc() */
 
-        u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t));
+        u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
         if (u->addrs == NULL) {
             return NGX_ERROR;
         }
--- a/src/core/ngx_inet.h	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_inet.h	Mon Apr 25 04:22:17 2011 +0400
@@ -12,21 +12,26 @@
 #include <ngx_core.h>
 
 
-#define NGX_INET_ADDRSTRLEN   (sizeof("255.255.255.255") - 1)
-#define NGX_INET6_ADDRSTRLEN                                                 \
-    (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") - 1)
-
-#define NGX_SOCKADDR_STRLEN   (NGX_INET6_ADDRSTRLEN + sizeof(":65535") - 1)
-
-
 /*
- * TODO: autoconfigure NGX_SOCKADDRLEN as
+ * TODO: autoconfigure NGX_SOCKADDRLEN and NGX_SOCKADDR_STRLEN as
  *       sizeof(struct sockaddr_storage)
  *       sizeof(struct sockaddr_un)
  *       sizeof(struct sockaddr_in6)
  *       sizeof(struct sockaddr_in)
  */
 
+#define NGX_INET_ADDRSTRLEN   (sizeof("255.255.255.255") - 1)
+#define NGX_INET6_ADDRSTRLEN                                                 \
+    (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") - 1)
+#define NGX_UNIX_ADDRSTRLEN                                                  \
+    (sizeof(struct sockaddr_un) - offsetof(struct sockaddr_un, sun_path))
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+#define NGX_SOCKADDR_STRLEN   (sizeof("unix:") - 1 + NGX_UNIX_ADDRSTRLEN)
+#else
+#define NGX_SOCKADDR_STRLEN   (NGX_INET6_ADDRSTRLEN + sizeof(":65535") - 1)
+#endif
+
 #if (NGX_HAVE_UNIX_DOMAIN)
 #define NGX_SOCKADDRLEN       sizeof(struct sockaddr_un)
 #else
@@ -65,7 +70,7 @@
     struct sockaddr          *sockaddr;
     socklen_t                 socklen;
     ngx_str_t                 name;
-} ngx_peer_addr_t;
+} ngx_addr_t;
 
 
 typedef struct {
@@ -89,7 +94,7 @@
     socklen_t                 socklen;
     u_char                    sockaddr[NGX_SOCKADDRLEN];
 
-    ngx_peer_addr_t          *addrs;
+    ngx_addr_t               *addrs;
     ngx_uint_t                naddrs;
 
     char                     *err;
@@ -97,13 +102,18 @@
 
 
 in_addr_t ngx_inet_addr(u_char *text, size_t len);
+#if (NGX_HAVE_INET6)
+ngx_int_t ngx_inet6_addr(u_char *p, size_t len, u_char *addr);
+size_t ngx_inet6_ntop(u_char *p, u_char *text, size_t len);
+#endif
 size_t ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len,
     ngx_uint_t port);
 size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len);
 ngx_int_t ngx_ptocidr(ngx_str_t *text, ngx_cidr_t *cidr);
+ngx_int_t ngx_parse_addr(ngx_pool_t *pool, ngx_addr_t *addr, u_char *text,
+    size_t len);
 ngx_int_t ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u);
 ngx_int_t ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u);
 
 
-
 #endif /* _NGX_INET_H_INCLUDED_ */
--- a/src/core/ngx_log.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_log.c	Mon Apr 25 04:22:17 2011 +0400
@@ -148,9 +148,9 @@
         return;
     }
 
-    msg -= (err_levels[level].len + 4);
+    msg -= (7 + err_levels[level].len + 3);
 
-    (void) ngx_sprintf(msg, "[%V]: ", &err_levels[level]);
+    (void) ngx_sprintf(msg, "nginx: [%V] ", &err_levels[level]);
 
     (void) ngx_write_console(ngx_stderr, msg, p - msg);
 }
@@ -209,9 +209,12 @@
     u_char    errstr[NGX_MAX_ERROR_STR];
 
     last = errstr + NGX_MAX_ERROR_STR;
+    p = errstr + 7;
+
+    ngx_memcpy(errstr, "nginx: ", 7);
 
     va_start(args, fmt);
-    p = ngx_vslprintf(errstr, last, fmt, args);
+    p = ngx_vslprintf(p, last, fmt, args);
     va_end(args);
 
     if (err) {
@@ -248,7 +251,7 @@
     buf = ngx_slprintf(buf, last, " (%d: ", err);
 #endif
 
-    buf = ngx_strerror_r(err, buf, last - buf);
+    buf = ngx_strerror(err, buf, last - buf);
 
     if (buf < last) {
         *buf++ = ')';
@@ -325,7 +328,7 @@
 
     if (ngx_log_file.fd == NGX_INVALID_FILE) {
         ngx_log_stderr(ngx_errno,
-                       "[alert]: could not open error log file: "
+                       "[alert] could not open error log file: "
                        ngx_open_file_n " \"%s\" failed", name);
 #if (NGX_WIN32)
         ngx_event_log(ngx_errno,
@@ -429,8 +432,7 @@
     value = cf->args->elts;
 
     if (ngx_strcmp(value[1].data, "stderr") == 0) {
-        name.len = 0;
-        name.data = NULL;
+        ngx_str_null(&name);
 
     } else {
         name = value[1];
--- a/src/core/ngx_log.h	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_log.h	Mon Apr 25 04:22:17 2011 +0400
@@ -68,7 +68,23 @@
 
 /*********************************/
 
-#if (NGX_HAVE_GCC_VARIADIC_MACROS)
+#if (NGX_HAVE_C99_VARIADIC_MACROS)
+
+#define NGX_HAVE_VARIADIC_MACROS  1
+
+#define ngx_log_error(level, log, ...)                                        \
+    if ((log)->log_level >= level) ngx_log_error_core(level, log, __VA_ARGS__)
+
+void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
+    const char *fmt, ...);
+
+#define ngx_log_debug(level, log, ...)                                        \
+    if ((log)->log_level & level)                                             \
+        ngx_log_error_core(NGX_LOG_DEBUG, log, __VA_ARGS__)
+
+/*********************************/
+
+#elif (NGX_HAVE_GCC_VARIADIC_MACROS)
 
 #define NGX_HAVE_VARIADIC_MACROS  1
 
@@ -84,22 +100,6 @@
 
 /*********************************/
 
-#elif (NGX_HAVE_C99_VARIADIC_MACROS)
-
-#define NGX_HAVE_VARIADIC_MACROS  1
-
-#define ngx_log_error(level, log, ...)                                        \
-    if ((log)->log_level >= level) ngx_log_error_core(level, log, __VA_ARGS__)
-
-void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
-    const char *fmt, ...);
-
-#define ngx_log_debug(level, log, ...)                                        \
-    if ((log)->log_level & level)                                             \
-        ngx_log_error_core(NGX_LOG_DEBUG, log, __VA_ARGS__)
-
-/*********************************/
-
 #else /* NO VARIADIC MACROS */
 
 #define NGX_HAVE_VARIADIC_MACROS  0
--- a/src/core/ngx_open_file_cache.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_open_file_cache.c	Mon Apr 25 04:22:17 2011 +0400
@@ -17,6 +17,9 @@
  */
 
 
+#define NGX_MIN_READ_AHEAD  (128 * 1024)
+
+
 static void ngx_open_file_cache_cleanup(void *data);
 static ngx_int_t ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of,
     ngx_log_t *log);
@@ -487,7 +490,14 @@
     }
 
     if (!of->log) {
-        fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
+
+        /*
+         * Use non-blocking open() not to hang on FIFO files, etc.
+         * This flag has no effect on a regular files.
+         */
+
+        fd = ngx_open_file(name, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
+                           NGX_FILE_OPEN, 0);
 
     } else {
         fd = ngx_open_file(name, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN,
@@ -524,8 +534,15 @@
     } else {
         of->fd = fd;
 
+        if (of->read_ahead && ngx_file_size(&fi) > NGX_MIN_READ_AHEAD) {
+            if (ngx_read_ahead(fd, of->read_ahead) == NGX_ERROR) {
+                ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+                              ngx_read_ahead_n " \"%s\" failed", name);
+            }
+        }
+
         if (of->directio <= ngx_file_size(&fi)) {
-            if (ngx_directio_on(fd) == -1) {
+            if (ngx_directio_on(fd) == NGX_FILE_ERROR) {
                 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
                               ngx_directio_on_n " \"%s\" failed", name);
 
--- a/src/core/ngx_open_file_cache.h	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_open_file_cache.h	Mon Apr 25 04:22:17 2011 +0400
@@ -21,6 +21,7 @@
     time_t                   mtime;
     off_t                    size;
     off_t                    directio;
+    size_t                   read_ahead;
 
     ngx_err_t                err;
     char                    *failed;
--- a/src/core/ngx_output_chain.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_output_chain.c	Mon Apr 25 04:22:17 2011 +0400
@@ -74,18 +74,18 @@
         }
     }
 
-#if (NGX_HAVE_FILE_AIO)
-    if (ctx->aio) {
-        return NGX_AGAIN;
-    }
-#endif
-
     out = NULL;
     last_out = &out;
     last = NGX_NONE;
 
     for ( ;; ) {
 
+#if (NGX_HAVE_FILE_AIO)
+        if (ctx->aio) {
+            return NGX_AGAIN;
+        }
+#endif
+
         while (ctx->in) {
 
             /*
@@ -465,10 +465,7 @@
     dst = ctx->buf;
 
     size = ngx_buf_size(src);
-
-    if (size > dst->end - dst->pos) {
-        size = dst->end - dst->pos;
-    }
+    size = ngx_min(size, dst->end - dst->pos);
 
     sendfile = ctx->sendfile & !ctx->directio;
 
@@ -514,7 +511,7 @@
 #if (NGX_HAVE_ALIGNED_DIRECTIO)
 
         if (ctx->unaligned) {
-            if (ngx_directio_off(src->file->fd) == -1) {
+            if (ngx_directio_off(src->file->fd) == NGX_FILE_ERROR) {
                 ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, ngx_errno,
                               ngx_directio_off_n " \"%s\" failed",
                               src->file->name.data);
@@ -550,7 +547,7 @@
 
             err = ngx_errno;
 
-            if (ngx_directio_on(src->file->fd) == -1) {
+            if (ngx_directio_on(src->file->fd) == NGX_FILE_ERROR) {
                 ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, ngx_errno,
                               ngx_directio_on_n " \"%s\" failed",
                               src->file->name.data);
--- a/src/core/ngx_palloc.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_palloc.c	Mon Apr 25 04:22:17 2011 +0400
@@ -17,7 +17,7 @@
 {
     ngx_pool_t  *p;
 
-    p = ngx_alloc(size, log);
+    p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log);
     if (p == NULL) {
         return NULL;
     }
@@ -181,7 +181,7 @@
 
     psize = (size_t) (pool->d.end - (u_char *) pool);
 
-    m = ngx_alloc(psize, pool->log);
+    m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log);
     if (m == NULL) {
         return NULL;
     }
--- a/src/core/ngx_palloc.h	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_palloc.h	Mon Apr 25 04:22:17 2011 +0400
@@ -19,8 +19,11 @@
 #define NGX_MAX_ALLOC_FROM_POOL  (ngx_pagesize - 1)
 
 #define NGX_DEFAULT_POOL_SIZE    (16 * 1024)
+
+#define NGX_POOL_ALIGNMENT       16
 #define NGX_MIN_POOL_SIZE                                                     \
-    (sizeof(ngx_pool_t) + 2 * sizeof(ngx_pool_large_t))
+    ngx_align((sizeof(ngx_pool_t) + 2 * sizeof(ngx_pool_large_t)),            \
+              NGX_POOL_ALIGNMENT)
 
 
 typedef void (*ngx_pool_cleanup_pt)(void *data);
--- a/src/core/ngx_regex.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_regex.c	Mon Apr 25 04:22:17 2011 +0400
@@ -23,61 +23,116 @@
 }
 
 
-ngx_regex_t *
-ngx_regex_compile(ngx_str_t *pattern, ngx_int_t options, ngx_pool_t *pool,
-    ngx_str_t *err)
+static ngx_inline void
+ngx_regex_malloc_init(ngx_pool_t *pool)
 {
-    int              erroff;
-    const char      *errstr;
-    ngx_regex_t     *re;
 #if (NGX_THREADS)
     ngx_core_tls_t  *tls;
 
-#if (NGX_SUPPRESS_WARN)
-    tls = NULL;
-#endif
-
     if (ngx_threaded) {
         tls = ngx_thread_get_tls(ngx_core_tls_key);
         tls->pool = pool;
-    } else {
-        ngx_pcre_pool = pool;
+        return;
     }
 
-#else
+#endif
 
     ngx_pcre_pool = pool;
+}
+
+
+static ngx_inline void
+ngx_regex_malloc_done(void)
+{
+#if (NGX_THREADS)
+    ngx_core_tls_t  *tls;
+
+    if (ngx_threaded) {
+        tls = ngx_thread_get_tls(ngx_core_tls_key);
+        tls->pool = NULL;
+        return;
+    }
 
 #endif
 
-    re = pcre_compile((const char *) pattern->data, (int) options,
+    ngx_pcre_pool = NULL;
+}
+
+
+ngx_int_t
+ngx_regex_compile(ngx_regex_compile_t *rc)
+{
+    int           n, erroff;
+    char         *p;
+    const char   *errstr;
+    ngx_regex_t  *re;
+
+    ngx_regex_malloc_init(rc->pool);
+
+    re = pcre_compile((const char *) rc->pattern.data, (int) rc->options,
                       &errstr, &erroff, NULL);
 
+    /* ensure that there is no current pool */
+    ngx_regex_malloc_done();
+
     if (re == NULL) {
-       if ((size_t) erroff == pattern->len) {
-           ngx_snprintf(err->data, err->len - 1,
-                        "pcre_compile() failed: %s in \"%s\"%Z",
-                        errstr, pattern->data);
+        if ((size_t) erroff == rc->pattern.len) {
+           rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
+                              "pcre_compile() failed: %s in \"%V\"",
+                               errstr, &rc->pattern)
+                      - rc->err.data;
+
         } else {
-           ngx_snprintf(err->data, err->len - 1,
-                        "pcre_compile() failed: %s in \"%s\" at \"%s\"%Z",
-                        errstr, pattern->data, pattern->data + erroff);
+           rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
+                              "pcre_compile() failed: %s in \"%V\" at \"%s\"",
+                               errstr, &rc->pattern, rc->pattern.data + erroff)
+                      - rc->err.data;
         }
+
+        return NGX_ERROR;
+    }
+
+    rc->regex = re;
+
+    n = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &rc->captures);
+    if (n < 0) {
+        p = "pcre_fullinfo(\"%V\", PCRE_INFO_CAPTURECOUNT) failed: %d";
+        goto failed;
+    }
+
+    if (rc->captures == 0) {
+        return NGX_OK;
     }
 
-    /* ensure that there is no current pool */
+    n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMECOUNT, &rc->named_captures);
+    if (n < 0) {
+        p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMECOUNT) failed: %d";
+        goto failed;
+    }
+
+    if (rc->named_captures == 0) {
+        return NGX_OK;
+    }
 
-#if (NGX_THREADS)
-    if (ngx_threaded) {
-        tls->pool = NULL;
-    } else {
-        ngx_pcre_pool = NULL;
+    n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMEENTRYSIZE, &rc->name_size);
+    if (n < 0) {
+        p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMEENTRYSIZE) failed: %d";
+        goto failed;
     }
-#else
-    ngx_pcre_pool = NULL;
-#endif
+
+    n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMETABLE, &rc->names);
+    if (n < 0) {
+        p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMETABLE) failed: %d";
+        goto failed;
+    }
 
-    return re;
+    return NGX_OK;
+
+failed:
+
+    rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, p, &rc->pattern, n)
+                  - rc->err.data;
+    return NGX_OK;
 }
 
 
@@ -99,22 +154,6 @@
 
 
 ngx_int_t
-ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures, ngx_int_t size)
-{
-    int  rc;
-
-    rc = pcre_exec(re, NULL, (const char *) s->data, s->len, 0, 0,
-                   captures, size);
-
-    if (rc == -1) {
-        return NGX_REGEX_NO_MATCHED;
-    }
-
-    return rc;
-}
-
-
-ngx_int_t
 ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log)
 {
     ngx_int_t         n;
@@ -133,7 +172,7 @@
 
         if (n < 0) {
             ngx_log_error(NGX_LOG_ALERT, log, 0,
-                          ngx_regex_exec_n " failed: %d on \"%V\" using \"%s\"",
+                          ngx_regex_exec_n " failed: %i on \"%V\" using \"%s\"",
                           n, s, re[i].name);
             return NGX_ERROR;
         }
@@ -157,11 +196,15 @@
     if (ngx_threaded) {
         tls = ngx_thread_get_tls(ngx_core_tls_key);
         pool = tls->pool;
+
     } else {
         pool = ngx_pcre_pool;
     }
+
 #else
+
     pool = ngx_pcre_pool;
+
 #endif
 
     if (pool) {
--- a/src/core/ngx_regex.h	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_regex.h	Mon Apr 25 04:22:17 2011 +0400
@@ -14,29 +14,42 @@
 #include <pcre.h>
 
 
-#define NGX_REGEX_NO_MATCHED  -1000
+#define NGX_REGEX_NO_MATCHED  PCRE_ERROR_NOMATCH   /* -1 */
 
 #define NGX_REGEX_CASELESS    PCRE_CASELESS
 
 typedef pcre  ngx_regex_t;
 
+
 typedef struct {
-    ngx_regex_t   *regex;
-    u_char        *name;
+    ngx_str_t     pattern;
+    ngx_pool_t   *pool;
+    ngx_int_t     options;
+
+    ngx_regex_t  *regex;
+    int           captures;
+    int           named_captures;
+    int           name_size;
+    u_char       *names;
+    ngx_str_t     err;
+} ngx_regex_compile_t;
+
+
+typedef struct {
+    ngx_regex_t  *regex;
+    u_char       *name;
 } ngx_regex_elt_t;
 
 
 void ngx_regex_init(void);
-ngx_regex_t *ngx_regex_compile(ngx_str_t *pattern, ngx_int_t options,
-    ngx_pool_t *pool, ngx_str_t *err);
-ngx_int_t ngx_regex_capture_count(ngx_regex_t *re);
-ngx_int_t ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures,
-    ngx_int_t size);
+ngx_int_t ngx_regex_compile(ngx_regex_compile_t *rc);
+
+#define ngx_regex_exec(re, s, captures, size)                                \
+    pcre_exec(re, NULL, (const char *) (s)->data, (s)->len, 0, 0,            \
+              captures, size)
+#define ngx_regex_exec_n      "pcre_exec()"
+
 ngx_int_t ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log);
 
 
-#define ngx_regex_exec_n           "pcre_exec()"
-#define ngx_regex_capture_count_n  "pcre_fullinfo()"
-
-
 #endif /* _NGX_REGEX_H_INCLUDED_ */
--- a/src/core/ngx_resolver.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_resolver.c	Mon Apr 25 04:22:17 2011 +0400
@@ -87,12 +87,11 @@
 static void ngx_resolver_free(ngx_resolver_t *r, void *p);
 static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p);
 static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);
-
-
-/* STUB: ngx_peer_addr_t * */
+static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len);
+
 
 ngx_resolver_t *
-ngx_resolver_create(ngx_conf_t *cf, ngx_peer_addr_t *addr)
+ngx_resolver_create(ngx_conf_t *cf, ngx_addr_t *addr)
 {
     ngx_resolver_t        *r;
     ngx_pool_cleanup_t    *cln;
@@ -139,7 +138,7 @@
     r->valid = 300;
 
     r->log = &cf->cycle->new_log;
-    r->log_level = NGX_LOG_ALERT;
+    r->log_level = NGX_LOG_ERR;
 
     if (addr) {
         uc = ngx_calloc(sizeof(ngx_udp_connection_t), cf->log);
@@ -152,7 +151,11 @@
         uc->sockaddr = addr->sockaddr;
         uc->socklen = addr->socklen;
         uc->server = addr->name;
-        uc->log = &cf->cycle->new_log;
+
+        uc->log = cf->cycle->new_log;
+        uc->log.handler = ngx_resolver_log_error;
+        uc->log.data = uc;
+        uc->log.action = "resolving";
     }
 
     return r;
@@ -464,6 +467,7 @@
 
             ctx->next = rn->waiting;
             rn->waiting = ctx;
+            ctx->state = NGX_AGAIN;
 
             return NGX_AGAIN;
         }
@@ -625,6 +629,7 @@
 
             ctx->next = rn->waiting;
             rn->waiting = ctx;
+            ctx->state = NGX_AGAIN;
 
             /* unlock addr mutex */
 
@@ -840,7 +845,7 @@
     }
 
     if ((size_t) n != (size_t) rn->qlen) {
-        ngx_log_error(NGX_LOG_CRIT, uc->log, 0, "send() incomplete");
+        ngx_log_error(NGX_LOG_CRIT, &uc->log, 0, "send() incomplete");
         return NGX_ERROR;
     }
 
@@ -1717,15 +1722,16 @@
 ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx)
 {
     u_char                *p, *s;
-    size_t                 len;
+    size_t                 len, nlen;
     ngx_uint_t             ident;
     ngx_resolver_qs_t     *qs;
     ngx_resolver_query_t  *query;
 
-    len = sizeof(ngx_resolver_query_t)
-          + 1 + ctx->name.len + 1 + sizeof(ngx_resolver_qs_t);
-
-    p = ngx_resolver_calloc(ctx->resolver, len);
+    nlen = ctx->name.len ? (1 + ctx->name.len + 1) : 1;
+
+    len = sizeof(ngx_resolver_query_t) + nlen + sizeof(ngx_resolver_qs_t);
+
+    p = ngx_resolver_alloc(ctx->resolver, len);
     if (p == NULL) {
         return NGX_ERROR;
     }
@@ -1752,7 +1758,7 @@
     query->nns_hi = 0; query->nns_lo = 0;
     query->nar_hi = 0; query->nar_lo = 0;
 
-    p += sizeof(ngx_resolver_query_t) + 1 + ctx->name.len + 1;
+    p += sizeof(ngx_resolver_query_t) + nlen;
 
     qs = (ngx_resolver_qs_t *) p;
 
@@ -1806,7 +1812,7 @@
           + sizeof(".255.255.255.255.in-addr.arpa.") - 1
           + sizeof(ngx_resolver_qs_t);
 
-    p = ngx_resolver_calloc(ctx->resolver, len);
+    p = ngx_resolver_alloc(ctx->resolver, len);
     if (p == NULL) {
         return NGX_ERROR;
     }
@@ -1830,7 +1836,7 @@
 
     p += sizeof(ngx_resolver_query_t);
 
-    for (n = 0; n < 32; n += 8){
+    for (n = 0; n < 32; n += 8) {
         d = ngx_sprintf(&p[1], "%ud", (ctx->addr >> n) & 0xff);
         *p = (u_char) (d - &p[1]);
         p = d;
@@ -1900,6 +1906,12 @@
         return NGX_OK;
     }
 
+    if (len == -1) {
+        name->len = 0;
+        name->data = NULL;
+        return NGX_OK;
+    }
+
     dst = ngx_resolver_alloc(r, len);
     if (dst == NULL) {
         return NGX_ERROR;
@@ -2064,6 +2076,29 @@
 }
 
 
+static u_char *
+ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len)
+{
+    u_char                *p;
+    ngx_udp_connection_t  *uc;
+
+    p = buf;
+
+    if (log->action) {
+        p = ngx_snprintf(buf, len, " while %s", log->action);
+        len -= p - buf;
+    }
+
+    uc = log->data;
+
+    if (uc) {
+        p = ngx_snprintf(p, len, ", resolver: %V", &uc->server);
+    }
+
+    return p;
+}
+
+
 ngx_int_t
 ngx_udp_connect(ngx_udp_connection_t *uc)
 {
@@ -2075,19 +2110,19 @@
 
     s = ngx_socket(AF_INET, SOCK_DGRAM, 0);
 
-    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, uc->log, 0, "UDP socket %d", s);
+    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, &uc->log, 0, "UDP socket %d", s);
 
     if (s == -1) {
-        ngx_log_error(NGX_LOG_ALERT, uc->log, ngx_socket_errno,
+        ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
                       ngx_socket_n " failed");
         return NGX_ERROR;
     }
 
-    c = ngx_get_connection(s, uc->log);
+    c = ngx_get_connection(s, &uc->log);
 
     if (c == NULL) {
         if (ngx_close_socket(s) == -1) {
-            ngx_log_error(NGX_LOG_ALERT, uc->log, ngx_socket_errno,
+            ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
                           ngx_close_socket_n "failed");
         }
 
@@ -2095,13 +2130,13 @@
     }
 
     if (ngx_nonblocking(s) == -1) {
-        ngx_log_error(NGX_LOG_ALERT, uc->log, ngx_socket_errno,
+        ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
                       ngx_nonblocking_n " failed");
 
         ngx_free_connection(c);
 
         if (ngx_close_socket(s) == -1) {
-            ngx_log_error(NGX_LOG_ALERT, uc->log, ngx_socket_errno,
+            ngx_log_error(NGX_LOG_ALERT, &uc->log, ngx_socket_errno,
                           ngx_close_socket_n " failed");
         }
 
@@ -2111,8 +2146,8 @@
     rev = c->read;
     wev = c->write;
 
-    rev->log = uc->log;
-    wev->log = uc->log;
+    rev->log = &uc->log;
+    wev->log = &uc->log;
 
     uc->connection = c;
 
@@ -2129,7 +2164,7 @@
 
 #endif
 
-    ngx_log_debug3(NGX_LOG_DEBUG_EVENT, uc->log, 0,
+    ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &uc->log, 0,
                    "connect to %V, fd:%d #%d", &uc->server, s, c->number);
 
     rc = connect(s, uc->sockaddr, uc->socklen);
@@ -2137,8 +2172,8 @@
     /* TODO: aio, iocp */
 
     if (rc == -1) {
-        ngx_log_error(NGX_LOG_CRIT, uc->log, ngx_socket_errno,
-                      "connect() to %V failed", &uc->server);
+        ngx_log_error(NGX_LOG_CRIT, &uc->log, ngx_socket_errno,
+                      "connect() failed");
 
         return NGX_ERROR;
     }
--- a/src/core/ngx_resolver.h	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_resolver.h	Mon Apr 25 04:22:17 2011 +0400
@@ -37,7 +37,7 @@
     struct sockaddr          *sockaddr;
     socklen_t                 socklen;
     ngx_str_t                 server;
-    ngx_log_t                *log;
+    ngx_log_t                 log;
 } ngx_udp_connection_t;
 
 
@@ -135,7 +135,7 @@
 };
 
 
-ngx_resolver_t *ngx_resolver_create(ngx_conf_t *cf, ngx_peer_addr_t *addr);
+ngx_resolver_t *ngx_resolver_create(ngx_conf_t *cf, ngx_addr_t *addr);
 ngx_resolver_ctx_t *ngx_resolve_start(ngx_resolver_t *r,
     ngx_resolver_ctx_t *temp);
 ngx_int_t ngx_resolve_name(ngx_resolver_ctx_t *ctx);
--- a/src/core/ngx_string.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_string.c	Mon Apr 25 04:22:17 2011 +0400
@@ -10,15 +10,18 @@
 
 static u_char *ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64,
     u_char zero, ngx_uint_t hexadecimal, ngx_uint_t width);
+static ngx_int_t ngx_decode_base64_internal(ngx_str_t *dst, ngx_str_t *src,
+    const u_char *basis);
 
 
 void
 ngx_strlow(u_char *dst, u_char *src, size_t n)
 {
-    while (n--) {
+    while (n) {
         *dst = ngx_tolower(*src);
         dst++;
         src++;
+        n--;
     }
 }
 
@@ -74,7 +77,7 @@
  *    %[0][width][u][x|X]D      int32_t/uint32_t
  *    %[0][width][u][x|X]L      int64_t/uint64_t
  *    %[0][width|m][u][x|X]A    ngx_atomic_int_t/ngx_atomic_uint_t
- *    %[0][width][.width]f      float
+ *    %[0][width][.width]f      double, max valid number fits to %18.15f
  *    %P                        ngx_pid_t
  *    %M                        ngx_msec_t
  *    %r                        rlim_t
@@ -142,12 +145,12 @@
 {
     u_char                *p, zero;
     int                    d;
-    float                  f, scale;
+    double                 f, scale;
     size_t                 len, slen;
     int64_t                i64;
     uint64_t               ui64;
     ngx_msec_t             ms;
-    ngx_uint_t             width, sign, hex, max_width, frac_width, i;
+    ngx_uint_t             width, sign, hex, max_width, frac_width, n;
     ngx_str_t             *v;
     ngx_variable_value_t  *vv;
 
@@ -228,9 +231,7 @@
             case 'V':
                 v = va_arg(args, ngx_str_t *);
 
-                len = v->len;
-                len = (buf + len < last) ? len : (size_t) (last - buf);
-
+                len = ngx_min(((size_t) (last - buf)), v->len);
                 buf = ngx_cpymem(buf, v->data, len);
                 fmt++;
 
@@ -239,9 +240,7 @@
             case 'v':
                 vv = va_arg(args, ngx_variable_value_t *);
 
-                len = vv->len;
-                len = (buf + len < last) ? len : (size_t) (last - buf);
-
+                len = ngx_min(((size_t) (last - buf)), vv->len);
                 buf = ngx_cpymem(buf, vv->data, len);
                 fmt++;
 
@@ -256,8 +255,7 @@
                     }
 
                 } else {
-                    len = (buf + slen < last) ? slen : (size_t) (last - buf);
-
+                    len = ngx_min(((size_t) (last - buf)), slen);
                     buf = ngx_cpymem(buf, p, len);
                 }
 
@@ -358,7 +356,7 @@
                 break;
 
             case 'f':
-                f = (float) va_arg(args, double);
+                f = va_arg(args, double);
 
                 if (f < 0) {
                     *buf++ = '-';
@@ -377,7 +375,7 @@
 
                     scale = 1.0;
 
-                    for (i = 0; i < frac_width; i++) {
+                    for (n = frac_width; n; n--) {
                         scale *= 10.0;
                     }
 
@@ -385,7 +383,7 @@
                      * (int64_t) cast is required for msvc6:
                      * it can not convert uint64_t to double
                      */
-                    ui64 = (uint64_t) ((f - (int64_t) ui64) * scale);
+                    ui64 = (uint64_t) ((f - (int64_t) ui64) * scale + 0.5);
 
                     buf = ngx_sprintf_num(buf, last, ui64, '0', 0, frac_width);
                 }
@@ -876,6 +874,56 @@
 }
 
 
+/* parse a fixed point number, e.g., ngx_atofp("10.5", 4, 2) returns 1050 */
+
+ngx_int_t
+ngx_atofp(u_char *line, size_t n, size_t point)
+{
+    ngx_int_t   value;
+    ngx_uint_t  dot;
+
+    if (n == 0) {
+        return NGX_ERROR;
+    }
+
+    dot = 0;
+
+    for (value = 0; n--; line++) {
+
+        if (point == 0) {
+            return NGX_ERROR;
+        }
+
+        if (*line == '.') {
+            if (dot) {
+                return NGX_ERROR;
+            }
+
+            dot = 1;
+            continue;
+        }
+
+        if (*line < '0' || *line > '9') {
+            return NGX_ERROR;
+        }
+
+        value = value * 10 + (*line - '0');
+        point -= dot;
+    }
+
+    while (point--) {
+        value = value * 10;
+    }
+
+    if (value < 0) {
+        return NGX_ERROR;
+
+    } else {
+        return value;
+    }
+}
+
+
 ssize_t
 ngx_atosz(u_char *line, size_t n)
 {
@@ -1049,8 +1097,6 @@
 ngx_int_t
 ngx_decode_base64(ngx_str_t *dst, ngx_str_t *src)
 {
-    size_t          len;
-    u_char         *d, *s;
     static u_char   basis64[] = {
         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
@@ -1071,12 +1117,49 @@
         77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77
     };
 
+    return ngx_decode_base64_internal(dst, src, basis64);
+}
+
+
+ngx_int_t
+ngx_decode_base64url(ngx_str_t *dst, ngx_str_t *src)
+{
+    static u_char   basis64[] = {
+        77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+        77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+        77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 62, 77, 77,
+        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 77, 77, 77, 77, 77, 77,
+        77,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+        15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 77, 77, 77, 77, 63,
+        77, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 77, 77, 77, 77, 77,
+
+        77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+        77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+        77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+        77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+        77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+        77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+        77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+        77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77
+    };
+
+    return ngx_decode_base64_internal(dst, src, basis64);
+}
+
+
+static ngx_int_t
+ngx_decode_base64_internal(ngx_str_t *dst, ngx_str_t *src, const u_char *basis)
+{
+    size_t          len;
+    u_char         *d, *s;
+
     for (len = 0; len < src->len; len++) {
         if (src->data[len] == '=') {
             break;
         }
 
-        if (basis64[src->data[len]] == 77) {
+        if (basis[src->data[len]] == 77) {
             return NGX_ERROR;
         }
     }
@@ -1089,20 +1172,20 @@
     d = dst->data;
 
     while (len > 3) {
-        *d++ = (u_char) (basis64[s[0]] << 2 | basis64[s[1]] >> 4);
-        *d++ = (u_char) (basis64[s[1]] << 4 | basis64[s[2]] >> 2);
-        *d++ = (u_char) (basis64[s[2]] << 6 | basis64[s[3]]);
+        *d++ = (u_char) (basis[s[0]] << 2 | basis[s[1]] >> 4);
+        *d++ = (u_char) (basis[s[1]] << 4 | basis[s[2]] >> 2);
+        *d++ = (u_char) (basis[s[2]] << 6 | basis[s[3]]);
 
         s += 4;
         len -= 4;
     }
 
     if (len > 1) {
-        *d++ = (u_char) (basis64[s[0]] << 2 | basis64[s[1]] >> 4);
+        *d++ = (u_char) (basis[s[0]] << 2 | basis[s[1]] >> 4);
     }
 
     if (len > 2) {
-        *d++ = (u_char) (basis64[s[1]] << 4 | basis64[s[2]] >> 2);
+        *d++ = (u_char) (basis[s[1]] << 4 | basis[s[2]] >> 2);
     }
 
     dst->len = d - dst->data;
@@ -1238,10 +1321,8 @@
             break;
         }
 
-        len--;
-
         while (src < next) {
-            *++dst = *++src;
+            *dst++ = *src++;
             len--;
         }
     }
@@ -1255,7 +1336,7 @@
 uintptr_t
 ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type)
 {
-    ngx_uint_t      i, n;
+    ngx_uint_t      n;
     uint32_t       *escape;
     static u_char   hex[] = "0123456789abcdef";
 
@@ -1279,13 +1360,13 @@
         0xffffffff  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
     };
 
-                    /* " ", "#", "%", "+", "?", %00-%1F, %7F-%FF */
+                    /* " ", "#", "%", "&", "+", "?", %00-%1F, %7F-%FF */
 
     static uint32_t   args[] = {
         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
 
                     /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
-        0x80000829, /* 1000 0000 0000 0000  0000 1000 0010 1001 */
+        0x88000869, /* 1000 1000 0000 0000  0000 1000 0110 1001 */
 
                     /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
         0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
@@ -1373,17 +1454,18 @@
 
         n = 0;
 
-        for (i = 0; i < size; i++) {
+        while (size) {
             if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
                 n++;
             }
             src++;
+            size--;
         }
 
         return (uintptr_t) n;
     }
 
-    for (i = 0; i < size; i++) {
+    while (size) {
         if (escape[*src >> 5] & (1 << (*src & 0x1f))) {
             *dst++ = '%';
             *dst++ = hex[*src >> 4];
@@ -1393,6 +1475,7 @@
         } else {
             *dst++ = *src++;
         }
+        size--;
     }
 
     return (uintptr_t) dst;
@@ -1533,13 +1616,13 @@
 ngx_escape_html(u_char *dst, u_char *src, size_t size)
 {
     u_char      ch;
-    ngx_uint_t  i, len;
+    ngx_uint_t  len;
 
     if (dst == NULL) {
 
         len = 0;
 
-        for (i = 0; i < size; i++) {
+        while (size) {
             switch (*src++) {
 
             case '<':
@@ -1557,12 +1640,13 @@
             default:
                 break;
             }
+            size--;
         }
 
         return (uintptr_t) len;
     }
 
-    for (i = 0; i < size; i++) {
+    while (size) {
         ch = *src++;
 
         switch (ch) {
@@ -1584,12 +1668,96 @@
             *dst++ = ch;
             break;
         }
+        size--;
     }
 
     return (uintptr_t) dst;
 }
 
 
+void
+ngx_str_rbtree_insert_value(ngx_rbtree_node_t *temp,
+    ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
+{
+    ngx_str_node_t      *n, *t;
+    ngx_rbtree_node_t  **p;
+
+    for ( ;; ) {
+
+        n = (ngx_str_node_t *) node;
+        t = (ngx_str_node_t *) temp;
+
+        if (node->key != temp->key) {
+
+            p = (node->key < temp->key) ? &temp->left : &temp->right;
+
+        } else if (n->str.len != t->str.len) {
+
+            p = (n->str.len < t->str.len) ? &temp->left : &temp->right;
+
+        } else {
+            p = (ngx_memcmp(n->str.data, t->str.data, n->str.len) < 0)
+                 ? &temp->left : &temp->right;
+        }
+
+        if (*p == sentinel) {
+            break;
+        }
+
+        temp = *p;
+    }
+
+    *p = node;
+    node->parent = temp;
+    node->left = sentinel;
+    node->right = sentinel;
+    ngx_rbt_red(node);
+}
+
+
+ngx_str_node_t *
+ngx_str_rbtree_lookup(ngx_rbtree_t *rbtree, ngx_str_t *val, uint32_t hash)
+{
+    ngx_int_t           rc;
+    ngx_str_node_t     *n;
+    ngx_rbtree_node_t  *node, *sentinel;
+
+    node = rbtree->root;
+    sentinel = rbtree->sentinel;
+
+    while (node != sentinel) {
+
+        n = (ngx_str_node_t *) node;
+
+        if (hash != node->key) {
+            node = (hash < node->key) ? node->left : node->right;
+            continue;
+        }
+
+        if (val->len != n->str.len) {
+            node = (val->len < n->str.len) ? node->left : node->right;
+            continue;
+        }
+
+        rc = ngx_memcmp(val->data, n->str.data, val->len);
+
+        if (rc < 0) {
+            node = node->left;
+            continue;
+        }
+
+        if (rc > 0) {
+            node = node->right;
+            continue;
+        }
+
+        return n;
+    }
+
+    return NULL;
+}
+
+
 /* ngx_sort() is implemented as insertion sort because we need stable sort */
 
 void
--- a/src/core/ngx_string.h	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_string.h	Mon Apr 25 04:22:17 2011 +0400
@@ -38,6 +38,9 @@
 
 #define ngx_string(str)     { sizeof(str) - 1, (u_char *) str }
 #define ngx_null_string     { 0, NULL }
+#define ngx_str_set(str, text)                                               \
+    (str)->len = sizeof(text) - 1; (str)->data = (u_char *) text
+#define ngx_str_null(str)   (str)->len = 0; (str)->data = NULL
 
 
 #define ngx_tolower(c)      (u_char) ((c >= 'A' && c <= 'Z') ? (c | 0x20) : c)
@@ -86,7 +89,7 @@
 #if (NGX_MEMCPY_LIMIT)
 
 void *ngx_memcpy(void *dst, void *src, size_t n);
-#define ngx_cpymem(dst, src, n)   ((u_char *) ngx_memcpy(dst, src, n)) + (n)
+#define ngx_cpymem(dst, src, n)   (((u_char *) ngx_memcpy(dst, src, n)) + (n))
 
 #else
 
@@ -96,7 +99,7 @@
  * icc8 compile memcpy(d, s, 4) to the inline "mov"es or XMM moves.
  */
 #define ngx_memcpy(dst, src, n)   (void) memcpy(dst, src, n)
-#define ngx_cpymem(dst, src, n)   ((u_char *) memcpy(dst, src, n)) + (n)
+#define ngx_cpymem(dst, src, n)   (((u_char *) memcpy(dst, src, n)) + (n))
 
 #endif
 
@@ -132,6 +135,10 @@
 #endif
 
 
+#define ngx_memmove(dst, src, n)   (void) memmove(dst, src, n)
+#define ngx_movemem(dst, src, n)   (((u_char *) memmove(dst, src, n)) + (n))
+
+
 /* msvc and icc7 compile memcmp() to the inline loop */
 #define ngx_memcmp(s1, s2, n)  memcmp((const char *) s1, (const char *) s2, n)
 
@@ -161,6 +168,7 @@
 ngx_int_t ngx_dns_strcmp(u_char *s1, u_char *s2);
 
 ngx_int_t ngx_atoi(u_char *line, size_t n);
+ngx_int_t ngx_atofp(u_char *line, size_t n, size_t point);
 ssize_t ngx_atosz(u_char *line, size_t n);
 off_t ngx_atoof(u_char *line, size_t n);
 time_t ngx_atotm(u_char *line, size_t n);
@@ -174,6 +182,7 @@
 
 void ngx_encode_base64(ngx_str_t *dst, ngx_str_t *src);
 ngx_int_t ngx_decode_base64(ngx_str_t *dst, ngx_str_t *src);
+ngx_int_t ngx_decode_base64url(ngx_str_t *dst, ngx_str_t *src);
 
 uint32_t ngx_utf8_decode(u_char **p, size_t n);
 size_t ngx_utf8_length(u_char *p, size_t n);
@@ -196,6 +205,17 @@
 uintptr_t ngx_escape_html(u_char *dst, u_char *src, size_t size);
 
 
+typedef struct {
+    ngx_rbtree_node_t         node;
+    ngx_str_t                 str;
+} ngx_str_node_t;
+
+
+void ngx_str_rbtree_insert_value(ngx_rbtree_node_t *temp,
+    ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
+ngx_str_node_t *ngx_str_rbtree_lookup(ngx_rbtree_t *rbtree, ngx_str_t *name,
+    uint32_t hash);
+
 
 void ngx_sort(void *base, size_t n, size_t size,
     ngx_int_t (*cmp)(const void *, const void *));
--- a/src/core/ngx_times.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_times.c	Mon Apr 25 04:22:17 2011 +0400
@@ -27,6 +27,18 @@
 volatile ngx_str_t       ngx_cached_err_log_time;
 volatile ngx_str_t       ngx_cached_http_time;
 volatile ngx_str_t       ngx_cached_http_log_time;
+volatile ngx_str_t       ngx_cached_http_log_iso8601;
+
+#if !(NGX_WIN32)
+
+/*
+ * locatime() and localtime_r() are not Async-Signal-Safe functions, therefore,
+ * they must not be called by a signal handler, so we use the cached
+ * GMT offset value. Fortunately the value is changed only two times a year.
+ */
+
+static ngx_int_t         cached_gmtoff;
+#endif
 
 static ngx_time_t        cached_time[NGX_TIME_SLOTS];
 static u_char            cached_err_log_time[NGX_TIME_SLOTS]
@@ -35,6 +47,8 @@
                                     [sizeof("Mon, 28 Sep 1970 06:00:00 GMT")];
 static u_char            cached_http_log_time[NGX_TIME_SLOTS]
                                     [sizeof("28/Sep/1970:12:00:00 +0600")];
+static u_char            cached_http_log_iso8601[NGX_TIME_SLOTS]
+                                    [sizeof("1970-09-28T12:00:00+06:00")];
 
 
 static char  *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
@@ -47,18 +61,21 @@
     ngx_cached_err_log_time.len = sizeof("1970/09/28 12:00:00") - 1;
     ngx_cached_http_time.len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1;
     ngx_cached_http_log_time.len = sizeof("28/Sep/1970:12:00:00 +0600") - 1;
+    ngx_cached_http_log_iso8601.len = sizeof("1970-09-28T12:00:00+06:00") - 1;
 
     ngx_cached_time = &cached_time[0];
 
-    ngx_time_update(0, 0);
+    ngx_time_update();
 }
 
 
 void
-ngx_time_update(time_t sec, ngx_uint_t msec)
+ngx_time_update(void)
 {
-    u_char          *p0, *p1, *p2;
+    u_char          *p0, *p1, *p2, *p3;
     ngx_tm_t         tm, gmt;
+    time_t           sec;
+    ngx_uint_t       msec;
     ngx_time_t      *tp;
     struct timeval   tv;
 
@@ -66,12 +83,10 @@
         return;
     }
 
-    if (sec == 0) {
-        ngx_gettimeofday(&tv);
+    ngx_gettimeofday(&tv);
 
-        sec = tv.tv_sec;
-        msec = tv.tv_usec / 1000;
-    }
+    sec = tv.tv_sec;
+    msec = tv.tv_usec / 1000;
 
     ngx_current_msec = (ngx_msec_t) sec * 1000 + msec;
 
@@ -112,12 +127,14 @@
 #elif (NGX_HAVE_GMTOFF)
 
     ngx_localtime(sec, &tm);
-    tp->gmtoff = (ngx_int_t) (tm.ngx_tm_gmtoff / 60);
+    cached_gmtoff = (ngx_int_t) (tm.ngx_tm_gmtoff / 60);
+    tp->gmtoff = cached_gmtoff;
 
 #else
 
     ngx_localtime(sec, &tm);
-    tp->gmtoff = ngx_timezone(tm.ngx_tm_isdst);
+    cached_gmtoff = ngx_timezone(tm.ngx_tm_isdst);
+    tp->gmtoff = cached_gmtoff;
 
 #endif
 
@@ -139,6 +156,15 @@
                        tp->gmtoff < 0 ? '-' : '+',
                        ngx_abs(tp->gmtoff / 60), ngx_abs(tp->gmtoff % 60));
 
+    p3 = &cached_http_log_iso8601[slot][0];
+
+    (void) ngx_sprintf(p3, "%4d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
+                       tm.ngx_tm_year, tm.ngx_tm_mon,
+                       tm.ngx_tm_mday, tm.ngx_tm_hour,
+                       tm.ngx_tm_min, tm.ngx_tm_sec,
+                       tp->gmtoff < 0 ? '-' : '+',
+                       ngx_abs(tp->gmtoff / 60), ngx_abs(tp->gmtoff % 60));
+
 
     ngx_memory_barrier();
 
@@ -146,11 +172,63 @@
     ngx_cached_http_time.data = p0;
     ngx_cached_err_log_time.data = p1;
     ngx_cached_http_log_time.data = p2;
+    ngx_cached_http_log_iso8601.data = p3;
 
     ngx_unlock(&ngx_time_lock);
 }
 
 
+#if !(NGX_WIN32)
+
+void
+ngx_time_sigsafe_update(void)
+{
+    u_char          *p;
+    ngx_tm_t         tm;
+    time_t           sec;
+    ngx_time_t      *tp;
+    struct timeval   tv;
+
+    if (!ngx_trylock(&ngx_time_lock)) {
+        return;
+    }
+
+    ngx_gettimeofday(&tv);
+
+    sec = tv.tv_sec;
+
+    tp = &cached_time[slot];
+
+    if (tp->sec == sec) {
+        ngx_unlock(&ngx_time_lock);
+        return;
+    }
+
+    if (slot == NGX_TIME_SLOTS - 1) {
+        slot = 0;
+    } else {
+        slot++;
+    }
+
+    ngx_gmtime(sec + cached_gmtoff * 60, &tm);
+
+    p = &cached_err_log_time[slot][0];
+
+    (void) ngx_sprintf(p, "%4d/%02d/%02d %02d:%02d:%02d",
+                       tm.ngx_tm_year, tm.ngx_tm_mon,
+                       tm.ngx_tm_mday, tm.ngx_tm_hour,
+                       tm.ngx_tm_min, tm.ngx_tm_sec);
+
+    ngx_memory_barrier();
+
+    ngx_cached_err_log_time.data = p;
+
+    ngx_unlock(&ngx_time_lock);
+}
+
+#endif
+
+
 u_char *
 ngx_http_time(u_char *buf, time_t t)
 {
--- a/src/core/ngx_times.h	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/core/ngx_times.h	Mon Apr 25 04:22:17 2011 +0400
@@ -20,7 +20,8 @@
 
 
 void ngx_time_init(void);
-void ngx_time_update(time_t sec, ngx_uint_t msec);
+void ngx_time_update(void);
+void ngx_time_sigsafe_update(void);
 u_char *ngx_http_time(u_char *buf, time_t t);
 u_char *ngx_http_cookie_time(u_char *buf, time_t t);
 void ngx_gmtime(time_t t, ngx_tm_t *tp);
@@ -37,6 +38,7 @@
 extern volatile ngx_str_t    ngx_cached_err_log_time;
 extern volatile ngx_str_t    ngx_cached_http_time;
 extern volatile ngx_str_t    ngx_cached_http_log_time;
+extern volatile ngx_str_t    ngx_cached_http_log_iso8601;
 
 /*
  * milliseconds elapsed since epoch and truncated to ngx_msec_t,
--- a/src/event/modules/ngx_devpoll_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/event/modules/ngx_devpoll_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -371,8 +371,8 @@
 
     err = (events == -1) ? ngx_errno : 0;
 
-    if (flags & NGX_UPDATE_TIME) {
-        ngx_time_update(0, 0);
+    if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
+        ngx_time_update();
     }
 
     if (err) {
--- a/src/event/modules/ngx_epoll_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/event/modules/ngx_epoll_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -531,8 +531,8 @@
 
     err = (events == -1) ? ngx_errno : 0;
 
-    if (flags & NGX_UPDATE_TIME) {
-        ngx_time_update(0, 0);
+    if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
+        ngx_time_update();
     }
 
     if (err) {
--- a/src/event/modules/ngx_eventport_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/event/modules/ngx_eventport_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -405,7 +405,7 @@
     err = ngx_errno;
 
     if (flags & NGX_UPDATE_TIME) {
-        ngx_time_update(0, 0);
+        ngx_time_update();
     }
 
     if (n == -1) {
@@ -439,7 +439,7 @@
     for (i = 0; i < events; i++) {
 
         if (event_list[i].portev_source == PORT_SOURCE_TIMER) {
-            ngx_time_update(0, 0);
+            ngx_time_update();
             continue;
         }
 
--- a/src/event/modules/ngx_kqueue_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/event/modules/ngx_kqueue_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -537,8 +537,8 @@
 
     err = (events == -1) ? ngx_errno : 0;
 
-    if (flags & NGX_UPDATE_TIME) {
-        ngx_time_update(0, 0);
+    if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
+        ngx_time_update();
     }
 
     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
@@ -589,7 +589,7 @@
 #if (NGX_HAVE_TIMER_EVENT)
 
         if (event_list[i].filter == EVFILT_TIMER) {
-            ngx_time_update(0, 0);
+            ngx_time_update();
             continue;
         }
 
--- a/src/event/modules/ngx_poll_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/event/modules/ngx_poll_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -72,7 +72,7 @@
         nevents = 0;
     }
 
-    if (ngx_process == NGX_PROCESS_WORKER
+    if (ngx_process >= NGX_PROCESS_WORKER
         || cycle->old_cycle == NULL
         || cycle->old_cycle->connection_n < cycle->connection_n)
     {
@@ -262,8 +262,8 @@
 
     err = (ready == -1) ? ngx_errno : 0;
 
-    if (flags & NGX_UPDATE_TIME) {
-        ngx_time_update(0, 0);
+    if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
+        ngx_time_update();
     }
 
     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
--- a/src/event/modules/ngx_rtsig_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/event/modules/ngx_rtsig_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -323,7 +323,7 @@
                        "rtsig signo:%d", signo);
 
         if (flags & NGX_UPDATE_TIME) {
-            ngx_time_update(0, 0);
+            ngx_time_update();
         }
 
         if (err == NGX_EAGAIN) {
@@ -349,7 +349,7 @@
                    signo, si.si_fd, si.si_band);
 
     if (flags & NGX_UPDATE_TIME) {
-        ngx_time_update(0, 0);
+        ngx_time_update();
     }
 
     rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module);
@@ -419,7 +419,7 @@
 
     } else if (signo == SIGALRM) {
 
-        ngx_time_update(0, 0);
+        ngx_time_update();
 
         return NGX_OK;
 
@@ -671,7 +671,7 @@
     }
 
     if (flags & NGX_UPDATE_TIME) {
-        ngx_time_update(0, 0);
+        ngx_time_update();
     }
 
     ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
--- a/src/event/modules/ngx_select_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/event/modules/ngx_select_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -81,7 +81,7 @@
         nevents = 0;
     }
 
-    if (ngx_process == NGX_PROCESS_WORKER
+    if (ngx_process >= NGX_PROCESS_WORKER
         || cycle->old_cycle == NULL
         || cycle->old_cycle->connection_n < cycle->connection_n)
     {
@@ -262,8 +262,8 @@
 
     err = (ready == -1) ? ngx_errno : 0;
 
-    if (flags & NGX_UPDATE_TIME) {
-        ngx_time_update(0, 0);
+    if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
+        ngx_time_update();
     }
 
     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
--- a/src/event/modules/ngx_win32_select_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/event/modules/ngx_win32_select_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -82,7 +82,7 @@
         nevents = 0;
     }
 
-    if (ngx_process == NGX_PROCESS_WORKER
+    if (ngx_process >= NGX_PROCESS_WORKER
         || cycle->old_cycle == NULL
         || cycle->old_cycle->connection_n < cycle->connection_n)
     {
@@ -269,7 +269,7 @@
     err = (ready == -1) ? ngx_socket_errno : 0;
 
     if (flags & NGX_UPDATE_TIME) {
-        ngx_time_update(0, 0);
+        ngx_time_update();
     }
 
     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
--- a/src/event/ngx_event.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/event/ngx_event.c	Mon Apr 25 04:22:17 2011 +0400
@@ -562,8 +562,6 @@
 {
     ngx_event_timer_alarm = 1;
 
-    ngx_time_update(0, 0);
-
 #if 1
     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, "timer signal");
 #endif
--- a/src/event/ngx_event_accept.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/event/ngx_event_accept.c	Mon Apr 25 04:22:17 2011 +0400
@@ -26,6 +26,9 @@
     ngx_connection_t  *c, *lc;
     ngx_event_conf_t  *ecf;
     u_char             sa[NGX_SOCKADDRLEN];
+#if (NGX_HAVE_ACCEPT4)
+    static ngx_uint_t  use_accept4 = 1;
+#endif
 
     ecf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_core_module);
 
@@ -46,7 +49,16 @@
     do {
         socklen = NGX_SOCKADDRLEN;
 
+#if (NGX_HAVE_ACCEPT4)
+        if (use_accept4) {
+            s = accept4(lc->fd, (struct sockaddr *) sa, &socklen,
+                        SOCK_NONBLOCK);
+        } else {
+            s = accept(lc->fd, (struct sockaddr *) sa, &socklen);
+        }
+#else
         s = accept(lc->fd, (struct sockaddr *) sa, &socklen);
+#endif
 
         if (s == -1) {
             err = ngx_socket_errno;
@@ -57,9 +69,22 @@
                 return;
             }
 
+#if (NGX_HAVE_ACCEPT4)
+            ngx_log_error((ngx_uint_t) ((err == NGX_ECONNABORTED) ?
+                                             NGX_LOG_ERR : NGX_LOG_ALERT),
+                          ev->log, err,
+                          use_accept4 ? "accept4() failed" : "accept() failed");
+
+            if (use_accept4 && err == NGX_ENOSYS) {
+                use_accept4 = 0;
+                ngx_inherited_nonblocking = 0;
+                continue;
+            }
+#else
             ngx_log_error((ngx_uint_t) ((err == NGX_ECONNABORTED) ?
                                              NGX_LOG_ERR : NGX_LOG_ALERT),
                           ev->log, err, "accept() failed");
+#endif
 
             if (err == NGX_ECONNABORTED) {
                 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
@@ -152,10 +177,20 @@
         c->socklen = socklen;
         c->listening = ls;
         c->local_sockaddr = ls->sockaddr;
-        c->local_socklen = ls->socklen;
 
         c->unexpected_eof = 1;
 
+#if (NGX_HAVE_UNIX_DOMAIN)
+        if (c->sockaddr->sa_family == AF_UNIX) {
+            c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
+            c->tcp_nodelay = NGX_TCP_NODELAY_DISABLED;
+#if (NGX_SOLARIS)
+            /* Solaris's sendfilev() supports AF_NCA, AF_INET, and AF_INET6 */
+            c->sendfile = 0;
+#endif
+        }
+#endif
+
         rev = c->read;
         wev = c->write;
 
--- a/src/event/ngx_event_connect.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/event/ngx_event_connect.c	Mon Apr 25 04:22:17 2011 +0400
@@ -54,15 +54,7 @@
         {
             ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
                           "setsockopt(SO_RCVBUF) failed");
-
-            ngx_free_connection(c);
-
-            if (ngx_close_socket(s) == -1) {
-                ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
-                              ngx_close_socket_n " failed");
-            }
-
-            return NGX_ERROR;
+            goto failed;
         }
     }
 
@@ -70,14 +62,16 @@
         ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
                       ngx_nonblocking_n " failed");
 
-        ngx_free_connection(c);
+        goto failed;
+    }
 
-        if (ngx_close_socket(s) == -1) {
-            ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
-                          ngx_close_socket_n " failed");
+    if (pc->local) {
+        if (bind(s, pc->local->sockaddr, pc->local->socklen) == -1) {
+            ngx_log_error(NGX_LOG_CRIT, pc->log, ngx_socket_errno,
+                          "bind(%V) failed", &pc->local->name);
+
+            goto failed;
         }
-
-        return NGX_ERROR;
     }
 
     c->recv = ngx_recv;
@@ -107,27 +101,22 @@
 
     pc->connection = c;
 
-    /*
-     * TODO: MT: - ngx_atomic_fetch_add()
-     *             or protection by critical section or mutex
-     *
-     * TODO: MP: - allocated in a shared memory
-     *           - ngx_atomic_fetch_add()
-     *             or protection by critical section or mutex
-     */
-
     c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
 
 #if (NGX_THREADS)
+
+    /* TODO: lock event when call completion handler */
+
     rev->lock = pc->lock;
     wev->lock = pc->lock;
     rev->own_lock = &c->lock;
     wev->own_lock = &c->lock;
+
 #endif
 
     if (ngx_add_conn) {
         if (ngx_add_conn(c) == NGX_ERROR) {
-            return NGX_ERROR;
+            goto failed;
         }
     }
 
@@ -199,7 +188,7 @@
         if (ngx_blocking(s) == -1) {
             ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
                           ngx_blocking_n " failed");
-            return NGX_ERROR;
+            goto failed;
         }
 
         /*
@@ -229,7 +218,7 @@
     }
 
     if (ngx_add_event(rev, NGX_READ_EVENT, event) != NGX_OK) {
-        return NGX_ERROR;
+        goto failed;
     }
 
     if (rc == -1) {
@@ -237,7 +226,7 @@
         /* NGX_EINPROGRESS */
 
         if (ngx_add_event(wev, NGX_WRITE_EVENT, event) != NGX_OK) {
-            return NGX_ERROR;
+            goto failed;
         }
 
         return NGX_AGAIN;
@@ -248,6 +237,17 @@
     wev->ready = 1;
 
     return NGX_OK;
+
+failed:
+
+    ngx_free_connection(c);
+
+    if (ngx_close_socket(s) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, pc->log, ngx_socket_errno,
+                      ngx_close_socket_n " failed");
+    }
+
+    return NGX_ERROR;
 }
 
 
--- a/src/event/ngx_event_connect.h	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/event/ngx_event_connect.h	Mon Apr 25 04:22:17 2011 +0400
@@ -55,6 +55,8 @@
     ngx_atomic_t                    *lock;
 #endif
 
+    ngx_addr_t                      *local;
+
     int                              rcvbuf;
 
     ngx_log_t                       *log;
@@ -70,5 +72,4 @@
 ngx_int_t ngx_event_get_peer(ngx_peer_connection_t *pc, void *data);
 
 
-
 #endif /* _NGX_EVENT_CONNECT_H_INCLUDED_ */
--- a/src/event/ngx_event_openssl.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/event/ngx_event_openssl.c	Mon Apr 25 04:22:17 2011 +0400
@@ -15,6 +15,8 @@
 
 
 static int ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
+static void ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where,
+    int ret);
 static void ngx_ssl_handshake_handler(ngx_event_t *ev);
 static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n);
 static void ngx_ssl_write_handler(ngx_event_t *wev);
@@ -104,6 +106,8 @@
 
     ENGINE_load_builtin_engines();
 
+    OpenSSL_add_all_algorithms();
+
     ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
 
     if (ngx_ssl_connection_index == -1) {
@@ -151,7 +155,6 @@
 
     SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG);
     SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG);
-    SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG);
 
     /* server side options */
 
@@ -175,6 +178,8 @@
 
     SSL_CTX_set_read_ahead(ssl->ctx, 1);
 
+    SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback);
+
     return NGX_OK;
 }
 
@@ -350,6 +355,22 @@
 }
 
 
+static void
+ngx_ssl_info_callback(const ngx_ssl_conn_t *ssl_conn, int where, int ret)
+{
+    ngx_connection_t  *c;
+
+    if (where & SSL_CB_HANDSHAKE_START) {
+        c = ngx_ssl_get_connection((ngx_ssl_conn_t *) ssl_conn);
+
+        if (c->ssl->handshaked) {
+            c->ssl->renegotiation = 1;
+            ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL renegotiation");
+        }
+    }
+}
+
+
 ngx_int_t
 ngx_ssl_generate_rsa512_key(ngx_ssl_t *ssl)
 {
@@ -539,6 +560,9 @@
 #if (NGX_DEBUG)
         {
         char         buf[129], *s, *d;
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+        const
+#endif
         SSL_CIPHER  *cipher;
 
         cipher = SSL_get_current_cipher(c->ssl->connection);
@@ -587,6 +611,11 @@
         c->recv_chain = ngx_ssl_recv_chain;
         c->send_chain = ngx_ssl_send_chain;
 
+        /* initial handshake done, disable renegotiation (CVE-2009-3555) */
+        if (c->ssl->connection->s3) {
+            c->ssl->connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
+        }
+
         return NGX_OK;
     }
 
@@ -789,6 +818,21 @@
     int        sslerr;
     ngx_err_t  err;
 
+    if (c->ssl->renegotiation) {
+        /*
+         * disable renegotiation (CVE-2009-3555):
+         * OpenSSL (at least up to 0.9.8l) does not handle disabled
+         * renegotiation gracefully, so drop connection here
+         */
+
+        ngx_log_error(NGX_LOG_NOTICE, c->log, 0, "SSL renegotiation disabled");
+
+        c->ssl->no_wait_shutdown = 1;
+        c->ssl->no_send_shutdown = 1;
+
+        return NGX_ERROR;
+    }
+
     if (n > 0) {
 
         if (c->ssl->saved_write_handler) {
@@ -946,7 +990,7 @@
 
     for ( ;; ) {
 
-        while (in && buf->last < buf->end) {
+        while (in && buf->last < buf->end && send < limit) {
             if (in->buf->last_buf || in->buf->flush) {
                 flush = 1;
             }
@@ -973,8 +1017,8 @@
             ngx_memcpy(buf->last, in->buf->pos, size);
 
             buf->last += size;
-
             in->buf->pos += size;
+            send += size;
 
             if (in->buf->pos == in->buf->last) {
                 in = in->next;
@@ -999,7 +1043,6 @@
         }
 
         buf->pos += n;
-        send += n;
         c->sent += n;
 
         if (n < size) {
@@ -1268,11 +1311,17 @@
         n = ERR_GET_REASON(ERR_peek_error());
 
             /* handshake failures */
-        if (n == SSL_R_DIGEST_CHECK_FAILED                           /*  149 */
+        if (n == SSL_R_BLOCK_CIPHER_PAD_IS_WRONG                     /*  129 */
+            || n == SSL_R_DIGEST_CHECK_FAILED                        /*  149 */
+            || n == SSL_R_LENGTH_MISMATCH                            /*  159 */
             || n == SSL_R_NO_CIPHERS_PASSED                          /*  182 */
+            || n == SSL_R_NO_CIPHERS_SPECIFIED                       /*  183 */
             || n == SSL_R_NO_SHARED_CIPHER                           /*  193 */
+            || n == SSL_R_RECORD_LENGTH_MISMATCH                     /*  213 */
             || n == SSL_R_UNEXPECTED_MESSAGE                         /*  244 */
             || n == SSL_R_UNEXPECTED_RECORD                          /*  245 */
+            || n == SSL_R_UNKNOWN_ALERT_TYPE                         /*  246 */
+            || n == SSL_R_UNKNOWN_PROTOCOL                           /*  252 */
             || n == SSL_R_WRONG_VERSION_NUMBER                       /*  267 */
             || n == SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC        /*  281 */
             || n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
@@ -1384,6 +1433,8 @@
         return NGX_OK;
     }
 
+    SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len);
+
     if (builtin_session_cache == NGX_SSL_NONE_SCACHE) {
 
         /*
@@ -1415,8 +1466,6 @@
 
     SSL_CTX_set_session_cache_mode(ssl->ctx, cache_mode);
 
-    SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len);
-
     if (builtin_session_cache != NGX_SSL_NO_BUILTIN_SCACHE) {
 
         if (builtin_session_cache != NGX_SSL_DFLT_BUILTIN_SCACHE) {
@@ -1588,7 +1637,7 @@
     hash = ngx_crc32_short(sess->session_id, sess->session_id_length);
 
     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
-                   "http ssl new session: %08XD:%d:%d",
+                   "ssl new session: %08XD:%d:%d",
                    hash, sess->session_id_length, len);
 
     sess_id->node.key = hash;
@@ -1651,7 +1700,7 @@
     *copy = 0;
 
     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
-                   "http ssl get session: %08XD:%d", hash, len);
+                   "ssl get session: %08XD:%d", hash, len);
 
     shm_zone = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn),
                                    ngx_ssl_session_cache_index);
@@ -1765,7 +1814,7 @@
     hash = ngx_crc32_short(id, len);
 
     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
-                   "http ssl remove session: %08XD:%uz", hash, len);
+                   "ssl remove session: %08XD:%uz", hash, len);
 
     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
 
@@ -1929,6 +1978,40 @@
 
 
 ngx_int_t
+ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
+{
+    int           len;
+    u_char       *p, *buf;
+    SSL_SESSION  *sess;
+
+    sess = SSL_get0_session(c->ssl->connection);
+
+    len = i2d_SSL_SESSION(sess, NULL);
+
+    buf = ngx_alloc(len, c->log);
+    if (buf == NULL) {
+        return NGX_ERROR;
+    }
+
+    s->len = 2 * len;
+    s->data = ngx_pnalloc(pool, 2 * len);
+    if (s->data == NULL) {
+        ngx_free(buf);
+        return NGX_ERROR;
+    }
+
+    p = buf;
+    i2d_SSL_SESSION(sess, &p);
+
+    ngx_hex_dump(s->data, buf, len);
+
+    ngx_free(buf);
+
+    return NGX_OK;
+}
+
+
+ngx_int_t
 ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
 {
     size_t   len;
@@ -2151,21 +2234,17 @@
     X509  *cert;
 
     if (SSL_get_verify_result(c->ssl->connection) != X509_V_OK) {
-        s->len = sizeof("FAILED") - 1;
-        s->data = (u_char *) "FAILED";
-
+        ngx_str_set(s, "FAILED");
         return NGX_OK;
     }
 
     cert = SSL_get_peer_certificate(c->ssl->connection);
 
     if (cert) {
-        s->len = sizeof("SUCCESS") - 1;
-        s->data = (u_char *) "SUCCESS";
+        ngx_str_set(s, "SUCCESS");
 
     } else {
-        s->len = sizeof("NONE") - 1;
-        s->data = (u_char *) "NONE";
+        ngx_str_set(s, "NONE");
     }
 
     X509_free(cert);
@@ -2237,5 +2316,6 @@
 static void
 ngx_openssl_exit(ngx_cycle_t *cycle)
 {
+    EVP_cleanup();
     ENGINE_cleanup();
 }
--- a/src/event/ngx_event_openssl.h	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/event/ngx_event_openssl.h	Mon Apr 25 04:22:17 2011 +0400
@@ -15,6 +15,7 @@
 #include <openssl/err.h>
 #include <openssl/conf.h>
 #include <openssl/engine.h>
+#include <openssl/evp.h>
 
 #define NGX_SSL_NAME     "OpenSSL"
 
@@ -41,6 +42,7 @@
     ngx_event_handler_pt        saved_write_handler;
 
     unsigned                    handshaked:1;
+    unsigned                    renegotiation:1;
     unsigned                    buffer:1;
     unsigned                    no_wait_shutdown:1;
     unsigned                    no_send_shutdown:1;
@@ -118,6 +120,8 @@
     ngx_str_t *s);
 ngx_int_t ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool,
     ngx_str_t *s);
+ngx_int_t ngx_ssl_get_session_id(ngx_connection_t *c, ngx_pool_t *pool,
+    ngx_str_t *s);
 ngx_int_t ngx_ssl_get_raw_certificate(ngx_connection_t *c, ngx_pool_t *pool,
     ngx_str_t *s);
 ngx_int_t ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool,
--- a/src/http/modules/ngx_http_access_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/http/modules/ngx_http_access_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -10,18 +10,37 @@
 
 
 typedef struct {
-    in_addr_t     mask;
-    in_addr_t     addr;
-    ngx_uint_t    deny;      /* unsigned  deny:1; */
+    in_addr_t         mask;
+    in_addr_t         addr;
+    ngx_uint_t        deny;      /* unsigned  deny:1; */
 } ngx_http_access_rule_t;
 
+#if (NGX_HAVE_INET6)
 
 typedef struct {
-    ngx_array_t  *rules;     /* array of ngx_http_access_rule_t */
+    struct in6_addr   addr;
+    struct in6_addr   mask;
+    ngx_uint_t        deny;      /* unsigned  deny:1; */
+} ngx_http_access_rule6_t;
+
+#endif
+
+typedef struct {
+    ngx_array_t      *rules;     /* array of ngx_http_access_rule_t */
+#if (NGX_HAVE_INET6)
+    ngx_array_t      *rules6;    /* array of ngx_http_access_rule6_t */
+#endif
 } ngx_http_access_loc_conf_t;
 
 
 static ngx_int_t ngx_http_access_handler(ngx_http_request_t *r);
+static ngx_int_t ngx_http_access_inet(ngx_http_request_t *r,
+    ngx_http_access_loc_conf_t *alcf, in_addr_t addr);
+#if (NGX_HAVE_INET6)
+static ngx_int_t ngx_http_access_inet6(ngx_http_request_t *r,
+    ngx_http_access_loc_conf_t *alcf, u_char *p);
+#endif
+static ngx_int_t ngx_http_access_found(ngx_http_request_t *r, ngx_uint_t deny);
 static char *ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
 static void *ngx_http_access_create_loc_conf(ngx_conf_t *cf);
@@ -87,46 +106,59 @@
 static ngx_int_t
 ngx_http_access_handler(ngx_http_request_t *r)
 {
-    ngx_uint_t                   i;
     struct sockaddr_in          *sin;
-    ngx_http_access_rule_t      *rule;
-    ngx_http_core_loc_conf_t    *clcf;
     ngx_http_access_loc_conf_t  *alcf;
 
     alcf = ngx_http_get_module_loc_conf(r, ngx_http_access_module);
 
-    if (alcf->rules == NULL) {
-        return NGX_DECLINED;
+#if (NGX_HAVE_INET6)
+
+    if (alcf->rules6 && r->connection->sockaddr->sa_family == AF_INET6) {
+        u_char               *p;
+        in_addr_t             addr;
+        struct sockaddr_in6  *sin6;
+
+        sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
+        p = sin6->sin6_addr.s6_addr;
+
+        if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
+            addr = p[12] << 24;
+            addr += p[13] << 16;
+            addr += p[14] << 8;
+            addr += p[15];
+            return ngx_http_access_inet(r, alcf, htonl(addr));
+        }
+
+        return ngx_http_access_inet6(r, alcf, p);
     }
 
-    /* AF_INET only */
+#endif
 
-    if (r->connection->sockaddr->sa_family != AF_INET) {
-        return NGX_DECLINED;
+    if (alcf->rules && r->connection->sockaddr->sa_family == AF_INET) {
+        sin = (struct sockaddr_in *) r->connection->sockaddr;
+        return ngx_http_access_inet(r, alcf, sin->sin_addr.s_addr);
     }
 
-    sin = (struct sockaddr_in *) r->connection->sockaddr;
+    return NGX_DECLINED;
+}
+
+
+static ngx_int_t
+ngx_http_access_inet(ngx_http_request_t *r, ngx_http_access_loc_conf_t *alcf,
+    in_addr_t addr)
+{
+    ngx_uint_t               i;
+    ngx_http_access_rule_t  *rule;
 
     rule = alcf->rules->elts;
     for (i = 0; i < alcf->rules->nelts; i++) {
 
         ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                        "access: %08XD %08XD %08XD",
-                       sin->sin_addr.s_addr, rule[i].mask, rule[i].addr);
-
-        if ((sin->sin_addr.s_addr & rule[i].mask) == rule[i].addr) {
-            if (rule[i].deny) {
-                clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+                       addr, rule[i].mask, rule[i].addr);
 
-                if (clcf->satisfy == NGX_HTTP_SATISFY_ALL) {
-                    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                                  "access forbidden by rule");
-                }
-
-                return NGX_HTTP_FORBIDDEN;
-            }
-
-            return NGX_OK;
+        if ((addr & rule[i].mask) == rule[i].addr) {
+            return ngx_http_access_found(r, rule[i].deny);
         }
     }
 
@@ -134,62 +166,159 @@
 }
 
 
+#if (NGX_HAVE_INET6)
+
+static ngx_int_t
+ngx_http_access_inet6(ngx_http_request_t *r, ngx_http_access_loc_conf_t *alcf,
+    u_char *p)
+{
+    ngx_uint_t                n;
+    ngx_uint_t                i;
+    ngx_http_access_rule6_t  *rule6;
+
+    rule6 = alcf->rules6->elts;
+    for (i = 0; i < alcf->rules6->nelts; i++) {
+
+#if (NGX_DEBUG)
+        {
+        size_t  cl, ml, al;
+        u_char  ct[NGX_INET6_ADDRSTRLEN];
+        u_char  mt[NGX_INET6_ADDRSTRLEN];
+        u_char  at[NGX_INET6_ADDRSTRLEN];
+
+        cl = ngx_inet6_ntop(p, ct, NGX_INET6_ADDRSTRLEN);
+        ml = ngx_inet6_ntop(rule6[i].mask.s6_addr, mt, NGX_INET6_ADDRSTRLEN);
+        al = ngx_inet6_ntop(rule6[i].addr.s6_addr, at, NGX_INET6_ADDRSTRLEN);
+
+        ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                       "access: %*s %*s %*s", cl, ct, ml, mt, al, at);
+        }
+#endif
+
+        for (n = 0; n < 16; n++) {
+            if ((p[n] & rule6[i].mask.s6_addr[n]) != rule6[i].addr.s6_addr[n]) {
+                goto next;
+            }
+        }
+
+        return ngx_http_access_found(r, rule6[i].deny);
+
+    next:
+        continue;
+    }
+
+    return NGX_DECLINED;
+}
+
+#endif
+
+
+static ngx_int_t
+ngx_http_access_found(ngx_http_request_t *r, ngx_uint_t deny)
+{
+    ngx_http_core_loc_conf_t  *clcf;
+
+    if (deny) {
+        clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+        if (clcf->satisfy == NGX_HTTP_SATISFY_ALL) {
+            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                          "access forbidden by rule");
+        }
+
+        return NGX_HTTP_FORBIDDEN;
+    }
+
+    return NGX_OK;
+}
+
+
 static char *
 ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     ngx_http_access_loc_conf_t *alcf = conf;
 
-    ngx_int_t                rc;
-    ngx_str_t               *value;
-    ngx_cidr_t               cidr;
-    ngx_http_access_rule_t  *rule;
+    ngx_int_t                 rc;
+    ngx_uint_t                all;
+    ngx_str_t                *value;
+    ngx_cidr_t                cidr;
+    ngx_http_access_rule_t   *rule;
+#if (NGX_HAVE_INET6)
+    ngx_http_access_rule6_t  *rule6;
+#endif
 
-    if (alcf->rules == NULL) {
-        alcf->rules = ngx_array_create(cf->pool, 4,
-                                       sizeof(ngx_http_access_rule_t));
-        if (alcf->rules == NULL) {
-            return NGX_CONF_ERROR;
-        }
-    }
-
-    rule = ngx_array_push(alcf->rules);
-    if (rule == NULL) {
-        return NGX_CONF_ERROR;
-    }
+    ngx_memzero(&cidr, sizeof(ngx_cidr_t));
 
     value = cf->args->elts;
 
-    rule->deny = (value[0].data[0] == 'd') ? 1 : 0;
+    all = (value[1].len == 3 && ngx_strcmp(value[1].data, "all") == 0);
+
+    if (!all) {
+
+        rc = ngx_ptocidr(&value[1], &cidr);
 
-    if (value[1].len == 3 && ngx_strcmp(value[1].data, "all") == 0) {
-        rule->mask = 0;
-        rule->addr = 0;
+        if (rc == NGX_ERROR) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                         "invalid parameter \"%V\"", &value[1]);
+            return NGX_CONF_ERROR;
+        }
 
-        return NGX_CONF_OK;
+        if (rc == NGX_DONE) {
+            ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+                         "low address bits of %V are meaningless", &value[1]);
+        }
     }
 
-    rc = ngx_ptocidr(&value[1], &cidr);
+    switch (cidr.family) {
+
+#if (NGX_HAVE_INET6)
+    case AF_INET6:
+    case 0: /* all */
 
-    if (rc == NGX_ERROR) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
-                           &value[1]);
-        return NGX_CONF_ERROR;
-    }
+        if (alcf->rules6 == NULL) {
+            alcf->rules6 = ngx_array_create(cf->pool, 4,
+                                            sizeof(ngx_http_access_rule6_t));
+            if (alcf->rules6 == NULL) {
+                return NGX_CONF_ERROR;
+            }
+        }
+
+        rule6 = ngx_array_push(alcf->rules6);
+        if (rule6 == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        rule6->mask = cidr.u.in6.mask;
+        rule6->addr = cidr.u.in6.addr;
+        rule6->deny = (value[0].data[0] == 'd') ? 1 : 0;
 
-    if (cidr.family != AF_INET) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "\"allow\" supports IPv4 only");
-        return NGX_CONF_ERROR;
-    }
+        if (!all) {
+            break;
+        }
+
+        /* "all" passes through */
+#endif
+
+    default: /* AF_INET */
 
-    if (rc == NGX_DONE) {
-        ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
-                           "low address bits of %V are meaningless", &value[1]);
+        if (alcf->rules == NULL) {
+            alcf->rules = ngx_array_create(cf->pool, 4,
+                                           sizeof(ngx_http_access_rule_t));
+            if (alcf->rules == NULL) {
+                return NGX_CONF_ERROR;
+            }
+        }
+
+        rule = ngx_array_push(alcf->rules);
+        if (rule == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        rule->mask = cidr.u.in.mask;
+        rule->addr = cidr.u.in.addr;
+        rule->deny = (value[0].data[0] == 'd') ? 1 : 0;
     }
 
-    rule->mask = cidr.u.in.mask;
-    rule->addr = cidr.u.in.addr;
-
     return NGX_CONF_OK;
 }
 
@@ -218,6 +347,12 @@
         conf->rules = prev->rules;
     }
 
+#if (NGX_HAVE_INET6)
+    if (conf->rules6 == NULL) {
+        conf->rules6 = prev->rules6;
+    }
+#endif
+
     return NGX_CONF_OK;
 }
 
--- a/src/http/modules/ngx_http_addition_filter_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/http/modules/ngx_http_addition_filter_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -237,8 +237,8 @@
     ngx_conf_merge_str_value(conf->before_body, prev->before_body, "");
     ngx_conf_merge_str_value(conf->after_body, prev->after_body, "");
 
-    if (ngx_http_merge_types(cf, conf->types_keys, &conf->types,
-                             prev->types_keys, &prev->types,
+    if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
+                             &prev->types_keys, &prev->types,
                              ngx_http_html_default_types)
         != NGX_OK)
     {
--- a/src/http/modules/ngx_http_auth_basic_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/http/modules/ngx_http_auth_basic_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -248,7 +248,7 @@
 
         if (state == sw_passwd) {
             left = left + n - passwd;
-            ngx_memcpy(buf, &buf[passwd], left);
+            ngx_memmove(buf, &buf[passwd], left);
             passwd = 0;
 
         } else {
@@ -348,8 +348,7 @@
     }
 
     r->headers_out.www_authenticate->hash = 1;
-    r->headers_out.www_authenticate->key.len = sizeof("WWW-Authenticate") - 1;
-    r->headers_out.www_authenticate->key.data = (u_char *) "WWW-Authenticate";
+    ngx_str_set(&r->headers_out.www_authenticate->key, "WWW-Authenticate");
     r->headers_out.www_authenticate->value = *realm;
 
     return NGX_HTTP_UNAUTHORIZED;
@@ -425,9 +424,7 @@
     u_char  *basic, *p;
 
     if (ngx_strcmp(realm->data, "off") == 0) {
-        realm->len = 0;
-        realm->data = (u_char *) "";
-
+        ngx_str_set(realm, "");
         return NGX_CONF_OK;
     }
 
--- a/src/http/modules/ngx_http_autoindex_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/http/modules/ngx_http_autoindex_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -160,10 +160,6 @@
         return NGX_DECLINED;
     }
 
-    if (r->zero_in_uri) {
-        return NGX_DECLINED;
-    }
-
     if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
         return NGX_DECLINED;
     }
@@ -235,8 +231,7 @@
 
     r->headers_out.status = NGX_HTTP_OK;
     r->headers_out.content_type_len = sizeof("text/html") - 1;
-    r->headers_out.content_type.len = sizeof("text/html") - 1;
-    r->headers_out.content_type.data = (u_char *) "text/html";
+    ngx_str_set(&r->headers_out.content_type, "text/html");
 
     rc = ngx_http_send_header(r);
 
--- a/src/http/modules/ngx_http_charset_filter_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/http/modules/ngx_http_charset_filter_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -1550,8 +1550,8 @@
     ngx_http_charset_recode_t     *recode;
     ngx_http_charset_main_conf_t  *mcf;
 
-    if (ngx_http_merge_types(cf, conf->types_keys, &conf->types,
-                             prev->types_keys, &prev->types,
+    if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
+                             &prev->types_keys, &prev->types,
                              ngx_http_charset_default_types)
         != NGX_OK)
     {
--- a/src/http/modules/ngx_http_chunked_filter_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/http/modules/ngx_http_chunked_filter_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -50,9 +50,10 @@
 static ngx_int_t
 ngx_http_chunked_header_filter(ngx_http_request_t *r)
 {
+    ngx_http_core_loc_conf_t  *clcf;
+
     if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED
         || r->headers_out.status == NGX_HTTP_NO_CONTENT
-        || r->headers_out.status == NGX_HTTP_CREATED
         || r != r->main
         || (r->method & NGX_HTTP_HEAD))
     {
@@ -64,7 +65,14 @@
             r->keepalive = 0;
 
         } else {
-            r->chunked = 1;
+            clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+            if (clcf->chunked_transfer_encoding) {
+                r->chunked = 1;
+
+            } else {
+                r->keepalive = 0;
+            }
         }
     }
 
--- a/src/http/modules/ngx_http_dav_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/http/modules/ngx_http_dav_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -146,10 +146,6 @@
     ngx_int_t                 rc;
     ngx_http_dav_loc_conf_t  *dlcf;
 
-    if (r->zero_in_uri) {
-        return NGX_DECLINED;
-    }
-
     dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module);
 
     if (!(r->method & dlcf->methods)) {
@@ -325,13 +321,13 @@
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http delete filename: \"%s\"", path.data);
 
-    if (ngx_file_info(path.data, &fi) == NGX_FILE_ERROR) {
+    if (ngx_link_info(path.data, &fi) == NGX_FILE_ERROR) {
         err = ngx_errno;
 
         rc = (err == NGX_ENOTDIR) ? NGX_HTTP_CONFLICT : NGX_HTTP_NOT_FOUND;
 
         return ngx_http_dav_error(r->connection->log, err,
-                                  rc, ngx_file_info_n, path.data);
+                                  rc, ngx_link_info_n, path.data);
     }
 
     if (ngx_is_dir(&fi)) {
@@ -358,7 +354,7 @@
 
         /*
          * we do not need to test (r->uri.data[r->uri.len - 1] == '/')
-         * because ngx_file_info("/file/") returned NGX_ENOTDIR above
+         * because ngx_link_info("/file/") returned NGX_ENOTDIR above
          */
 
         depth = ngx_http_dav_depth(r, 0);
@@ -490,6 +486,7 @@
     p = ngx_http_map_uri_to_path(r, &path, &root, 0);
 
     *(p - 1) = '\0';
+    r->uri.len--;
 
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http mkcol path: \"%s\"", path.data);
@@ -516,8 +513,8 @@
     size_t                    len, root;
     ngx_err_t                 err;
     ngx_int_t                 rc, depth;
-    ngx_uint_t                overwrite, slash, dir;
-    ngx_str_t                 path, uri;
+    ngx_uint_t                overwrite, slash, dir, flags;
+    ngx_str_t                 path, uri, duri, args;
     ngx_tree_ctx_t            tree;
     ngx_copy_file_t           cf;
     ngx_file_info_t           fi;
@@ -538,6 +535,13 @@
         return NGX_HTTP_BAD_REQUEST;
     }
 
+    p = dest->value.data;
+    /* there is always '\0' even after empty header value */
+    if (p[0] == '/') {
+        last = p + dest->value.len;
+        goto destination_done;
+    }
+
     len = r->headers_in.server.len;
 
     if (len == 0) {
@@ -594,6 +598,14 @@
 
 destination_done:
 
+    duri.len = last - p;
+    duri.data = p;
+    flags = 0;
+
+    if (ngx_http_parse_unsafe_uri(r, &duri, &args, &flags) != NGX_OK) {
+        goto invalid_destination;
+    }
+
     if ((r->uri.data[r->uri.len - 1] == '/' && *(last - 1) != '/')
         || (r->uri.data[r->uri.len - 1] != '/' && *(last - 1) == '/'))
     {
@@ -656,9 +668,7 @@
                    "http copy from: \"%s\"", path.data);
 
     uri = r->uri;
-
-    r->uri.len = last - p;
-    r->uri.data = p;
+    r->uri = duri;
 
     ngx_http_map_uri_to_path(r, &copy.path, &root, 0);
 
@@ -678,12 +688,12 @@
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http copy to: \"%s\"", copy.path.data);
 
-    if (ngx_file_info(copy.path.data, &fi) == NGX_FILE_ERROR) {
+    if (ngx_link_info(copy.path.data, &fi) == NGX_FILE_ERROR) {
         err = ngx_errno;
 
         if (err != NGX_ENOENT) {
             return ngx_http_dav_error(r->connection->log, err,
-                                      NGX_HTTP_NOT_FOUND, ngx_file_info_n,
+                                      NGX_HTTP_NOT_FOUND, ngx_link_info_n,
                                       copy.path.data);
         }
 
@@ -712,9 +722,9 @@
         dir = ngx_is_dir(&fi);
     }
 
-    if (ngx_file_info(path.data, &fi) == NGX_FILE_ERROR) {
+    if (ngx_link_info(path.data, &fi) == NGX_FILE_ERROR) {
         return ngx_http_dav_error(r->connection->log, ngx_errno,
-                                  NGX_HTTP_NOT_FOUND, ngx_file_info_n,
+                                  NGX_HTTP_NOT_FOUND, ngx_link_info_n,
                                   path.data);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/http/modules/ngx_http_degradation_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -0,0 +1,242 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+typedef struct {
+    size_t      sbrk_size;
+} ngx_http_degradation_main_conf_t;
+
+
+typedef struct {
+    ngx_uint_t  degrade;
+} ngx_http_degradation_loc_conf_t;
+
+
+static ngx_conf_enum_t  ngx_http_degrade[] = {
+    { ngx_string("204"), 204 },
+    { ngx_string("444"), 444 },
+    { ngx_null_string, 0 }
+};
+
+
+static void *ngx_http_degradation_create_main_conf(ngx_conf_t *cf);
+static void *ngx_http_degradation_create_loc_conf(ngx_conf_t *cf);
+static char *ngx_http_degradation_merge_loc_conf(ngx_conf_t *cf, void *parent,
+    void *child);
+static char *ngx_http_degradation(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
+static ngx_int_t ngx_http_degradation_init(ngx_conf_t *cf);
+
+
+static ngx_command_t  ngx_http_degradation_commands[] = {
+
+    { ngx_string("degradation"),
+      NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
+      ngx_http_degradation,
+      NGX_HTTP_MAIN_CONF_OFFSET,
+      0,
+      NULL },
+
+    { ngx_string("degrade"),
+      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_degradation_loc_conf_t, degrade),
+      &ngx_http_degrade },
+
+      ngx_null_command
+};
+
+
+static ngx_http_module_t  ngx_http_degradation_module_ctx = {
+    NULL,                                  /* preconfiguration */
+    ngx_http_degradation_init,             /* postconfiguration */
+
+    ngx_http_degradation_create_main_conf, /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    ngx_http_degradation_create_loc_conf,  /* create location configuration */
+    ngx_http_degradation_merge_loc_conf    /* merge location configuration */
+};
+
+
+ngx_module_t  ngx_http_degradation_module = {
+    NGX_MODULE_V1,
+    &ngx_http_degradation_module_ctx,      /* module context */
+    ngx_http_degradation_commands,         /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    NULL,                                  /* init master */
+    NULL,                                  /* init module */
+    NULL,                                  /* init process */
+    NULL,                                  /* init thread */
+    NULL,                                  /* exit thread */
+    NULL,                                  /* exit process */
+    NULL,                                  /* exit master */
+    NGX_MODULE_V1_PADDING
+};
+
+
+static ngx_int_t
+ngx_http_degradation_handler(ngx_http_request_t *r)
+{
+    ngx_http_degradation_loc_conf_t  *dlcf;
+
+    dlcf = ngx_http_get_module_loc_conf(r, ngx_http_degradation_module);
+
+    if (dlcf->degrade && ngx_http_degraded(r)) {
+        return dlcf->degrade;
+    }
+
+    return NGX_DECLINED;
+}
+
+
+ngx_uint_t
+ngx_http_degraded(ngx_http_request_t *r)
+{
+    time_t                             now;
+    ngx_uint_t                         log;
+    static size_t                      sbrk_size;
+    static time_t                      sbrk_time;
+    ngx_http_degradation_main_conf_t  *dmcf;
+
+    dmcf = ngx_http_get_module_main_conf(r, ngx_http_degradation_module);
+
+    if (dmcf->sbrk_size) {
+
+        log = 0;
+        now = ngx_time();
+
+        /* lock mutex */
+
+        if (now != sbrk_time) {
+
+            /*
+             * ELF/i386 is loaded at 0x08000000, 128M
+             * ELF/amd64 is loaded at 0x00400000, 4M
+             *
+             * use a function address to substract the loading address
+             */
+
+            sbrk_size = (size_t) sbrk(0) - ((uintptr_t) ngx_palloc & ~0x3FFFFF);
+            sbrk_time = now;
+            log = 1;
+        }
+
+        /* unlock mutex */
+
+        if (sbrk_size >= dmcf->sbrk_size) {
+            if (log) {
+                ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
+                              "degradation sbrk:%uzM",
+                              sbrk_size / (1024 * 1024));
+            }
+
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+
+static void *
+ngx_http_degradation_create_main_conf(ngx_conf_t *cf)
+{
+    ngx_http_degradation_main_conf_t  *dmcf;
+
+    dmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_degradation_main_conf_t));
+    if (dmcf == NULL) {
+        return NULL;
+    }
+
+    return dmcf;
+}
+
+
+static void *
+ngx_http_degradation_create_loc_conf(ngx_conf_t *cf)
+{
+    ngx_http_degradation_loc_conf_t  *conf;
+
+    conf = ngx_palloc(cf->pool, sizeof(ngx_http_degradation_loc_conf_t));
+    if (conf == NULL) {
+        return NULL;
+    }
+
+    conf->degrade = NGX_CONF_UNSET_UINT;
+
+    return conf;
+}
+
+
+static char *
+ngx_http_degradation_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
+{
+    ngx_http_degradation_loc_conf_t  *prev = parent;
+    ngx_http_degradation_loc_conf_t  *conf = child;
+
+    ngx_conf_merge_uint_value(conf->degrade, prev->degrade, 0);
+
+    return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_degradation(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_degradation_main_conf_t  *dmcf = conf;
+
+    ngx_str_t  *value, s;
+
+    value = cf->args->elts;
+
+    if (ngx_strncmp(value[1].data, "sbrk=", 5) == 0) {
+
+        s.len = value[1].len - 5;
+        s.data = value[1].data + 5;
+
+        dmcf->sbrk_size = ngx_parse_size(&s);
+        if (dmcf->sbrk_size == (size_t) NGX_ERROR) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "invalid sbrk size \"%V\"", &value[1]);
+            return NGX_CONF_ERROR;
+        }
+
+        return NGX_CONF_OK;
+    }
+
+    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                       "invalid parameter \"%V\"", &value[1]);
+
+    return NGX_CONF_ERROR;
+}
+
+
+static ngx_int_t
+ngx_http_degradation_init(ngx_conf_t *cf)
+{
+    ngx_http_handler_pt        *h;
+    ngx_http_core_main_conf_t  *cmcf;
+
+    cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
+
+    h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers);
+    if (h == NULL) {
+        return NGX_ERROR;
+    }
+
+    *h = ngx_http_degradation_handler;
+
+    return NGX_OK;
+}
--- a/src/http/modules/ngx_http_empty_gif_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/http/modules/ngx_http_empty_gif_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -105,12 +105,14 @@
 };
 
 
+static ngx_str_t  ngx_http_gif_type = ngx_string("image/gif");
+
+
 static ngx_int_t
 ngx_http_empty_gif_handler(ngx_http_request_t *r)
 {
-    ngx_int_t     rc;
-    ngx_buf_t    *b;
-    ngx_chain_t   out;
+    ngx_int_t                 rc;
+    ngx_http_complex_value_t  cv;
 
     if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
         return NGX_HTTP_NOT_ALLOWED;
@@ -122,42 +124,13 @@
         return rc;
     }
 
-    r->headers_out.content_type_len = sizeof("image/gif") - 1;
-    r->headers_out.content_type.len = sizeof("image/gif") - 1;
-    r->headers_out.content_type.data = (u_char *) "image/gif";
-
-    if (r->method == NGX_HTTP_HEAD) {
-        r->headers_out.status = NGX_HTTP_OK;
-        r->headers_out.content_length_n = sizeof(ngx_empty_gif);
-        r->headers_out.last_modified_time = 23349600;
-
-        return ngx_http_send_header(r);
-    }
+    ngx_memzero(&cv, sizeof(ngx_http_complex_value_t));
 
-    b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
-    if (b == NULL) {
-        return NGX_HTTP_INTERNAL_SERVER_ERROR;
-    }
-
-    out.buf = b;
-    out.next = NULL;
-
-    b->pos = ngx_empty_gif;
-    b->last = ngx_empty_gif + sizeof(ngx_empty_gif);
-    b->memory = 1;
-    b->last_buf = 1;
-
-    r->headers_out.status = NGX_HTTP_OK;
-    r->headers_out.content_length_n = sizeof(ngx_empty_gif);
+    cv.value.len = sizeof(ngx_empty_gif);
+    cv.value.data = ngx_empty_gif;
     r->headers_out.last_modified_time = 23349600;
 
-    rc = ngx_http_send_header(r);
-
-    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
-        return rc;
-    }
-
-    return ngx_http_output_filter(r, &out);
+    return ngx_http_send_response(r, NGX_HTTP_OK, &ngx_http_gif_type, &cv);
 }
 
 
--- a/src/http/modules/ngx_http_fastcgi_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/http/modules/ngx_http_fastcgi_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -23,6 +23,9 @@
     ngx_array_t                   *fastcgi_lengths;
     ngx_array_t                   *fastcgi_values;
 
+    ngx_hash_t                     headers_hash;
+    ngx_uint_t                     header_params;
+
 #if (NGX_HTTP_CACHE)
     ngx_http_complex_value_t       cache_key;
 #endif
@@ -62,7 +65,8 @@
     size_t                         length;
     size_t                         padding;
 
-    ngx_uint_t                     fastcgi_stdout; /* unsigned :1 */
+    unsigned                       fastcgi_stdout:1;
+    unsigned                       large_stderr:1;
 
     ngx_array_t                   *split_parts;
 
@@ -161,11 +165,6 @@
 static char *ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post,
     void *data);
 
-static char *ngx_http_fastcgi_upstream_max_fails_unsupported(ngx_conf_t *cf,
-    ngx_command_t *cmd, void *conf);
-static char *ngx_http_fastcgi_upstream_fail_timeout_unsupported(ngx_conf_t *cf,
-    ngx_command_t *cmd, void *conf);
-
 
 static ngx_conf_post_t  ngx_http_fastcgi_lowat_post =
     { ngx_http_fastcgi_lowat_check };
@@ -184,15 +183,6 @@
 };
 
 
-static ngx_conf_bitmask_t  ngx_http_fastcgi_ignore_headers_masks[] = {
-    { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT },
-    { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES },
-    { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES },
-    { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL },
-    { ngx_null_string, 0 }
-};
-
-
 ngx_module_t  ngx_http_fastcgi_module;
 
 
@@ -240,6 +230,13 @@
       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.ignore_client_abort),
       NULL },
 
+    { ngx_string("fastcgi_bind"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_http_upstream_bind_set_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.local),
+      NULL },
+
     { ngx_string("fastcgi_connect_timeout"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_msec_slot,
@@ -313,14 +310,14 @@
 #if (NGX_HTTP_CACHE)
 
     { ngx_string("fastcgi_cache"),
-      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_http_fastcgi_cache,
       NGX_HTTP_LOC_CONF_OFFSET,
       0,
       NULL },
 
     { ngx_string("fastcgi_cache_key"),
-      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_http_fastcgi_cache_key,
       NGX_HTTP_LOC_CONF_OFFSET,
       0,
@@ -333,6 +330,20 @@
       0,
       &ngx_http_fastcgi_module },
 
+    { ngx_string("fastcgi_cache_bypass"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
+      ngx_http_set_predicate_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_bypass),
+      NULL },
+
+    { ngx_string("fastcgi_no_cache"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
+      ngx_http_set_predicate_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.no_cache),
+      NULL },
+
     { ngx_string("fastcgi_cache_valid"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
       ngx_http_file_cache_valid_set_slot,
@@ -391,20 +402,6 @@
       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream),
       &ngx_http_fastcgi_next_upstream_masks },
 
-    { ngx_string("fastcgi_upstream_max_fails"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_http_fastcgi_upstream_max_fails_unsupported,
-      0,
-      0,
-      NULL },
-
-    { ngx_string("fastcgi_upstream_fail_timeout"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_http_fastcgi_upstream_fail_timeout_unsupported,
-      0,
-      0,
-      NULL },
-
     { ngx_string("fastcgi_param"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
       ngx_conf_set_keyval_slot,
@@ -413,14 +410,14 @@
       NULL },
 
     { ngx_string("fastcgi_pass_header"),
-      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_str_array_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.pass_headers),
       NULL },
 
     { ngx_string("fastcgi_hide_header"),
-      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_str_array_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.hide_headers),
@@ -431,7 +428,7 @@
       ngx_conf_set_bitmask_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.ignore_headers),
-      &ngx_http_fastcgi_ignore_headers_masks },
+      &ngx_http_upstream_ignore_headers_masks },
 
     { ngx_string("fastcgi_catch_stderr"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
@@ -523,6 +520,21 @@
 };
 
 
+#if (NGX_HTTP_CACHE)
+
+static ngx_keyval_t  ngx_http_fastcgi_cache_headers[] = {
+    { ngx_string("HTTP_IF_MODIFIED_SINCE"), ngx_string("") },
+    { ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
+    { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("") },
+    { ngx_string("HTTP_IF_MATCH"), ngx_string("") },
+    { ngx_string("HTTP_RANGE"), ngx_string("") },
+    { ngx_string("HTTP_IF_RANGE"), ngx_string("") },
+    { ngx_null_string, ngx_null_string }
+};
+
+#endif
+
+
 static ngx_path_init_t  ngx_http_fastcgi_temp_path = {
     ngx_string(NGX_HTTP_FASTCGI_TEMP_PATH), { 1, 2, 0 }
 };
@@ -564,9 +576,7 @@
 
     u = r->upstream;
 
-    u->schema.len = sizeof("fastcgi://") - 1;
-    u->schema.data = (u_char *) "fastcgi://";
-
+    ngx_str_set(&u->schema, "fastcgi://");
     u->output.tag = (ngx_buf_tag_t) &ngx_http_fastcgi_module;
 
     u->conf = &flcf->upstream;
@@ -603,49 +613,46 @@
 static ngx_int_t
 ngx_http_fastcgi_eval(ngx_http_request_t *r, ngx_http_fastcgi_loc_conf_t *flcf)
 {
-    ngx_url_t  u;
-
-    ngx_memzero(&u, sizeof(ngx_url_t));
-
-    if (ngx_http_script_run(r, &u.url, flcf->fastcgi_lengths->elts, 0,
+    ngx_url_t             url;
+    ngx_http_upstream_t  *u;
+
+    ngx_memzero(&url, sizeof(ngx_url_t));
+
+    if (ngx_http_script_run(r, &url.url, flcf->fastcgi_lengths->elts, 0,
                             flcf->fastcgi_values->elts)
         == NULL)
     {
         return NGX_ERROR;
     }
 
-    u.no_resolve = 1;
-
-    if (ngx_parse_url(r->pool, &u) != NGX_OK) {
-         if (u.err) {
+    url.no_resolve = 1;
+
+    if (ngx_parse_url(r->pool, &url) != NGX_OK) {
+         if (url.err) {
             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                          "%s in upstream \"%V\"", u.err, &u.url);
+                          "%s in upstream \"%V\"", url.err, &url.url);
         }
 
         return NGX_ERROR;
     }
 
-    if (u.no_port) {
-        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                      "no port in upstream \"%V\"", &u.url);
-        return NGX_ERROR;
-    }
-
-    r->upstream->resolved = ngx_pcalloc(r->pool,
-                                        sizeof(ngx_http_upstream_resolved_t));
-    if (r->upstream->resolved == NULL) {
+    u = r->upstream;
+
+    u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
+    if (u->resolved == NULL) {
         return NGX_ERROR;
     }
 
-    if (u.addrs && u.addrs[0].sockaddr) {
-        r->upstream->resolved->sockaddr = u.addrs[0].sockaddr;
-        r->upstream->resolved->socklen = u.addrs[0].socklen;
-        r->upstream->resolved->naddrs = 1;
-        r->upstream->resolved->host = u.addrs[0].name;
+    if (url.addrs && url.addrs[0].sockaddr) {
+        u->resolved->sockaddr = url.addrs[0].sockaddr;
+        u->resolved->socklen = url.addrs[0].socklen;
+        u->resolved->naddrs = 1;
+        u->resolved->host = url.addrs[0].name;
 
     } else {
-        r->upstream->resolved->host = u.host;
-        r->upstream->resolved->port = u.port;
+        u->resolved->host = url.host;
+        u->resolved->port = url.port;
+        u->resolved->no_port = url.no_port;
     }
 
     return NGX_OK;
@@ -681,13 +688,14 @@
 ngx_http_fastcgi_create_request(ngx_http_request_t *r)
 {
     off_t                         file_pos;
-    u_char                        ch, *pos;
-    size_t                        size, len, key_len, val_len, padding;
-    ngx_uint_t                    i, n, next;
+    u_char                        ch, *pos, *lowcase_key;
+    size_t                        size, len, key_len, val_len, padding,
+                                  allocated;
+    ngx_uint_t                    i, n, next, hash, header_params;
     ngx_buf_t                    *b;
     ngx_chain_t                  *cl, *body;
     ngx_list_part_t              *part;
-    ngx_table_elt_t              *header;
+    ngx_table_elt_t              *header, **ignored;
     ngx_http_script_code_pt       code;
     ngx_http_script_engine_t      e, le;
     ngx_http_fastcgi_header_t    *h;
@@ -695,6 +703,8 @@
     ngx_http_script_len_code_pt   lcode;
 
     len = 0;
+    header_params = 0;
+    ignored = NULL;
 
     flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
 
@@ -723,6 +733,16 @@
 
     if (flcf->upstream.pass_request_headers) {
 
+        allocated = 0;
+        lowcase_key = NULL;
+
+        if (flcf->header_params) {
+            ignored = ngx_palloc(r->pool, flcf->header_params * sizeof(void *));
+            if (ignored == NULL) {
+                return NGX_ERROR;
+            }
+        }
+
         part = &r->headers_in.headers.part;
         header = part->elts;
 
@@ -738,9 +758,44 @@
                 i = 0;
             }
 
-            len += ((sizeof("HTTP_") - 1 + header[i].key.len > 127) ? 4 : 1)
-                + ((header[i].value.len > 127) ? 4 : 1)
-                + sizeof("HTTP_") - 1 + header[i].key.len + header[i].value.len;
+            if (flcf->header_params) {
+                if (allocated < header[i].key.len) {
+                    allocated = header[i].key.len + 16;
+                    lowcase_key = ngx_pnalloc(r->pool, allocated);
+                    if (lowcase_key == NULL) {
+                        return NGX_ERROR;
+                    }
+                }
+
+                hash = 0;
+
+                for (n = 0; n < header[i].key.len; n++) {
+                    ch = header[i].key.data[n];
+
+                    if (ch >= 'A' && ch <= 'Z') {
+                        ch |= 0x20;
+
+                    } else if (ch == '-') {
+                        ch = '_';
+                    }
+
+                    hash = ngx_hash(hash, ch);
+                    lowcase_key[n] = ch;
+                }
+
+                if (ngx_hash_find(&flcf->headers_hash, hash, lowcase_key, n)) {
+                    ignored[header_params++] = &header[i];
+                    continue;
+                }
+
+                n += sizeof("HTTP_") - 1;
+
+            } else {
+                n = sizeof("HTTP_") - 1 + header[i].key.len;
+            }
+
+            len += ((n > 127) ? 4 : 1) + ((header[i].value.len > 127) ? 4 : 1)
+                + n + header[i].value.len;
         }
     }
 
@@ -860,26 +915,32 @@
                 i = 0;
             }
 
-            len = sizeof("HTTP_") - 1 + header[i].key.len;
-            if (len > 127) {
-                *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
-                *b->last++ = (u_char) ((len >> 16) & 0xff);
-                *b->last++ = (u_char) ((len >> 8) & 0xff);
-                *b->last++ = (u_char) (len & 0xff);
+            for (n = 0; n < header_params; n++) {
+                if (&header[i] == ignored[n]) {
+                    goto next;
+                }
+            }
+
+            key_len = sizeof("HTTP_") - 1 + header[i].key.len;
+            if (key_len > 127) {
+                *b->last++ = (u_char) (((key_len >> 24) & 0x7f) | 0x80);
+                *b->last++ = (u_char) ((key_len >> 16) & 0xff);
+                *b->last++ = (u_char) ((key_len >> 8) & 0xff);
+                *b->last++ = (u_char) (key_len & 0xff);
 
             } else {
-                *b->last++ = (u_char) len;
+                *b->last++ = (u_char) key_len;
             }
 
-            len = header[i].value.len;
-            if (len > 127) {
-                *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
-                *b->last++ = (u_char) ((len >> 16) & 0xff);
-                *b->last++ = (u_char) ((len >> 8) & 0xff);
-                *b->last++ = (u_char) (len & 0xff);
+            val_len = header[i].value.len;
+            if (val_len > 127) {
+                *b->last++ = (u_char) (((val_len >> 24) & 0x7f) | 0x80);
+                *b->last++ = (u_char) ((val_len >> 16) & 0xff);
+                *b->last++ = (u_char) ((val_len >> 8) & 0xff);
+                *b->last++ = (u_char) (val_len & 0xff);
 
             } else {
-                *b->last++ = (u_char) len;
+                *b->last++ = (u_char) val_len;
             }
 
             b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1);
@@ -897,8 +958,15 @@
                 *b->last++ = ch;
             }
 
-            b->last = ngx_copy(b->last, header[i].value.data,
-                               header[i].value.len);
+            b->last = ngx_copy(b->last, header[i].value.data, val_len);
+
+            ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                           "fastcgi param: \"%*s: %*s\"",
+                           key_len, b->last - (key_len + val_len),
+                           val_len, b->last - val_len);
+        next:
+
+            continue;
         }
     }
 
@@ -1057,6 +1125,7 @@
 
     f->state = ngx_http_fastcgi_st_version;
     f->fastcgi_stdout = 0;
+    f->large_stderr = 0;
 
     return NGX_OK;
 }
@@ -1199,8 +1268,18 @@
                          * of the PHP warnings to not allocate memory
                          */
 
+#if (NGX_HTTP_CACHE)
+                        if (r->cache) {
+                            u->buffer.pos = u->buffer.start
+                                                     + r->cache->header_start;
+                        } else {
+                            u->buffer.pos = u->buffer.start;
+                        }
+#else
                         u->buffer.pos = u->buffer.start;
-                        u->buffer.last = u->buffer.start;
+#endif
+                        u->buffer.last = u->buffer.pos;
+                        f->large_stderr = 1;
                     }
 
                     return NGX_AGAIN;
@@ -1216,6 +1295,46 @@
 
         /* f->type == NGX_HTTP_FASTCGI_STDOUT */
 
+#if (NGX_HTTP_CACHE)
+
+        if (f->large_stderr && r->cache) {
+            u_char                     *start;
+            ssize_t                     len;
+            ngx_http_fastcgi_header_t  *fh;
+
+            start = u->buffer.start + r->cache->header_start;
+
+            len = u->buffer.pos - start - 2 * sizeof(ngx_http_fastcgi_header_t);
+
+            /*
+             * A tail of large stderr output before HTTP header is placed
+             * in a cache file without a FastCGI record header.
+             * To workaround it we put a dummy FastCGI record header at the
+             * start of the stderr output or update r->cache_header_start,
+             * if there is no enough place for the record header.
+             */
+
+            if (len >= 0) {
+                fh = (ngx_http_fastcgi_header_t *) start;
+                fh->version = 1;
+                fh->type = NGX_HTTP_FASTCGI_STDERR;
+                fh->request_id_hi = 0;
+                fh->request_id_lo = 1;
+                fh->content_length_hi = (u_char) ((len >> 8) & 0xff);
+                fh->content_length_lo = (u_char) (len & 0xff);
+                fh->padding_length = 0;
+                fh->reserved = 0;
+
+            } else {
+                r->cache->header_start += u->buffer.pos - start
+                                           - sizeof(ngx_http_fastcgi_header_t);
+            }
+
+            f->large_stderr = 0;
+        }
+
+#endif
+
         f->fastcgi_stdout = 1;
 
         start = u->buffer.pos;
@@ -1374,15 +1493,12 @@
 
                 } else if (u->headers_in.location) {
                     u->headers_in.status_n = 302;
-                    u->headers_in.status_line.len =
-                                           sizeof("302 Moved Temporarily") - 1;
-                    u->headers_in.status_line.data =
-                                           (u_char *) "302 Moved Temporarily";
+                    ngx_str_set(&u->headers_in.status_line,
+                                "302 Moved Temporarily");
 
                 } else {
                     u->headers_in.status_n = 200;
-                    u->headers_in.status_line.len = sizeof("200 OK") - 1;
-                    u->headers_in.status_line.data = (u_char *) "200 OK";
+                    ngx_str_set(&u->headers_in.status_line, "200 OK");
                 }
 
                 if (u->state) {
@@ -1847,8 +1963,7 @@
      *     conf->upstream.store_lengths = NULL;
      *     conf->upstream.store_values = NULL;
      *
-     *     conf->index.len = 0;
-     *     conf->index.data = NULL;
+     *     conf->index.len = { 0, NULL };
      */
 
     conf->upstream.store = NGX_CONF_UNSET;
@@ -1873,6 +1988,8 @@
 #if (NGX_HTTP_CACHE)
     conf->upstream.cache = NGX_CONF_UNSET_PTR;
     conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
+    conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
+    conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
     conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
 #endif
 
@@ -1900,8 +2017,11 @@
     size_t                        size;
     uintptr_t                    *code;
     ngx_uint_t                    i;
+    ngx_array_t                   headers_names;
     ngx_keyval_t                 *src;
+    ngx_hash_key_t               *hk;
     ngx_hash_init_t               hash;
+    ngx_http_core_loc_conf_t     *clcf;
     ngx_http_script_compile_t     sc;
     ngx_http_script_copy_code_t  *copy;
 
@@ -2093,6 +2213,18 @@
 
     conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;
 
+    ngx_conf_merge_ptr_value(conf->upstream.cache_bypass,
+                             prev->upstream.cache_bypass, NULL);
+
+    ngx_conf_merge_ptr_value(conf->upstream.no_cache,
+                             prev->upstream.no_cache, NULL);
+
+    if (conf->upstream.no_cache && conf->upstream.cache_bypass == NULL) {
+        ngx_log_error(NGX_LOG_WARN, cf->log, 0,
+             "\"fastcgi_no_cache\" functionality has been changed in 0.8.46, "
+             "now it should be used together with \"fastcgi_cache_bypass\"");
+    }
+
     ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
                              prev->upstream.cache_valid, NULL);
 
@@ -2120,9 +2252,7 @@
     hash.name = "fastcgi_hide_headers_hash";
 
     if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
-                                            &prev->upstream,
-                                            ngx_http_fastcgi_hide_headers,
-                                            &hash)
+             &prev->upstream, ngx_http_fastcgi_hide_headers, &hash)
         != NGX_OK)
     {
         return NGX_CONF_ERROR;
@@ -2137,6 +2267,13 @@
         conf->fastcgi_values = prev->fastcgi_values;
     }
 
+    if (conf->upstream.upstream || conf->fastcgi_lengths) {
+        clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
+        if (clcf->handler == NULL && clcf->lmt_excpt) {
+            clcf->handler = ngx_http_fastcgi_handler;
+        }
+    }
+
 #if (NGX_PCRE)
     if (conf->split_regex == NULL) {
         conf->split_regex = prev->split_regex;
@@ -2149,10 +2286,32 @@
         conf->params_len = prev->params_len;
         conf->params = prev->params;
         conf->params_source = prev->params_source;
+        conf->headers_hash = prev->headers_hash;
+
+#if (NGX_HTTP_CACHE)
+
+        if (conf->params_source == NULL) {
+
+            if ((conf->upstream.cache == NULL)
+                == (prev->upstream.cache == NULL))
+            {
+                return NGX_CONF_OK;
+            }
+
+            /* 6 is a number of ngx_http_fastcgi_cache_headers entries */
+            conf->params_source = ngx_array_create(cf->pool, 6,
+                                                   sizeof(ngx_keyval_t));
+            if (conf->params_source == NULL) {
+                return NGX_CONF_ERROR;
+            }
+        }
+#else
 
         if (conf->params_source == NULL) {
             return NGX_CONF_OK;
         }
+
+#endif
     }
 
     conf->params_len = ngx_array_create(cf->pool, 64, 1);
@@ -2165,89 +2324,100 @@
         return NGX_CONF_ERROR;
     }
 
+    if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
+        != NGX_OK)
+    {
+        return NGX_CONF_ERROR;
+    }
+
     src = conf->params_source->elts;
-    for (i = 0; i < conf->params_source->nelts; i++) {
-
-        if (ngx_http_script_variables_count(&src[i].value) == 0) {
-            copy = ngx_array_push_n(conf->params_len,
-                                    sizeof(ngx_http_script_copy_code_t));
-            if (copy == NULL) {
+
+#if (NGX_HTTP_CACHE)
+
+    if (conf->upstream.cache) {
+        ngx_keyval_t  *h, *s;
+
+        for (h = ngx_http_fastcgi_cache_headers; h->key.len; h++) {
+
+            for (i = 0; i < conf->params_source->nelts; i++) {
+                if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
+                    goto next;
+                }
+            }
+
+            s = ngx_array_push(conf->params_source);
+            if (s == NULL) {
                 return NGX_CONF_ERROR;
             }
 
-            copy->code = (ngx_http_script_code_pt)
-                                                  ngx_http_script_copy_len_code;
-            copy->len = src[i].key.len;
-
-
-            copy = ngx_array_push_n(conf->params_len,
-                                    sizeof(ngx_http_script_copy_code_t));
-            if (copy == NULL) {
-                return NGX_CONF_ERROR;
-            }
-
-            copy->code = (ngx_http_script_code_pt)
-                                                 ngx_http_script_copy_len_code;
-            copy->len = src[i].value.len;
-
-
-            size = (sizeof(ngx_http_script_copy_code_t)
-                       + src[i].key.len + src[i].value.len
-                       + sizeof(uintptr_t) - 1)
-                    & ~(sizeof(uintptr_t) - 1);
-
-            copy = ngx_array_push_n(conf->params, size);
-            if (copy == NULL) {
+            *s = *h;
+
+            src = conf->params_source->elts;
+
+        next:
+
+            h++;
+        }
+    }
+
+#endif
+
+    for (i = 0; i < conf->params_source->nelts; i++) {
+
+        if (src[i].key.len > sizeof("HTTP_") - 1
+            && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0)
+        {
+            hk = ngx_array_push(&headers_names);
+            if (hk == NULL) {
                 return NGX_CONF_ERROR;
             }
 
-            copy->code = ngx_http_script_copy_code;
-            copy->len = src[i].key.len + src[i].value.len;
-
-            p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
-
-            p = ngx_cpymem(p, src[i].key.data, src[i].key.len);
-            ngx_memcpy(p, src[i].value.data, src[i].value.len);
-
-        } else {
-            copy = ngx_array_push_n(conf->params_len,
-                                    sizeof(ngx_http_script_copy_code_t));
-            if (copy == NULL) {
-                return NGX_CONF_ERROR;
+            hk->key.len = src[i].key.len - 5;
+            hk->key.data = src[i].key.data + 5;
+            hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len);
+            hk->value = (void *) 1;
+
+            if (src[i].value.len == 0) {
+                continue;
             }
-
-            copy->code = (ngx_http_script_code_pt)
-                                                 ngx_http_script_copy_len_code;
-            copy->len = src[i].key.len;
-
-
-            size = (sizeof(ngx_http_script_copy_code_t)
-                    + src[i].key.len + sizeof(uintptr_t) - 1)
-                    & ~(sizeof(uintptr_t) - 1);
-
-            copy = ngx_array_push_n(conf->params, size);
-            if (copy == NULL) {
-                return NGX_CONF_ERROR;
-            }
-
-            copy->code = ngx_http_script_copy_code;
-            copy->len = src[i].key.len;
-
-            p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
-            ngx_memcpy(p, src[i].key.data, src[i].key.len);
-
-
-            ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
-            sc.cf = cf;
-            sc.source = &src[i].value;
-            sc.flushes = &conf->flushes;
-            sc.lengths = &conf->params_len;
-            sc.values = &conf->params;
-
-            if (ngx_http_script_compile(&sc) != NGX_OK) {
-                return NGX_CONF_ERROR;
-            }
+        }
+
+        copy = ngx_array_push_n(conf->params_len,
+                                sizeof(ngx_http_script_copy_code_t));
+        if (copy == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
+        copy->len = src[i].key.len;
+
+
+        size = (sizeof(ngx_http_script_copy_code_t)
+                + src[i].key.len + sizeof(uintptr_t) - 1)
+                & ~(sizeof(uintptr_t) - 1);
+
+        copy = ngx_array_push_n(conf->params, size);
+        if (copy == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        copy->code = ngx_http_script_copy_code;
+        copy->len = src[i].key.len;
+
+        p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
+        ngx_memcpy(p, src[i].key.data, src[i].key.len);
+
+
+        ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
+
+        sc.cf = cf;
+        sc.source = &src[i].value;
+        sc.flushes = &conf->flushes;
+        sc.lengths = &conf->params_len;
+        sc.values = &conf->params;
+
+        if (ngx_http_script_compile(&sc) != NGX_OK) {
+            return NGX_CONF_ERROR;
         }
 
         code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t));
@@ -2273,6 +2443,22 @@
 
     *code = (uintptr_t) NULL;
 
+
+    conf->header_params = headers_names.nelts;
+
+    hash.hash = &conf->headers_hash;
+    hash.key = ngx_hash_key_lc;
+    hash.max_size = 512;
+    hash.bucket_size = 64;
+    hash.name = "fastcgi_params_hash";
+    hash.pool = cf->pool;
+    hash.temp_pool = NULL;
+
+    if (ngx_hash_init(&hash, headers_names.elts, headers_names.nelts) != NGX_OK)
+    {
+        return NGX_CONF_ERROR;
+    }
+
     return NGX_CONF_OK;
 }
 
@@ -2374,27 +2560,25 @@
 
     n = ngx_regex_exec(flcf->split_regex, &r->uri, captures, (1 + 2) * 3);
 
+    if (n >= 0) { /* match */
+        f->script_name.len = captures[3] - captures[2];
+        f->script_name.data = r->uri.data + captures[2];
+
+        f->path_info.len = captures[5] - captures[4];
+        f->path_info.data = r->uri.data + captures[4];
+
+        return f;
+    }
+
     if (n == NGX_REGEX_NO_MATCHED) {
         f->script_name = r->uri;
         return f;
     }
 
-    if (n < 0) {
-        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                      ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"",
-                      n, &r->uri, &flcf->split_name);
-        return NULL;
-    }
-
-    /* match */
-
-    f->script_name.len = captures[3] - captures[2];
-    f->script_name.data = r->uri.data;
-
-    f->path_info.len = captures[5] - captures[4];
-    f->path_info.data = r->uri.data + f->script_name.len;
-
-    return f;
+    ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                  ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
+                  n, &r->uri, &flcf->split_name);
+    return NULL;
 
 #else
 
@@ -2485,39 +2669,34 @@
 #if (NGX_PCRE)
     ngx_http_fastcgi_loc_conf_t *flcf = conf;
 
-    ngx_int_t   n;
-    ngx_str_t  *value, err;
-    u_char      errstr[NGX_MAX_CONF_ERRSTR];
+    ngx_str_t            *value;
+    ngx_regex_compile_t   rc;
+    u_char                errstr[NGX_MAX_CONF_ERRSTR];
 
     value = cf->args->elts;
 
     flcf->split_name = value[1];
 
-    err.len = NGX_MAX_CONF_ERRSTR;
-    err.data = errstr;
-
-    flcf->split_regex = ngx_regex_compile(&value[1], 0, cf->pool, &err);
-
-    if (flcf->split_regex == NULL) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
+    ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
+
+    rc.pattern = value[1];
+    rc.pool = cf->pool;
+    rc.err.len = NGX_MAX_CONF_ERRSTR;
+    rc.err.data = errstr;
+
+    if (ngx_regex_compile(&rc) != NGX_OK) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
         return NGX_CONF_ERROR;
     }
 
-    n = ngx_regex_capture_count(flcf->split_regex);
-
-    if (n < 0) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           ngx_regex_capture_count_n " failed for "
-                           "pattern \"%V\"", &value[1]);
-        return NGX_CONF_ERROR;
-    }
-
-    if (n != 2) {
+    if (rc.captures != 2) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                            "pattern \"%V\" must have 2 captures", &value[1]);
         return NGX_CONF_ERROR;
     }
 
+    flcf->split_regex = rc.regex;
+
     return NGX_CONF_OK;
 
 #else
@@ -2678,29 +2857,3 @@
 
     return NGX_CONF_OK;
 }
-
-
-static char *
-ngx_http_fastcgi_upstream_max_fails_unsupported(ngx_conf_t *cf,
-    ngx_command_t *cmd, void *conf)
-{
-    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-         "\"fastcgi_upstream_max_fails\" is not supported, "
-         "use the \"max_fails\" parameter of the \"server\" directive ",
-         "inside the \"upstream\" block");
-
-    return NGX_CONF_ERROR;
-}
-
-
-static char *
-ngx_http_fastcgi_upstream_fail_timeout_unsupported(ngx_conf_t *cf,
-    ngx_command_t *cmd, void *conf)
-{
-    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-         "\"fastcgi_upstream_fail_timeout\" is not supported, "
-         "use the \"fail_timeout\" parameter of the \"server\" directive ",
-         "inside the \"upstream\" block");
-
-    return NGX_CONF_ERROR;
-}
--- a/src/http/modules/ngx_http_flv_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/http/modules/ngx_http_flv_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -80,10 +80,6 @@
         return NGX_DECLINED;
     }
 
-    if (r->zero_in_uri) {
-        return NGX_DECLINED;
-    }
-
     rc = ngx_http_discard_request_body(r);
 
     if (rc != NGX_OK) {
@@ -106,6 +102,7 @@
 
     ngx_memzero(&of, sizeof(ngx_open_file_info_t));
 
+    of.read_ahead = clcf->read_ahead;
     of.directio = clcf->directio;
     of.valid = clcf->open_file_cache_valid;
     of.min_uses = clcf->open_file_cache_min_uses;
--- a/src/http/modules/ngx_http_geo_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/http/modules/ngx_http_geo_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -10,41 +10,53 @@
 
 
 typedef struct {
+    ngx_http_variable_value_t       *value;
     u_short                          start;
     u_short                          end;
-    ngx_http_variable_value_t       *value;
 } ngx_http_geo_range_t;
 
 
 typedef struct {
-    ngx_http_geo_range_t            *ranges;
-    ngx_uint_t                       n;
-} ngx_http_geo_low_ranges_t;
-
-
-typedef struct {
-    ngx_http_geo_low_ranges_t        low[0x10000];
+    ngx_http_geo_range_t           **low;
     ngx_http_variable_value_t       *default_value;
 } ngx_http_geo_high_ranges_t;
 
 
 typedef struct {
+    ngx_str_node_t                   sn;
+    ngx_http_variable_value_t       *value;
+    size_t                           offset;
+} ngx_http_geo_variable_value_node_t;
+
+
+typedef struct {
     ngx_http_variable_value_t       *value;
     ngx_str_t                       *net;
-    ngx_http_geo_high_ranges_t      *high;
+    ngx_http_geo_high_ranges_t       high;
     ngx_radix_tree_t                *tree;
     ngx_rbtree_t                     rbtree;
     ngx_rbtree_node_t                sentinel;
     ngx_array_t                     *proxies;
     ngx_pool_t                      *pool;
     ngx_pool_t                      *temp_pool;
+
+    size_t                           data_size;
+
+    ngx_str_t                        include_name;
+    ngx_uint_t                       includes;
+    ngx_uint_t                       entries;
+
+    unsigned                         ranges:1;
+    unsigned                         outside_entries:1;
+    unsigned                         allow_binary_include:1;
+    unsigned                         binary_include:1;
 } ngx_http_geo_conf_ctx_t;
 
 
 typedef struct {
     union {
         ngx_radix_tree_t            *tree;
-        ngx_http_geo_high_ranges_t  *high;
+        ngx_http_geo_high_ranges_t   high;
     } u;
 
     ngx_array_t                     *proxies;
@@ -73,6 +85,13 @@
     ngx_http_geo_conf_ctx_t *ctx, ngx_cidr_t *cidr);
 static ngx_int_t ngx_http_geo_cidr_value(ngx_conf_t *cf, ngx_str_t *net,
     ngx_cidr_t *cidr);
+static char *ngx_http_geo_include(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
+    ngx_str_t *name);
+static ngx_int_t ngx_http_geo_include_binary_base(ngx_conf_t *cf,
+    ngx_http_geo_conf_ctx_t *ctx, ngx_str_t *name);
+static void ngx_http_geo_create_binary_base(ngx_http_geo_conf_ctx_t *ctx);
+static u_char *ngx_http_geo_copy_values(u_char *base, u_char *p,
+    ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
 
 
 static ngx_command_t  ngx_http_geo_commands[] = {
@@ -119,6 +138,20 @@
 };
 
 
+typedef struct {
+    u_char    GEORNG[6];
+    u_char    version;
+    u_char    ptr_size;
+    uint32_t  endianess;
+    uint32_t  crc32;
+} ngx_http_geo_header_t;
+
+
+static ngx_http_geo_header_t  ngx_http_geo_header = {
+    { 'G', 'E', 'O', 'R', 'N', 'G' }, 0, sizeof(void *), 0x12345678, 0
+};
+
+
 /* AF_INET only */
 
 static ngx_int_t
@@ -148,23 +181,24 @@
     ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data;
 
     in_addr_t              addr;
-    ngx_uint_t             i, n;
+    ngx_uint_t             n;
     ngx_http_geo_range_t  *range;
 
-    *v = *ctx->u.high->default_value;
+    *v = *ctx->u.high.default_value;
 
     addr = ngx_http_geo_addr(r, ctx);
 
-    range = ctx->u.high->low[addr >> 16].ranges;
-
-    n = addr & 0xffff;
+    range = ctx->u.high.low[addr >> 16];
 
-    for (i = 0; i < ctx->u.high->low[addr >> 16].n; i++) {
-        if (n >= (ngx_uint_t) range[i].start
-            && n <= (ngx_uint_t) range[i].end)
-        {
-            *v = *range[i].value;
-        }
+    if (range) {
+        n = addr & 0xffff;
+        do {
+            if (n >= (ngx_uint_t) range->start && n <= (ngx_uint_t) range->end)
+            {
+                *v = *range->value;
+                break;
+            }
+        } while ((++range)->value);
     }
 
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -256,6 +290,7 @@
 ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     char                     *rv;
+    void                    **p;
     size_t                    len;
     ngx_str_t                *value, name;
     ngx_uint_t                i;
@@ -302,18 +337,20 @@
         return NGX_CONF_ERROR;
     }
 
+    ngx_memzero(&ctx, sizeof(ngx_http_geo_conf_ctx_t));
+
     ctx.temp_pool = ngx_create_pool(16384, cf->log);
     if (ctx.temp_pool == NULL) {
         return NGX_CONF_ERROR;
     }
 
-    ngx_rbtree_init(&ctx.rbtree, &ctx.sentinel,
-                    ngx_http_variable_value_rbtree_insert);
+    ngx_rbtree_init(&ctx.rbtree, &ctx.sentinel, ngx_str_rbtree_insert_value);
 
-    ctx.high = NULL;
-    ctx.tree = NULL;
-    ctx.proxies = NULL;
     ctx.pool = cf->pool;
+    ctx.data_size = sizeof(ngx_http_geo_header_t)
+                  + sizeof(ngx_http_variable_value_t)
+                  + 0x10000 * sizeof(ngx_http_geo_range_t *);
+    ctx.allow_binary_include = 1;
 
     save = *cf;
     cf->pool = pool;
@@ -327,25 +364,35 @@
 
     geo->proxies = ctx.proxies;
 
-    if (ctx.high) {
+    if (ctx.high.low) {
+
+        if (!ctx.binary_include) {
+            for (i = 0; i < 0x10000; i++) {
+                a = (ngx_array_t *) ctx.high.low[i];
+
+                if (a == NULL || a->nelts == 0) {
+                    continue;
+                }
 
-        for (i = 0; i < 0x10000; i++) {
-            a = (ngx_array_t *) ctx.high->low[i].ranges;
+                len = a->nelts * sizeof(ngx_http_geo_range_t);
 
-            if (a == NULL || a->nelts == 0) {
-                continue;
+                ctx.high.low[i] = ngx_palloc(cf->pool, len + sizeof(void *));
+                if (ctx.high.low[i] == NULL) {
+                    return NGX_CONF_ERROR;
+                }
+
+                p = (void **) ngx_cpymem(ctx.high.low[i], a->elts, len);
+                *p = NULL;
+                ctx.data_size += len + sizeof(void *);
             }
 
-            ctx.high->low[i].n = a->nelts;
-
-            len = a->nelts * sizeof(ngx_http_geo_range_t);
-
-            ctx.high->low[i].ranges = ngx_palloc(cf->pool, len);
-            if (ctx.high->low[i].ranges == NULL ){
-                return NGX_CONF_ERROR;
+            if (ctx.allow_binary_include
+                && !ctx.outside_entries
+                && ctx.entries > 100000
+                && ctx.includes == 1)
+            {
+                ngx_http_geo_create_binary_base(&ctx);
             }
-
-            ngx_memcpy(ctx.high->low[i].ranges, a->elts, len);
         }
 
         geo->u.high = ctx.high;
@@ -353,13 +400,13 @@
         var->get_handler = ngx_http_geo_range_variable;
         var->data = (uintptr_t) geo;
 
+        if (ctx.high.default_value == NULL) {
+            ctx.high.default_value = &ngx_http_variable_null_value;
+        }
+
         ngx_destroy_pool(ctx.temp_pool);
         ngx_destroy_pool(pool);
 
-        if (ctx.high->default_value == NULL) {
-            ctx.high->default_value = &ngx_http_variable_null_value;
-        }
-
     } else {
         if (ctx.tree == NULL) {
             ctx.tree = ngx_radix_tree_create(cf->pool, -1);
@@ -396,7 +443,7 @@
 ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
 {
     char                     *rv;
-    ngx_str_t                *value, file;
+    ngx_str_t                *value;
     ngx_cidr_t                cidr;
     ngx_http_geo_conf_ctx_t  *ctx;
 
@@ -415,11 +462,7 @@
                 goto failed;
             }
 
-            ctx->high = ngx_pcalloc(ctx->pool,
-                                    sizeof(ngx_http_geo_high_ranges_t));
-            if (ctx->high == NULL) {
-                goto failed;
-            }
+            ctx->ranges = 1;
 
             rv = NGX_CONF_OK;
 
@@ -435,20 +478,7 @@
 
     if (ngx_strcmp(value[0].data, "include") == 0) {
 
-        file.len = value[1].len++;
-
-        file.data = ngx_pstrdup(ctx->temp_pool, &value[1]);
-        if (file.data == NULL) {
-            goto failed;
-        }
-
-        if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK){
-            goto failed;
-        }
-
-        ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
-
-        rv = ngx_conf_parse(cf, &file);
+        rv = ngx_http_geo_include(cf, ctx, &value[1]);
 
         goto done;
 
@@ -463,7 +493,7 @@
         goto done;
     }
 
-    if (ctx->high) {
+    if (ctx->ranges) {
         rv = ngx_http_geo_range(cf, ctx, value);
 
     } else {
@@ -488,30 +518,45 @@
 ngx_http_geo_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
     ngx_str_t *value)
 {
-    u_char                     *p, *last;
-    in_addr_t                   start, end;
-    ngx_str_t                  *net;
-    ngx_uint_t                  del;
-    ngx_http_variable_value_t  *old;
+    u_char      *p, *last;
+    in_addr_t    start, end;
+    ngx_str_t   *net;
+    ngx_uint_t   del;
 
     if (ngx_strcmp(value[0].data, "default") == 0) {
 
-        old = ctx->high->default_value;
-
-        ctx->high->default_value = ngx_http_geo_value(cf, ctx, &value[1]);
-        if (ctx->high->default_value == NULL) {
-            return NGX_CONF_ERROR;
+        if (ctx->high.default_value) {
+            ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+                "duplicate default geo range value: \"%V\", old value: \"%v\"",
+                &value[1], ctx->high.default_value);
         }
 
-        if (old) {
-            ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
-                    "duplicate range \"%V\", value: \"%v\", old value: \"%v\"",
-                    &value[0], ctx->high->default_value, old);
+        ctx->high.default_value = ngx_http_geo_value(cf, ctx, &value[1]);
+        if (ctx->high.default_value == NULL) {
+            return NGX_CONF_ERROR;
         }
 
         return NGX_CONF_OK;
     }
 
+    if (ctx->binary_include) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+            "binary geo range base \"%s\" may not be mixed with usual entries",
+            ctx->include_name.data);
+        return NGX_CONF_ERROR;
+    }
+
+    if (ctx->high.low == NULL) {
+        ctx->high.low = ngx_pcalloc(ctx->pool,
+                                    0x10000 * sizeof(ngx_http_geo_range_t *));
+        if (ctx->high.low == NULL) {
+            return NGX_CONF_ERROR;
+        }
+    }
+
+    ctx->entries++;
+    ctx->outside_entries = 1;
+
     if (ngx_strcmp(value[0].data, "delete") == 0) {
         net = &value[1];
         del = 1;
@@ -589,7 +634,7 @@
     ngx_array_t           *a;
     ngx_http_geo_range_t  *range;
 
-    for (n = start; n <= end; n += 0x10000) {
+    for (n = start; n <= end; n = (n + 0x10000) & 0xffff0000) {
 
         h = n >> 16;
 
@@ -606,7 +651,7 @@
             e = 0xffff;
         }
 
-        a = (ngx_array_t *) ctx->high->low[h].ranges;
+        a = (ngx_array_t *) ctx->high.low[h];
 
         if (a == NULL) {
             a = ngx_array_create(ctx->temp_pool, 64,
@@ -615,7 +660,7 @@
                 return NGX_CONF_ERROR;
             }
 
-            ctx->high->low[h].ranges = (ngx_http_geo_range_t *) a;
+            ctx->high.low[h] = (ngx_http_geo_range_t *) a;
         }
 
         i = a->nelts;
@@ -640,7 +685,7 @@
 
                 range = a->elts;
 
-                ngx_memcpy(&range[i + 2], &range[i + 1],
+                ngx_memmove(&range[i + 2], &range[i + 1],
                            (a->nelts - 2 - i) * sizeof(ngx_http_geo_range_t));
 
                 range[i + 1].start = (u_short) s;
@@ -679,7 +724,7 @@
 
                 range = a->elts;
 
-                ngx_memcpy(&range[i + 3], &range[i + 1],
+                ngx_memmove(&range[i + 3], &range[i + 1],
                            (a->nelts - 3 - i) * sizeof(ngx_http_geo_range_t));
 
                 range[i + 2].start = (u_short) (e + 1);
@@ -707,7 +752,7 @@
 
                 range = a->elts;
 
-                ngx_memcpy(&range[i + 1], &range[i],
+                ngx_memmove(&range[i + 1], &range[i],
                            (a->nelts - 1 - i) * sizeof(ngx_http_geo_range_t));
 
                 range[i + 1].start = (u_short) (e + 1);
@@ -731,7 +776,7 @@
 
                 range = a->elts;
 
-                ngx_memcpy(&range[i + 2], &range[i + 1],
+                ngx_memmove(&range[i + 2], &range[i + 1],
                            (a->nelts - 2 - i) * sizeof(ngx_http_geo_range_t));
 
                 range[i + 1].start = (u_short) s;
@@ -803,7 +848,7 @@
             e = 0xffff;
         }
 
-        a = (ngx_array_t *) ctx->high->low[h].ranges;
+        a = (ngx_array_t *) ctx->high.low[h];
 
         if (a == NULL) {
             warn = 1;
@@ -816,7 +861,7 @@
             if (s == (ngx_uint_t) range[i].start
                 && e == (ngx_uint_t) range[i].end)
             {
-                ngx_memcpy(&range[i], &range[i + 1],
+                ngx_memmove(&range[i], &range[i + 1],
                            (a->nelts - 1 - i) * sizeof(ngx_http_geo_range_t));
 
                 a->nelts--;
@@ -929,16 +974,17 @@
 ngx_http_geo_value(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
     ngx_str_t *value)
 {
-    uint32_t                         hash;
-    ngx_http_variable_value_t       *val;
-    ngx_http_variable_value_node_t  *vvn;
+    uint32_t                             hash;
+    ngx_http_variable_value_t           *val;
+    ngx_http_geo_variable_value_node_t  *gvvn;
 
     hash = ngx_crc32_long(value->data, value->len);
 
-    val = ngx_http_variable_value_lookup(&ctx->rbtree, value, hash);
+    gvvn = (ngx_http_geo_variable_value_node_t *)
+               ngx_str_rbtree_lookup(&ctx->rbtree, value, hash);
 
-    if (val) {
-        return val;
+    if (gvvn) {
+        return gvvn->value;
     }
 
     val = ngx_palloc(ctx->pool, sizeof(ngx_http_variable_value_t));
@@ -956,16 +1002,22 @@
     val->no_cacheable = 0;
     val->not_found = 0;
 
-    vvn = ngx_palloc(ctx->temp_pool, sizeof(ngx_http_variable_value_node_t));
-    if (vvn == NULL) {
+    gvvn = ngx_palloc(ctx->temp_pool,
+                      sizeof(ngx_http_geo_variable_value_node_t));
+    if (gvvn == NULL) {
         return NULL;
     }
 
-    vvn->node.key = hash;
-    vvn->len = val->len;
-    vvn->value = val;
+    gvvn->sn.node.key = hash;
+    gvvn->sn.str.len = val->len;
+    gvvn->sn.str.data = val->data;
+    gvvn->value = val;
+    gvvn->offset = 0;
 
-    ngx_rbtree_insert(&ctx->rbtree, &vvn->node);
+    ngx_rbtree_insert(&ctx->rbtree, &gvvn->sn.node);
+
+    ctx->data_size += ngx_align(sizeof(ngx_http_variable_value_t) + value->len,
+                                sizeof(void *));
 
     return val;
 }
@@ -1030,3 +1082,335 @@
 
     return NGX_OK;
 }
+
+
+static char *
+ngx_http_geo_include(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
+    ngx_str_t *name)
+{
+    char       *rv;
+    ngx_str_t   file;
+
+    file.len = name->len + 4;
+    file.data = ngx_pnalloc(ctx->temp_pool, name->len + 5);
+    if (file.data == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    ngx_sprintf(file.data, "%V.bin%Z", name);
+
+    if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) {
+        return NGX_CONF_ERROR;
+    }
+
+    if (ctx->ranges) {
+        ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
+
+        switch (ngx_http_geo_include_binary_base(cf, ctx, &file)) {
+        case NGX_OK:
+            return NGX_CONF_OK;
+        case NGX_ERROR:
+            return NGX_CONF_ERROR;
+        default:
+            break;
+        }
+    }
+
+    file.len -= 4;
+    file.data[file.len] = '\0';
+
+    ctx->include_name = file;
+
+    if (ctx->outside_entries) {
+        ctx->allow_binary_include = 0;
+    }
+
+    ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
+
+    rv = ngx_conf_parse(cf, &file);
+
+    ctx->includes++;
+    ctx->outside_entries = 0;
+
+    return rv;
+}
+
+
+static ngx_int_t
+ngx_http_geo_include_binary_base(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
+    ngx_str_t *name)
+{
+    u_char                     *base, ch;
+    time_t                      mtime;
+    size_t                      size, len;
+    ssize_t                     n;
+    uint32_t                    crc32;
+    ngx_err_t                   err;
+    ngx_int_t                   rc;
+    ngx_uint_t                  i;
+    ngx_file_t                  file;
+    ngx_file_info_t             fi;
+    ngx_http_geo_range_t       *range, **ranges;
+    ngx_http_geo_header_t      *header;
+    ngx_http_variable_value_t  *vv;
+
+    ngx_memzero(&file, sizeof(ngx_file_t));
+    file.name = *name;
+    file.log = cf->log;
+
+    file.fd = ngx_open_file(name->data, NGX_FILE_RDONLY, 0, 0);
+    if (file.fd == NGX_INVALID_FILE) {
+        err = ngx_errno;
+        if (err != NGX_ENOENT) {
+            ngx_conf_log_error(NGX_LOG_CRIT, cf, err,
+                               ngx_open_file_n " \"%s\" failed", name->data);
+        }
+        return NGX_DECLINED;
+    }
+
+    if (ctx->outside_entries) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+            "binary geo range base \"%s\" may not be mixed with usual entries",
+            name->data);
+        rc = NGX_ERROR;
+        goto done;
+    }
+
+    if (ctx->binary_include) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+            "second binary geo range base \"%s\" may not be mixed with \"%s\"",
+            name->data, ctx->include_name.data);
+        rc = NGX_ERROR;
+        goto done;
+    }
+
+    if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) {
+        ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
+                           ngx_fd_info_n " \"%s\" failed", name->data);
+        goto failed;
+    }
+
+    size = (size_t) ngx_file_size(&fi);
+    mtime = ngx_file_mtime(&fi);
+
+    ch = name->data[name->len - 4];
+    name->data[name->len - 4] = '\0';
+
+    if (ngx_file_info(name->data, &fi) == NGX_FILE_ERROR) {
+        ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
+                           ngx_file_info_n " \"%s\" failed", name->data);
+        goto failed;
+    }
+
+    name->data[name->len - 4] = ch;
+
+    if (mtime < ngx_file_mtime(&fi)) {
+        ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+                           "stale binary geo range base \"%s\"", name->data);
+        goto failed;
+    }
+
+    base = ngx_palloc(ctx->pool, size);
+    if (base == NULL) {
+        goto failed;
+    }
+
+    n = ngx_read_file(&file, base, size, 0);
+
+    if (n == NGX_ERROR) {
+        ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
+                           ngx_read_file_n " \"%s\" failed", name->data);
+        goto failed;
+    }
+
+    if ((size_t) n != size) {
+        ngx_conf_log_error(NGX_LOG_CRIT, cf, 0,
+            ngx_read_file_n " \"%s\" returned only %z bytes instead of %z",
+            name->data, n, size);
+        goto failed;
+    }
+
+    header = (ngx_http_geo_header_t *) base;
+
+    if (size < 16 || ngx_memcmp(&ngx_http_geo_header, header, 12) != 0) {
+        ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+             "incompatible binary geo range base \"%s\"", name->data);
+        goto failed;
+    }
+
+    ngx_crc32_init(crc32);
+
+    vv = (ngx_http_variable_value_t *) (base + sizeof(ngx_http_geo_header_t));
+
+    while(vv->data) {
+        len = ngx_align(sizeof(ngx_http_variable_value_t) + vv->len,
+                        sizeof(void *));
+        ngx_crc32_update(&crc32, (u_char *) vv, len);
+        vv->data += (size_t) base;
+        vv = (ngx_http_variable_value_t *) ((u_char *) vv + len);
+    }
+    ngx_crc32_update(&crc32, (u_char *) vv, sizeof(ngx_http_variable_value_t));
+    vv++;
+
+    ranges = (ngx_http_geo_range_t **) vv;
+
+    for (i = 0; i < 0x10000; i++) {
+        ngx_crc32_update(&crc32, (u_char *) &ranges[i], sizeof(void *));
+        if (ranges[i]) {
+            ranges[i] = (ngx_http_geo_range_t *)
+                            ((u_char *) ranges[i] + (size_t) base);
+        }
+    }
+
+    range = (ngx_http_geo_range_t *) &ranges[0x10000];
+
+    while ((u_char *) range < base + size) {
+        while (range->value) {
+            ngx_crc32_update(&crc32, (u_char *) range,
+                             sizeof(ngx_http_geo_range_t));
+            range->value = (ngx_http_variable_value_t *)
+                               ((u_char *) range->value + (size_t) base);
+            range++;
+        }
+        ngx_crc32_update(&crc32, (u_char *) range, sizeof(void *));
+        range = (ngx_http_geo_range_t *) ((u_char *) range + sizeof(void *));
+    }
+
+    ngx_crc32_final(crc32);
+
+    if (crc32 != header->crc32) {
+        ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+                  "CRC32 mismatch in binary geo range base \"%s\"", name->data);
+        goto failed;
+    }
+
+    ngx_conf_log_error(NGX_LOG_NOTICE, cf, 0,
+                       "using binary geo range base \"%s\"", name->data);
+
+    ctx->include_name = *name;
+    ctx->binary_include = 1;
+    ctx->high.low = ranges;
+    rc = NGX_OK;
+
+    goto done;
+
+failed:
+
+    rc = NGX_DECLINED;
+
+done:
+
+    if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
+        ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
+                      ngx_close_file_n " \"%s\" failed", name->data);
+    }
+
+    return rc;
+}
+
+
+static void
+ngx_http_geo_create_binary_base(ngx_http_geo_conf_ctx_t *ctx)
+{
+    u_char                              *p;
+    uint32_t                             hash;
+    ngx_str_t                            s;
+    ngx_uint_t                           i;
+    ngx_file_mapping_t                   fm;
+    ngx_http_geo_range_t                *r, *range, **ranges;
+    ngx_http_geo_header_t               *header;
+    ngx_http_geo_variable_value_node_t  *gvvn;
+
+    fm.name = ngx_pnalloc(ctx->temp_pool, ctx->include_name.len + 5);
+    if (fm.name == NULL) {
+        return;
+    }
+
+    ngx_sprintf(fm.name, "%V.bin%Z", &ctx->include_name);
+
+    fm.size = ctx->data_size;
+    fm.log = ctx->pool->log;
+
+    ngx_log_error(NGX_LOG_NOTICE, fm.log, 0,
+                  "creating binary geo range base \"%s\"", fm.name);
+
+    if (ngx_create_file_mapping(&fm) != NGX_OK) {
+        return;
+    }
+
+    p = ngx_cpymem(fm.addr, &ngx_http_geo_header,
+                   sizeof(ngx_http_geo_header_t));
+
+    p = ngx_http_geo_copy_values(fm.addr, p, ctx->rbtree.root,
+                                 ctx->rbtree.sentinel);
+
+    p += sizeof(ngx_http_variable_value_t);
+
+    ranges = (ngx_http_geo_range_t **) p;
+
+    p += 0x10000 * sizeof(ngx_http_geo_range_t *);
+
+    for (i = 0; i < 0x10000; i++) {
+        r = ctx->high.low[i];
+        if (r == NULL) {
+            continue;
+        }
+
+        range = (ngx_http_geo_range_t *) p;
+        ranges[i] = (ngx_http_geo_range_t *) (p - (u_char *) fm.addr);
+
+        do {
+            s.len = r->value->len;
+            s.data = r->value->data;
+            hash = ngx_crc32_long(s.data, s.len);
+            gvvn = (ngx_http_geo_variable_value_node_t *)
+                        ngx_str_rbtree_lookup(&ctx->rbtree, &s, hash);
+
+            range->value = (ngx_http_variable_value_t *) gvvn->offset;
+            range->start = r->start;
+            range->end = r->end;
+            range++;
+
+        } while ((++r)->value);
+
+        range->value = NULL;
+
+        p = (u_char *) range + sizeof(void *);
+    }
+
+    header = fm.addr;
+    header->crc32 = ngx_crc32_long((u_char *) fm.addr
+                                       + sizeof(ngx_http_geo_header_t),
+                                   fm.size - sizeof(ngx_http_geo_header_t));
+
+    ngx_close_file_mapping(&fm);
+}
+
+
+static u_char *
+ngx_http_geo_copy_values(u_char *base, u_char *p, ngx_rbtree_node_t *node,
+    ngx_rbtree_node_t *sentinel)
+{
+    ngx_http_variable_value_t           *vv;
+    ngx_http_geo_variable_value_node_t  *gvvn;
+
+    if (node == sentinel) {
+        return p;
+    }
+
+    gvvn = (ngx_http_geo_variable_value_node_t *) node;
+    gvvn->offset = p - base;
+
+    vv = (ngx_http_variable_value_t *) p;
+    *vv = *gvvn->value;
+    p += sizeof(ngx_http_variable_value_t);
+    vv->data = (u_char *) (p - base);
+
+    p = ngx_cpymem(p, gvvn->sn.str.data, gvvn->sn.str.len);
+
+    p = ngx_align_ptr(p, sizeof(void *));
+
+    p = ngx_http_geo_copy_values(base, p, node->left, sentinel);
+
+    return ngx_http_geo_copy_values(base, p, node->right, sentinel);
+}
--- a/src/http/modules/ngx_http_geoip_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/http/modules/ngx_http_geoip_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -30,6 +30,13 @@
     ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_geoip_city_variable(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_geoip_region_name_variable(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_geoip_city_float_variable(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_geoip_city_int_variable(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
+static GeoIPRecord *ngx_http_geoip_get_city_record(ngx_http_request_t *r);
 
 static ngx_int_t ngx_http_geoip_add_variables(ngx_conf_t *cf);
 static void *ngx_http_geoip_create_conf(ngx_conf_t *cf);
@@ -43,14 +50,14 @@
 static ngx_command_t  ngx_http_geoip_commands[] = {
 
     { ngx_string("geoip_country"),
-      NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
+      NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE12,
       ngx_http_geoip_country,
       NGX_HTTP_MAIN_CONF_OFFSET,
       0,
       NULL },
 
     { ngx_string("geoip_city"),
-      NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
+      NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE12,
       ngx_http_geoip_city,
       NGX_HTTP_MAIN_CONF_OFFSET,
       0,
@@ -93,29 +100,42 @@
 
 static ngx_http_variable_t  ngx_http_geoip_vars[] = {
 
-    { ngx_string("geoip_country_code"), NULL, ngx_http_geoip_country_variable,
+    { ngx_string("geoip_country_code"), NULL,
+      ngx_http_geoip_country_variable,
       (uintptr_t) GeoIP_country_code_by_ipnum, 0, 0 },
 
-    { ngx_string("geoip_country_code3"), NULL, ngx_http_geoip_country_variable,
+    { ngx_string("geoip_country_code3"), NULL,
+      ngx_http_geoip_country_variable,
       (uintptr_t) GeoIP_country_code3_by_ipnum, 0, 0 },
 
-    { ngx_string("geoip_country_name"), NULL, ngx_http_geoip_country_variable,
+    { ngx_string("geoip_country_name"), NULL,
+      ngx_http_geoip_country_variable,
       (uintptr_t) GeoIP_country_name_by_ipnum, 0, 0 },
 
-    { ngx_string("geoip_city_country_code"), NULL, ngx_http_geoip_city_variable,
+    { ngx_string("geoip_city_continent_code"), NULL,
+      ngx_http_geoip_city_variable,
+      offsetof(GeoIPRecord, continent_code), 0, 0 },
+
+    { ngx_string("geoip_city_country_code"), NULL,
+      ngx_http_geoip_city_variable,
       offsetof(GeoIPRecord, country_code), 0, 0 },
 
     { ngx_string("geoip_city_country_code3"), NULL,
       ngx_http_geoip_city_variable,
       offsetof(GeoIPRecord, country_code3), 0, 0 },
 
-    { ngx_string("geoip_city_country_name"), NULL, ngx_http_geoip_city_variable,
+    { ngx_string("geoip_city_country_name"), NULL,
+      ngx_http_geoip_city_variable,
       offsetof(GeoIPRecord, country_name), 0, 0 },
 
     { ngx_string("geoip_region"), NULL,
       ngx_http_geoip_city_variable,
       offsetof(GeoIPRecord, region), 0, 0 },
 
+    { ngx_string("geoip_region_name"), NULL,
+      ngx_http_geoip_region_name_variable,
+      0, 0, 0 },
+
     { ngx_string("geoip_city"), NULL,
       ngx_http_geoip_city_variable,
       offsetof(GeoIPRecord, city), 0, 0 },
@@ -124,6 +144,22 @@
       ngx_http_geoip_city_variable,
       offsetof(GeoIPRecord, postal_code), 0, 0 },
 
+    { ngx_string("geoip_latitude"), NULL,
+      ngx_http_geoip_city_float_variable,
+      offsetof(GeoIPRecord, latitude), 0, 0 },
+
+    { ngx_string("geoip_longitude"), NULL,
+      ngx_http_geoip_city_float_variable,
+      offsetof(GeoIPRecord, longitude), 0, 0 },
+
+    { ngx_string("geoip_dma_code"), NULL,
+      ngx_http_geoip_city_int_variable,
+      offsetof(GeoIPRecord, dma_code), 0, 0 },
+
+    { ngx_string("geoip_area_code"), NULL,
+      ngx_http_geoip_city_int_variable,
+      offsetof(GeoIPRecord, area_code), 0, 0 },
+
     { ngx_null_string, NULL, NULL, 0, 0, 0 }
 };
 
@@ -179,41 +215,22 @@
 ngx_http_geoip_city_variable(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data)
 {
-    u_long                  addr;
-    char                   *val;
-    size_t                  len;
-    GeoIPRecord            *gr;
-    struct sockaddr_in     *sin;
-    ngx_http_geoip_conf_t  *gcf;
-
-    gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
+    char         *val;
+    size_t        len;
+    GeoIPRecord  *gr;
 
-    if (gcf->city == NULL) {
-        goto not_found;
-    }
-
-    if (r->connection->sockaddr->sa_family != AF_INET) {
-        goto not_found;
-    }
-
-    sin = (struct sockaddr_in *) r->connection->sockaddr;
-    addr = ntohl(sin->sin_addr.s_addr);
-
-    gr = GeoIP_record_by_ipnum(gcf->city, addr);
-
+    gr = ngx_http_geoip_get_city_record(r);
     if (gr == NULL) {
         goto not_found;
     }
 
     val = *(char **) ((char *) gr + data);
-
     if (val == NULL) {
         goto no_value;
     }
 
     len = ngx_strlen(val);
     v->data = ngx_pnalloc(r->pool, len);
-
     if (v->data == NULL) {
         GeoIPRecord_delete(gr);
         return NGX_ERROR;
@@ -243,6 +260,129 @@
 
 
 static ngx_int_t
+ngx_http_geoip_region_name_variable(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data)
+{
+    size_t        len;
+    const char   *val;
+    GeoIPRecord  *gr;
+
+    gr = ngx_http_geoip_get_city_record(r);
+    if (gr == NULL) {
+        goto not_found;
+    }
+
+    val = GeoIP_region_name_by_code(gr->country_code, gr->region);
+
+    GeoIPRecord_delete(gr);
+
+    if (val == NULL) {
+        goto not_found;
+    }
+
+    len = ngx_strlen(val);
+    v->data = ngx_pnalloc(r->pool, len);
+    if (v->data == NULL) {
+        return NGX_ERROR;
+    }
+
+    ngx_memcpy(v->data, val, len);
+
+    v->len = len;
+    v->valid = 1;
+    v->no_cacheable = 0;
+    v->not_found = 0;
+
+    return NGX_OK;
+
+not_found:
+
+    v->not_found = 1;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_geoip_city_float_variable(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data)
+{
+    float         val;
+    GeoIPRecord  *gr;
+
+    gr = ngx_http_geoip_get_city_record(r);
+    if (gr == NULL) {
+        v->not_found = 1;
+        return NGX_OK;
+    }
+
+    v->data = ngx_pnalloc(r->pool, NGX_INT64_LEN + 5);
+    if (v->data == NULL) {
+        GeoIPRecord_delete(gr);
+        return NGX_ERROR;
+    }
+
+    val = *(float *) ((char *) gr + data);
+
+    v->len = ngx_sprintf(v->data, "%.4f", val) - v->data;
+
+    GeoIPRecord_delete(gr);
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_geoip_city_int_variable(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data)
+{
+    int           val;
+    GeoIPRecord  *gr;
+
+    gr = ngx_http_geoip_get_city_record(r);
+    if (gr == NULL) {
+        v->not_found = 1;
+        return NGX_OK;
+    }
+
+    v->data = ngx_pnalloc(r->pool, NGX_INT64_LEN);
+    if (v->data == NULL) {
+        GeoIPRecord_delete(gr);
+        return NGX_ERROR;
+    }
+
+    val = *(int *) ((char *) gr + data);
+
+    v->len = ngx_sprintf(v->data, "%d", val) - v->data;
+
+    GeoIPRecord_delete(gr);
+
+    return NGX_OK;
+}
+
+
+static GeoIPRecord *
+ngx_http_geoip_get_city_record(ngx_http_request_t *r)
+{
+    u_long                  addr;
+    struct sockaddr_in     *sin;
+    ngx_http_geoip_conf_t  *gcf;
+
+    gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
+
+    if (gcf->city && r->connection->sockaddr->sa_family == AF_INET) {
+
+        sin = (struct sockaddr_in *) r->connection->sockaddr;
+        addr = ntohl(sin->sin_addr.s_addr);
+
+        return GeoIP_record_by_ipnum(gcf->city, addr);
+    }
+
+    return NULL;
+}
+
+
+static ngx_int_t
 ngx_http_geoip_add_variables(ngx_conf_t *cf)
 {
     ngx_http_variable_t  *var, *v;
@@ -306,6 +446,17 @@
         return NGX_CONF_ERROR;
     }
 
+    if (cf->args->nelts == 3) {
+        if (ngx_strcmp(value[2].data, "utf8") == 0) {
+            GeoIP_set_charset (gcf->country, GEOIP_CHARSET_UTF8);
+
+        } else {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "invalid parameter \"%V\"", &value[2]);
+            return NGX_CONF_ERROR;
+        }
+    }
+
     switch (gcf->country->databaseType) {
 
     case GEOIP_COUNTRY_EDITION:
@@ -345,6 +496,17 @@
         return NGX_CONF_ERROR;
     }
 
+    if (cf->args->nelts == 3) {
+        if (ngx_strcmp(value[2].data, "utf8") == 0) {
+            GeoIP_set_charset (gcf->city, GEOIP_CHARSET_UTF8);
+
+        } else {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "invalid parameter \"%V\"", &value[2]);
+            return NGX_CONF_ERROR;
+        }
+    }
+
     switch (gcf->city->databaseType) {
 
     case GEOIP_CITY_EDITION_REV0:
--- a/src/http/modules/ngx_http_gzip_filter_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/http/modules/ngx_http_gzip_filter_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -246,14 +246,36 @@
         || (r->headers_out.status != NGX_HTTP_OK
             && r->headers_out.status != NGX_HTTP_FORBIDDEN
             && r->headers_out.status != NGX_HTTP_NOT_FOUND)
-        || r->header_only
         || (r->headers_out.content_encoding
             && r->headers_out.content_encoding->value.len)
         || (r->headers_out.content_length_n != -1
             && r->headers_out.content_length_n < conf->min_length)
         || ngx_http_test_content_type(r, &conf->types) == NULL
-        || ngx_http_gzip_ok(r) != NGX_OK)
+        || r->header_only)
+    {
+        return ngx_http_next_header_filter(r);
+    }
+
+    r->gzip_vary = 1;
+
+#if (NGX_HTTP_DEGRADATION)
     {
+    ngx_http_core_loc_conf_t  *clcf;
+
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+    if (clcf->gzip_disable_degradation && ngx_http_degraded(r)) {
+        return ngx_http_next_header_filter(r);
+    }
+    }
+#endif
+
+    if (!r->gzip_tested) {
+        if (ngx_http_gzip_ok(r) != NGX_OK) {
+            return ngx_http_next_header_filter(r);
+        }
+
+    } else if (!r->gzip_ok) {
         return ngx_http_next_header_filter(r);
     }
 
@@ -275,11 +297,8 @@
     }
 
     h->hash = 1;
-    h->key.len = sizeof("Content-Encoding") - 1;
-    h->key.data = (u_char *) "Content-Encoding";
-    h->value.len = sizeof("gzip") - 1;
-    h->value.data = (u_char *) "gzip";
-
+    ngx_str_set(&h->key, "Content-Encoding");
+    ngx_str_set(&h->value, "gzip");
     r->headers_out.content_encoding = h;
 
     r->main_filter_need_in_memory = 1;
@@ -1113,8 +1132,8 @@
                               MAX_MEM_LEVEL - 1);
     ngx_conf_merge_value(conf->min_length, prev->min_length, 20);
 
-    if (ngx_http_merge_types(cf, conf->types_keys, &conf->types,
-                             prev->types_keys, &prev->types,
+    if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
+                             &prev->types_keys, &prev->types,
                              ngx_http_html_default_types)
         != NGX_OK)
     {
--- a/src/http/modules/ngx_http_gzip_static_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/http/modules/ngx_http_gzip_static_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -89,19 +89,17 @@
         return NGX_DECLINED;
     }
 
-    if (r->zero_in_uri) {
-        return NGX_DECLINED;
-    }
-
     gzcf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_static_module);
 
     if (!gzcf->enable) {
         return NGX_DECLINED;
     }
 
+    rc = ngx_http_gzip_ok(r);
+
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
-    if (clcf->gzip_vary && ngx_http_gzip_ok(r) != NGX_OK) {
+    if (!clcf->gzip_vary && rc != NGX_OK) {
         return NGX_DECLINED;
     }
 
@@ -124,6 +122,7 @@
 
     ngx_memzero(&of, sizeof(ngx_open_file_info_t));
 
+    of.read_ahead = clcf->read_ahead;
     of.directio = clcf->directio;
     of.valid = clcf->open_file_cache_valid;
     of.min_uses = clcf->open_file_cache_min_uses;
@@ -142,7 +141,6 @@
         case NGX_ENOTDIR:
         case NGX_ENAMETOOLONG:
 
-            r->gzip = 0;
             return NGX_DECLINED;
 
         case NGX_EACCES:
@@ -162,6 +160,12 @@
         return NGX_DECLINED;
     }
 
+    r->gzip_vary = 1;
+
+    if (rc != NGX_OK) {
+        return NGX_DECLINED;
+    }
+
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", of.fd);
 
     if (of.is_dir) {
@@ -172,7 +176,7 @@
 #if !(NGX_WIN32) /* the not regular files are probably Unix specific */
 
     if (!of.is_file) {
-        ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
+        ngx_log_error(NGX_LOG_CRIT, log, 0,
                       "\"%s\" is not a regular file", path.data);
 
         return NGX_HTTP_NOT_FOUND;
@@ -204,12 +208,10 @@
     }
 
     h->hash = 1;
-    h->key.len = sizeof("Content-Encoding") - 1;
-    h->key.data = (u_char *) "Content-Encoding";
-    h->value.len = sizeof("gzip") - 1;
-    h->value.data = (u_char *) "gzip";
+    ngx_str_set(&h->key, "Content-Encoding");
+    ngx_str_set(&h->value, "gzip");
+    r->headers_out.content_encoding = h;
 
-    r->headers_out.content_encoding = h;
     r->ignore_content_encoding = 1;
 
     /* we need to allocate all before the header would be sent */
--- a/src/http/modules/ngx_http_headers_filter_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/http/modules/ngx_http_headers_filter_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -196,8 +196,7 @@
         r->headers_out.expires = expires;
 
         expires->hash = 1;
-        expires->key.len = sizeof("Expires") - 1;
-        expires->key.data = (u_char *) "Expires";
+        ngx_str_set(&expires->key, "Expires");
     }
 
     len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT");
@@ -225,9 +224,7 @@
         }
 
         cc->hash = 1;
-        cc->key.len = sizeof("Cache-Control") - 1;
-        cc->key.data = (u_char *) "Cache-Control";
-
+        ngx_str_set(&cc->key, "Cache-Control");
         *ccp = cc;
 
     } else {
@@ -240,20 +237,14 @@
 
     if (conf->expires == NGX_HTTP_EXPIRES_EPOCH) {
         expires->value.data = (u_char *) "Thu, 01 Jan 1970 00:00:01 GMT";
-
-        cc->value.len = sizeof("no-cache") - 1;
-        cc->value.data = (u_char *) "no-cache";
-
+        ngx_str_set(&cc->value, "no-cache");
         return NGX_OK;
     }
 
     if (conf->expires == NGX_HTTP_EXPIRES_MAX) {
         expires->value.data = (u_char *) "Thu, 31 Dec 2037 23:55:55 GMT";
-
         /* 10 years */
-        cc->value.len = sizeof("max-age=315360000") - 1;
-        cc->value.data = (u_char *) "max-age=315360000";
-
+        ngx_str_set(&cc->value, "max-age=315360000");
         return NGX_OK;
     }
 
@@ -265,10 +256,7 @@
     if (conf->expires_time == 0) {
         ngx_memcpy(expires->value.data, ngx_cached_http_time.data,
                    ngx_cached_http_time.len + 1);
-
-        cc->value.len = sizeof("max-age=0") - 1;
-        cc->value.data = (u_char *) "max-age=0";
-
+        ngx_str_set(&cc->value, "max-age=0");
         return NGX_OK;
     }
 
@@ -291,10 +279,8 @@
 
     ngx_http_time(expires->value.data, expires_time);
 
-    if (conf->expires_time < 0) {
-        cc->value.len = sizeof("no-cache") - 1;
-        cc->value.data = (u_char *) "no-cache";
-
+    if (conf->expires_time < 0 || max_age < 0) {
+        ngx_str_set(&cc->value, "no-cache");
         return NGX_OK;
     }
 
@@ -361,8 +347,7 @@
     }
 
     cc->hash = 1;
-    cc->key.len = sizeof("Cache-Control") - 1;
-    cc->key.data = (u_char *) "Cache-Control";
+    ngx_str_set(&cc->key, "Cache-Control");
     cc->value = *value;
 
     *ccp = cc;
--- a/src/http/modules/ngx_http_image_filter_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/http/modules/ngx_http_image_filter_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -16,6 +16,7 @@
 #define NGX_HTTP_IMAGE_SIZE      2
 #define NGX_HTTP_IMAGE_RESIZE    3
 #define NGX_HTTP_IMAGE_CROP      4
+#define NGX_HTTP_IMAGE_ROTATE    5
 
 
 #define NGX_HTTP_IMAGE_START     0
@@ -38,12 +39,15 @@
     ngx_uint_t                   filter;
     ngx_uint_t                   width;
     ngx_uint_t                   height;
-    ngx_int_t                    jpeg_quality;
+    ngx_uint_t                   angle;
+    ngx_uint_t                   jpeg_quality;
 
     ngx_flag_t                   transparency;
 
     ngx_http_complex_value_t    *wcv;
     ngx_http_complex_value_t    *hcv;
+    ngx_http_complex_value_t    *acv;
+    ngx_http_complex_value_t    *jqcv;
 
     size_t                       buffer_size;
 } ngx_http_image_filter_conf_t;
@@ -57,12 +61,13 @@
 
     ngx_uint_t                   width;
     ngx_uint_t                   height;
-
     ngx_uint_t                   max_width;
     ngx_uint_t                   max_height;
+    ngx_uint_t                   angle;
 
     ngx_uint_t                   phase;
     ngx_uint_t                   type;
+    ngx_uint_t                   force;
 } ngx_http_image_filter_ctx_t;
 
 
@@ -98,13 +103,15 @@
     void *child);
 static char *ngx_http_image_filter(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
+static char *ngx_http_image_filter_jpeg_quality(ngx_conf_t *cf,
+    ngx_command_t *cmd, void *conf);
 static ngx_int_t ngx_http_image_filter_init(ngx_conf_t *cf);
 
 
 static ngx_command_t  ngx_http_image_filter_commands[] = {
 
     { ngx_string("image_filter"),
-      NGX_HTTP_LOC_CONF|NGX_CONF_TAKE13,
+      NGX_HTTP_LOC_CONF|NGX_CONF_TAKE13|NGX_CONF_TAKE2,
       ngx_http_image_filter,
       NGX_HTTP_LOC_CONF_OFFSET,
       0,
@@ -112,9 +119,9 @@
 
     { ngx_string("image_filter_jpeg_quality"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_num_slot,
+      ngx_http_image_filter_jpeg_quality,
       NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_image_filter_conf_t, jpeg_quality),
+      0,
       NULL },
 
     { ngx_string("image_filter_transparency"),
@@ -227,7 +234,7 @@
         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                       "image filter: too big response: %O", len);
 
-        return NGX_ERROR;
+        return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE;
     }
 
     if (len == -1) {
@@ -488,6 +495,17 @@
         return ngx_http_image_json(r, rc == NGX_OK ? ctx : NULL);
     }
 
+    ctx->angle = ngx_http_image_filter_get_value(r, conf->acv, conf->angle);
+
+    if (conf->filter == NGX_HTTP_IMAGE_ROTATE) {
+
+        if (ctx->angle != 90 && ctx->angle != 180 && ctx->angle != 270) {
+            return NULL;
+        }
+
+        return ngx_http_image_resize(r, ctx);
+    }
+
     ctx->max_width = ngx_http_image_filter_get_value(r, conf->wcv, conf->width);
     if (ctx->max_width == 0) {
         return NULL;
@@ -501,7 +519,9 @@
 
     if (rc == NGX_OK
         && ctx->width <= ctx->max_width
-        && ctx->height <= ctx->max_height)
+        && ctx->height <= ctx->max_height
+        && ctx->angle == 0
+        && !ctx->force)
     {
         return ngx_http_image_asis(r, ctx);
     }
@@ -527,8 +547,7 @@
     ngx_http_clean_header(r);
 
     r->headers_out.status = NGX_HTTP_OK;
-    r->headers_out.content_type.len = sizeof("text/plain") - 1;
-    r->headers_out.content_type.data = (u_char *) "text/plain";
+    ngx_str_set(&r->headers_out.content_type, "text/plain");
     r->headers_out.content_type_lowcase = NULL;
 
     if (ctx == NULL) {
@@ -601,6 +620,7 @@
 ngx_http_image_size(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
 {
     u_char      *p, *last;
+    size_t       len, app;
     ngx_uint_t   width, height;
 
     p = ctx->image;
@@ -611,26 +631,38 @@
 
         p += 2;
         last = ctx->image + ctx->length - 10;
+        width = 0;
+        height = 0;
+        app = 0;
 
         while (p < last) {
 
             if (p[0] == 0xff && p[1] != 0xff) {
 
                 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                               "JPEG: %02xd %02xd", *p, *(p + 1));
+                               "JPEG: %02xd %02xd", p[0], p[1]);
 
                 p++;
 
-                if (*p == 0xc0 || *p == 0xc1 || *p == 0xc2 || *p == 0xc3
-                    || *p == 0xc9 || *p == 0xca || *p == 0xcb)
+                if ((*p == 0xc0 || *p == 0xc1 || *p == 0xc2 || *p == 0xc3
+                     || *p == 0xc9 || *p == 0xca || *p == 0xcb)
+                    && (width == 0 || height == 0))
                 {
-                    goto found;
+                    width = p[6] * 256 + p[7];
+                    height = p[4] * 256 + p[5];
                 }
 
                 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                                "JPEG: %02xd %02xd", p[1], p[2]);
 
-                p += p[1] * 256 + p[2];
+                len = p[1] * 256 + p[2];
+
+                if (*p >= 0xe1 && *p <= 0xef) {
+                    /* application data, e.g., EXIF, Adobe XMP, etc. */
+                    app += len;
+                }
+
+                p += len;
 
                 continue;
             }
@@ -638,12 +670,16 @@
             p++;
         }
 
-        return NGX_DECLINED;
+        if (width == 0 || height == 0) {
+            return NGX_DECLINED;
+        }
 
-    found:
-
-        width = p[6] * 256 + p[7];
-        height = p[4] * 256 + p[5];
+        if (ctx->length / 20 < app) {
+            /* force conversion if application data consume more than 5% */
+            ctx->force = 1;
+            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                           "app data size: %uz", app);
+        }
 
         break;
 
@@ -689,7 +725,7 @@
 {
     int                            sx, sy, dx, dy, ox, oy, size,
                                    colors, palette, transparent,
-                                   red, green, blue;
+                                   red, green, blue, t;
     u_char                        *out;
     ngx_buf_t                     *b;
     ngx_uint_t                     resize;
@@ -708,7 +744,9 @@
 
     conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
 
-    if ((ngx_uint_t) sx <= ctx->max_width
+    if (!ctx->force
+        && ctx->angle == 0
+        && (ngx_uint_t) sx <= ctx->max_width
         && (ngx_uint_t) sy <= ctx->max_height)
     {
         gdImageDestroy(src);
@@ -759,6 +797,10 @@
 
         resize = 1;
 
+    } else if (conf->filter == NGX_HTTP_IMAGE_ROTATE) {
+
+        resize = 0;
+
     } else { /* NGX_HTTP_IMAGE_CROP */
 
         resize = 0;
@@ -807,6 +849,38 @@
         dst = src;
     }
 
+    if (ctx->angle) {
+        src = dst;
+
+        switch (ctx->angle) {
+
+        case 90:
+        case 270:
+            dst = ngx_http_image_new(r, dy, dx, palette);
+            if (dst == NULL) {
+                gdImageDestroy(src);
+                return NULL;
+            }
+            gdImageCopyRotated(dst, src, dy/2, dx/2, 0, 0, dx, dy, ctx->angle);
+            gdImageDestroy(src);
+
+            t = dx;
+            dx = dy;
+            dy = t;
+            break;
+
+        case 180:
+            dst = ngx_http_image_new(r, dx, dy, palette);
+            if (dst == NULL) {
+                gdImageDestroy(src);
+                return NULL;
+            }
+            gdImageCopyRotated(dst, src, dx/2, dy/2, 0, 0, dx, dy, ctx->angle);
+            gdImageDestroy(src);
+            break;
+        }
+    }
+
     if (conf->filter == NGX_HTTP_IMAGE_CROP) {
 
         src = dst;
@@ -970,6 +1044,7 @@
 {
     char                          *failed;
     u_char                        *out;
+    ngx_int_t                      jq;
     ngx_http_image_filter_conf_t  *conf;
 
     out = NULL;
@@ -978,7 +1053,13 @@
 
     case NGX_HTTP_IMAGE_JPEG:
         conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
-        out = gdImageJpegPtr(img, size, conf->jpeg_quality);
+
+        jq = ngx_http_image_filter_get_value(r, conf->jqcv, conf->jpeg_quality);
+        if (jq <= 0) {
+            return NULL;
+        }
+
+        out = gdImageJpegPtr(img, size, jq);
         failed = "gdImageJpegPtr() failed";
         break;
 
@@ -1060,7 +1141,8 @@
     }
 
     conf->filter = NGX_CONF_UNSET_UINT;
-    conf->jpeg_quality = NGX_CONF_UNSET;
+    conf->jpeg_quality = NGX_CONF_UNSET_UINT;
+    conf->angle = NGX_CONF_UNSET_UINT;
     conf->transparency = NGX_CONF_UNSET;
     conf->buffer_size = NGX_CONF_UNSET_SIZE;
 
@@ -1089,7 +1171,16 @@
     }
 
     /* 75 is libjpeg default quality */
-    ngx_conf_merge_value(conf->jpeg_quality, prev->jpeg_quality, 75);
+    ngx_conf_merge_uint_value(conf->jpeg_quality, prev->jpeg_quality, 75);
+
+    if (conf->jqcv == NULL) {
+        conf->jqcv = prev->jqcv;
+    }
+
+    ngx_conf_merge_uint_value(conf->angle, prev->angle, 0);
+    if (conf->acv == NULL) {
+        conf->acv = prev->acv;
+    }
 
     ngx_conf_merge_value(conf->transparency, prev->transparency, 1);
 
@@ -1130,6 +1221,46 @@
         }
 
         return NGX_CONF_OK;
+
+    } else if (cf->args->nelts == 3) {
+
+        if (ngx_strcmp(value[i].data, "rotate") == 0) {
+            imcf->filter = NGX_HTTP_IMAGE_ROTATE;
+
+            ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
+
+            ccv.cf = cf;
+            ccv.value = &value[++i];
+            ccv.complex_value = &cv;
+
+            if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
+                return NGX_CONF_ERROR;
+            }
+
+            if (cv.lengths == NULL) {
+                n = ngx_http_image_filter_value(&value[i]);
+
+                if (n != 90 && n != 180 && n != 270) {
+                    goto failed;
+                }
+
+                imcf->angle = (ngx_uint_t) n;
+
+            } else {
+                imcf->acv = ngx_palloc(cf->pool,
+                                       sizeof(ngx_http_complex_value_t));
+                if (imcf->acv == NULL) {
+                    return NGX_CONF_ERROR;
+                }
+
+                *imcf->acv = cv;
+            }
+
+            return NGX_CONF_OK;
+
+        } else {
+            goto failed;
+        }
     }
 
     if (ngx_strcmp(value[i].data, "resize") == 0) {
@@ -1209,6 +1340,53 @@
 }
 
 
+static char *
+ngx_http_image_filter_jpeg_quality(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf)
+{
+    ngx_http_image_filter_conf_t *imcf = conf;
+
+    ngx_str_t                         *value;
+    ngx_int_t                          n;
+    ngx_http_complex_value_t           cv;
+    ngx_http_compile_complex_value_t   ccv;
+
+    value = cf->args->elts;
+
+    ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
+
+    ccv.cf = cf;
+    ccv.value = &value[1];
+    ccv.complex_value = &cv;
+
+    if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
+        return NGX_CONF_ERROR;
+    }
+
+    if (cv.lengths == NULL) {
+        n = ngx_http_image_filter_value(&value[1]);
+
+        if (n <= 0) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "invalid parameter \"%V\"", &value[1]);
+            return NGX_CONF_ERROR;
+        }
+
+        imcf->jpeg_quality = (ngx_uint_t) n;
+
+    } else {
+        imcf->jqcv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
+        if (imcf->jqcv == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        *imcf->jqcv = cv;
+    }
+
+    return NGX_CONF_OK;
+}
+
+
 static ngx_int_t
 ngx_http_image_filter_init(ngx_conf_t *cf)
 {
--- a/src/http/modules/ngx_http_index_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/http/modules/ngx_http_index_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -116,10 +116,6 @@
         return NGX_DECLINED;
     }
 
-    if (r->zero_in_uri) {
-        return NGX_DECLINED;
-    }
-
     ilcf = ngx_http_get_module_loc_conf(r, ngx_http_index_module);
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
@@ -205,6 +201,7 @@
 
         ngx_memzero(&of, sizeof(ngx_open_file_info_t));
 
+        of.read_ahead = clcf->read_ahead;
         of.directio = clcf->directio;
         of.valid = clcf->open_file_cache_valid;
         of.min_uses = clcf->open_file_cache_min_uses;
@@ -222,7 +219,10 @@
                 return NGX_HTTP_INTERNAL_SERVER_ERROR;
             }
 
-            if (of.err == NGX_ENOTDIR || of.err == NGX_EACCES) {
+            if (of.err == NGX_ENOTDIR
+                || of.err == NGX_ENAMETOOLONG
+                || of.err == NGX_EACCES)
+            {
                 return ngx_http_index_error(r, clcf, path.data, of.err);
             }
 
--- a/src/http/modules/ngx_http_limit_req_module.c	Sun Sep 27 01:10:42 2009 +0400
+++ b/src/http/modules/ngx_http_limit_req_module.c	Mon Apr 25 04:22:17 2011 +0400
@@ -42,13 +42,16 @@
     ngx_shm_zone_t              *shm_zone;
     /* integer value, 1 corresponds to 0.001 r/s */
     ngx_uint_t                   burst;
-    ngx_uint_t                   nodelay;/* unsigned  nodelay:1 */
+    ngx_uint_t                   limit_log_level;
+    ngx_uint_t                   delay_log_level;
+
+    ngx_uint_t                   nodelay; /* unsigned  nodelay:1 */
 } ngx_http_limit_req_conf_t;
 
 
 static void ngx_http_limit_req_delay(ngx_http_request_t *r);
 static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf,
-    ngx_uint_t hash, u_char *data, size_t len, ngx_http_limit_req_node_t **lrp);
+    ngx_uint_t hash, u_char *data, size_t len, ngx_uint_t *ep);
 static void ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx,
     ngx_uint_t n);
 
@@ -62,6 +65,15 @@
 static ngx_int_t ngx_http_limit_req_init(ngx_conf_t *cf);
 
 
+static ngx_conf_enum_t  ngx_http_limit_req_log_levels[] = {
+    { ngx_string("info"), NGX_LOG_INFO },
+    { ngx_string("notice"), NGX_LOG_NOTICE },
+    { ngx_string("warn"), NGX_LOG_WARN },
+    { ngx_string("error"), NGX_LOG_ERR },
+    { ngx_null_string, 0 }
+};
+
+
 static ngx_command_t  ngx_http_limit_req_commands[] = {
 
     { ngx_string("limit_req_zone"),
@@ -78,6 +90,13 @@
       0,
       NULL },
 
+    { ngx_string("limit_req_log_level"),
+      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_limit_req_conf_t, limit_log_level),
+      &ngx_http_limit_req_log_levels },
+
       ngx_null_command
 };
 
@@ -167,96 +186,83 @@
 
     ngx_http_limit_req_expire(ctx, 1);
 
-    rc = ngx_http_limit_req_lookup(lrcf, hash, vv->data, len, &lr);
-
-    if (lr) {
-        ngx_queue_remove(&lr->queue);
-
-        ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);
-
-        excess = lr->excess;
-
-    } else {
-        excess = 0;
-    }
+    rc = ngx_http_limit_req_lookup(lrcf, hash, vv->data, len, &excess);
 
     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "limit_req: %i %ui.%03ui", rc, excess / 1000, excess % 1000);
 
-    if (rc == NGX_BUSY) {
+    if (rc == NGX_DECLINED) {
+
+        n = offsetof(ngx_rbtree_node_t, color)
+            + offsetof(ngx_http_limit_req_node_t, data)
+            + len;
+
+        node = ngx_slab_alloc_locked(ctx->shpool, n);
+        if (node == NULL) {
+
+            ngx_http_limit_req_expire(ctx, 0);
+
+            node = ngx_slab_alloc_locked(ctx->shpool, n);
+            if (node == NULL) {
+                ngx_shmtx_unlock(&ctx->shpool->mutex);
+                return NGX_HTTP_SERVICE_UNAVAILABLE;
+            }
+        }
+
+        lr = (ngx_http_limit_req_node_t *) &node->color;
+
+        node->key = hash;
+        lr->len = (u_char) len;
+
+        tp = ngx_timeofday();
+        lr->last = (ngx_msec_t) (tp->sec * 1000 + tp->msec);
+
+        lr->excess = 0;
+        ngx_memcpy(lr->data, vv->data, len);
+
+        ngx_rbtree_insert(&ctx->sh->rbtree, node);
+
+        ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);
+
         ngx_shmtx_unlock(&ctx->shpool->mutex);
 
-        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+        return NGX_DECLINED;
+    }
+
+    ngx_shmtx_unlock(&ctx->shpool->mutex);
+
+    if (rc == NGX_OK) {
+        return NGX_DECLINED;
+    }
+
+    if (rc == NGX_BUSY) {
+        ngx_log_error(lrcf->limit_log_level, r->connection->log, 0,
                       "limiting requests, excess: %ui.%03ui by zone \"%V\"",
                       excess / 1000, excess % 1000, &lrcf->shm_zone->shm.name);
 
         return NGX_HTTP_SERVICE_UNAVAILABLE;
     }
 
-    if (rc == NGX_AGAIN) {
-        ngx_shmtx_unlock(&ctx->shpool->mutex);
-
-        if (lrcf->nodelay) {
-            return NGX_DECLINED;
-        }
-
-        ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
-                      "delaying request, excess: %ui.%03ui, by zone \"%V\"",
-                      excess / 1000, excess % 1000, &lrcf->shm_zone->shm.name);
+    /* rc == NGX_AGAIN */
 
-        if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
-            return NGX_HTTP_INTERNAL_SERVER_ERROR;
-        }
-
-        r->read_event_handler = ngx_http_test_reading;
-        r->write_event_handler = ngx_http_limit_req_delay;
-        ngx_add_timer(r->connection->write, (ngx_msec_t) excess);
-
-        return NGX_AGAIN;
-    }
-
-    if (rc == NGX_OK) {
-        goto done;
+    if (lrcf->nodelay) {
+        return NGX_DECLINED;
     }
 
-    /* rc == NGX_DECLINED */
-
-    n = offsetof(ngx_rbtree_node_t, color)
-        + offsetof(ngx_http_limit_req_node_t, data)
-        + len;
+    ngx_log_error(lrcf->delay_log_level, r->connection->log, 0,
+                  "delaying request, excess: %ui.%03ui, by zone \"%V\"",
+                  excess / 1000, excess % 1000, &lrcf->shm_zone->shm.name);
 
-    node = ngx_slab_alloc_locked(ctx->shpool, n);
-    if (node == NULL) {
-
-        ngx_http_limit_req_expire(ctx, 0);
-
-        node = ngx_slab_alloc_locked(ctx->shpool, n);
-        if (node == NULL) {
-            ngx_shmtx_unlock(&ctx->shpool->mutex);
-            return NGX_HTTP_SERVICE_UNAVAILABLE;
-        }
+    if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    lr = (ngx_http_limit_req_node_t *) &node->color;
-
-    node->key = hash;
-    lr->len = (u_char) len;
-
-    tp = ngx_timeofday();
-    lr->last = (ngx_msec_t) (tp->sec * 1000 + tp->msec);
+    r->read_event_handler = ngx_http_test_reading;
+    r->write_event_handler = ngx_http_limit_req_delay;
+    ngx_add_timer(r->connection->write,
+                  (ngx_msec_t) excess * 1000 / ctx->rate);
 
-    lr->excess = 0;
-    ngx_memcpy(lr->data, vv->data, len);
-
-    ngx_rbtree_insert(&ctx->sh->rbtree, node);
-
-    ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);
-
-done:
-
-    ngx_shmtx_unlock(&ctx->shpool->mutex);
-
-    return NGX_DECLINED;
+    return NGX_AGAIN;
 }
 
 
@@ -336,7 +342,7 @@
 
 static ngx_int_t
 ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, ngx_uint_t hash,
-    u_char *data, size_t len, ngx_http_limit_req_node_t **lrp)
+    u_char *data, size_t len, ngx_uint_t *ep)
 {
     ngx_int_t                   rc, excess;
     ngx_time_t                 *tp;
@@ -371,6 +377,8 @@
             rc = ngx_memn2cmp(data, lr->data, len, (size_t) lr->len);
 
             if (rc == 0) {
+                ngx_queue_remove(&lr->queue);
+                ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);
 
                 tp = ngx_timeofday();
 
@@ -383,15 +391,15 @@
                     excess = 0;
                 }
 
-                lr->excess = excess;
-                lr->last = now;
-
-                *lrp = lr;
+                *ep = excess;
 
                 if ((ngx_uint_t) excess > lrcf->burst) {
                     return NGX_BUSY;
                 }
 
+                lr->excess = excess;
+                lr->last = now;
+
                 if (excess) {
                     return NGX_AGAIN;
                 }
@@ -406,7 +414,7 @@
         break;
     }
 
-    *lrp = NULL;
+    *ep = 0;
 
     return NGX_DECLINED;
 }
@@ -548,6 +556,8 @@
      *     conf->nodelay = 0;
      */
 
+    conf->limit_log_level = NGX_CONF_UNSET_UINT;
+
     return conf;
 }
 
@@ -562,6 +572,12 @@
         *conf = *prev;
     }
 
+    ngx_conf_merge_uint_value(conf->limit_log_level, prev->limit_log_level,
+                              NGX_LOG_ERR);
+
+    conf->delay_log_level = (conf->limit_log_level == NGX_LOG_INFO) ?
+                                NGX_LOG_INFO : conf->limit_log_level + 1;
+
     return NGX_CONF_OK;
 }
 
--- a/src/http/modules/ngx_http_limit_zone_module.c	Sun Sep 27 01:10:42 2009 +0400
+