changeset 492:98143f74eb3d NGINX_0_7_58

nginx 0.7.58 *) Feature: a "listen" directive of the mail proxy module supports IPv6. *) Feature: the "image_filter_jpeg_quality" directive. *) Feature: the "client_body_in_single_buffer" directive. *) Feature: the $request_body variable. *) Bugfix: in ngx_http_autoindex_module in file name links having a ":" symbol in the name. *) Bugfix: "make upgrade" procedure did not work; the bug had appeared in 0.7.53. Thanks to Denis F. Latypoff.
author Igor Sysoev <http://sysoev.ru>
date Mon, 18 May 2009 00:00:00 +0400
parents bb2281a3edb6
children d13d7ebf1370
files CHANGES CHANGES.ru auto/cc/owc auto/init auto/install auto/lib/md5/make auto/lib/md5/makefile.bcc auto/lib/md5/makefile.msvc auto/lib/md5/makefile.owc auto/lib/openssl/conf auto/lib/openssl/make auto/lib/openssl/makefile.bcc auto/lib/openssl/makefile.msvc auto/lib/pcre/make auto/lib/pcre/makefile.bcc auto/lib/pcre/makefile.msvc auto/lib/pcre/makefile.owc auto/lib/pcre/patch.config.in auto/lib/pcre/patch.pcre.c auto/lib/pcre/patch.pcre.in auto/lib/pcre/patch.pcre.in.owc auto/lib/sha1/make auto/lib/sha1/makefile.bcc auto/lib/sha1/makefile.msvc auto/lib/sha1/makefile.owc auto/lib/zlib/make auto/lib/zlib/makefile.bcc auto/lib/zlib/makefile.msvc auto/lib/zlib/makefile.owc auto/make src/core/nginx.h src/core/ngx_conf_file.c src/core/ngx_connection.c src/core/ngx_connection.h src/core/ngx_inet.c src/core/ngx_inet.h src/event/modules/ngx_aio_module.c src/http/modules/ngx_http_autoindex_module.c src/http/modules/ngx_http_image_filter_module.c src/http/modules/ngx_http_userid_filter_module.c src/http/modules/perl/nginx.pm src/http/ngx_http.c src/http/ngx_http_core_module.c src/http/ngx_http_core_module.h src/http/ngx_http_header_filter_module.c src/http/ngx_http_request.c src/http/ngx_http_upstream.c src/http/ngx_http_variables.c src/mail/ngx_mail.c src/mail/ngx_mail.h src/mail/ngx_mail_auth_http_module.c src/mail/ngx_mail_core_module.c src/mail/ngx_mail_handler.c src/mail/ngx_mail_smtp_handler.c
diffstat 54 files changed, 876 insertions(+), 488 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,22 @@
 
+Changes with nginx 0.7.58                                        18 May 2009
+
+    *) Feature: a "listen" directive of the mail proxy module supports IPv6.
+
+    *) Feature: the "image_filter_jpeg_quality" directive.
+
+    *) Feature: the "client_body_in_single_buffer" directive.
+
+    *) Feature: the $request_body variable.
+
+    *) Bugfix: in ngx_http_autoindex_module in file name links having a ":" 
+       symbol in the name.
+
+    *) Bugfix: "make upgrade" procedure did not work; the bug had appeared 
+       in 0.7.53.
+       Thanks to Denis F. Latypoff.
+
+
 Changes with nginx 0.7.57                                        12 May 2009
 
     *) Bugfix: a segmentation fault occurred in worker process, if the 
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,23 @@
 
+Изменения в nginx 0.7.58                                          18.05.2009
+
+    *) Добавление: директива listen почтового прокси-сервера поддерживает 
+       IPv6.
+
+    *) Добавление: директива image_filter_jpeg_quality.
+
+    *) Добавление: директива client_body_in_single_buffer.
+
+    *) Добавление: переменная $request_body.
+
+    *) Исправление: в модуле ngx_http_autoindex_module в ссылках на имена 
+       файлов, содержащих символ ":".
+
+    *) Исправление: процедура "make upgrade" не работала; ошибка появилась 
+       в 0.7.53.
+       Спасибо Денису Латыпову.
+
+
 Изменения в nginx 0.7.57                                          12.05.2009
 
     *) Исправление: при перенаправлении ошибок модуля 
--- a/auto/cc/owc
+++ b/auto/cc/owc
@@ -88,8 +88,16 @@ ngx_binext=".exe"
 ngx_regex_dirsep='\\'
 ngx_dirsep="\\"
 
-ngx_regex_cont=' '
-ngx_long_regex_cont=' '
-ngx_cont=' '
-ngx_long_cont=' '
-ngx_tab=' '
+ngx_long_start=' '
+ngx_long_end=' '
+ngx_long_regex_cont=' \&\
+	'
+ngx_long_cont=' &
+	'
+
+ngx_regex_cont=' \&\
+	'
+ngx_cont=' &
+	'
+ngx_tab=' &
+		'
--- a/auto/init
+++ b/auto/init
@@ -43,36 +43,8 @@ fi
 
 cat << END > Makefile
 
-build:
-	\$(MAKE) -f $NGX_MAKEFILE
-
-install:
-	\$(MAKE) -f $NGX_MAKEFILE install
+default:	build
 
 clean:
 	rm -rf Makefile $NGX_OBJS
-
-upgrade:
-	$NGX_SBIN_PATH -t
-
-	kill -USR2 \`cat $NGX_PID_PATH\`
-	sleep 1
-	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/install
+++ b/auto/install
@@ -124,3 +124,39 @@ if test -n "\$(DESTDIR)$NGX_ERROR_LOG_PA
 END
 
 fi
+
+
+# create Makefile
+
+cat << END >> Makefile
+
+build:
+	\$(MAKE) -f $NGX_MAKEFILE
+
+install:
+	\$(MAKE) -f $NGX_MAKEFILE install
+
+upgrade:
+	$NGX_SBIN_PATH -t
+
+	kill -USR2 \`cat $NGX_PID_PATH\`
+	sleep 1
+	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/md5/make
+++ b/auto/lib/md5/make
@@ -7,16 +7,19 @@ case "$NGX_CC_NAME" in
     msvc*)
         ngx_makefile=makefile.msvc
         ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC MD5_ASM=$MD5_ASM"
+        ngx_md5="MD5=\"$MD5\""
     ;;
 
     owc*)
         ngx_makefile=makefile.owc
         ngx_opt="CPU_OPT=\"$CPU_OPT\""
+        ngx_md5=`echo MD5=\"$MD5\" | sed -e "s/\//$ngx_regex_dirsep/g"`
     ;;
 
     bcc)
         ngx_makefile=makefile.bcc
         ngx_opt="-DCPU_OPT=\"$CPU_OPT\" -DMD5_ASM=$MD5_ASM"
+        ngx_md5=`echo \-DMD5=\"$MD5\" | sed -e "s/\//$ngx_regex_dirsep/g"`
     ;;
 
 esac
@@ -28,14 +31,10 @@ done=NO
 case "$NGX_PLATFORM" in
 
     win32)
-        cp auto/lib/md5/$ngx_makefile $MD5
-
         cat << END                                        >> $NGX_MAKEFILE
 
 `echo "$MD5/md5.lib:	$NGX_MAKEFILE" | sed -e "s/\//$ngx_regex_dirsep/g"`
-	cd `echo $MD5 | sed -e "s/\//$ngx_regex_dirsep/g"`
-	\$(MAKE) -f $ngx_makefile $ngx_opt
-	cd \$(CURDIR)
+	\$(MAKE) -f auto/lib/md5/$ngx_makefile $ngx_opt $ngx_md5
 
 END
 
--- a/auto/lib/md5/makefile.bcc
+++ b/auto/lib/md5/makefile.bcc
@@ -7,12 +7,14 @@ CFLAGS = -q -O2 -tWM $(CPU_OPT) -DL_ENDI
 !if "$(MD5_ASM)" == "YES"
 
 md5.lib:
+	cd $(MD5)
 	bcc32 -c $(CFLAGS) -DMD5_ASM md5_dgst.c
 	tlib md5.lib +md5_dgst.obj +"asm\m-win32.obj"
 
 !else
 
 md5.lib:
+	cd $(MD5)
 	bcc32 -c $(CFLAGS) md5_dgst.c
 	tlib md5.lib +md5_dgst.obj
 
--- a/auto/lib/md5/makefile.msvc
+++ b/auto/lib/md5/makefile.msvc
@@ -7,12 +7,14 @@ CFLAGS = -nologo -O2 -Ob1 -Oi -Gs $(LIBC
 !IF "$(MD5_ASM)" == "YES"
 
 md5.lib:
+	cd $(MD5)
 	cl -c $(CFLAGS) -D MD5_ASM md5_dgst.c
 	link -lib -out:md5.lib md5_dgst.obj asm/m-win32.obj
 
 !ELSE
 
 md5.lib:
+	cd $(MD5)
 	cl -c $(CFLAGS) md5_dgst.c
 	link -lib -out:md5.lib md5_dgst.obj
 
--- a/auto/lib/md5/makefile.owc
+++ b/auto/lib/md5/makefile.owc
@@ -5,5 +5,6 @@
 CFLAGS = -zq -bt=nt -bm -ot -op -oi -oe -s $(CPU_OPT)
 
 md5.lib:
+	cd $(MD5)
 	wcl386 -c $(CFLAGS) -dL_ENDIAN md5_dgst.c
 	wlib -n md5.lib md5_dgst.obj
--- a/auto/lib/openssl/conf
+++ b/auto/lib/openssl/conf
@@ -3,19 +3,19 @@
 
 
 if [ $OPENSSL != NONE ]; then
-    CORE_INCS="$CORE_INCS $OPENSSL/include"
 
     case "$CC" in
 
-        cl|bcc32)
+        cl | bcc32)
             have=NGX_OPENSSL . auto/have
             have=NGX_SSL . auto/have
 
-            LINK_DEPS="$LINK_DEPS $OPENSSL/out32/ssleay32.lib"
-            CORE_LIBS="$CORE_LIBS $OPENSSL/out32/ssleay32.lib"
+            CFLAGS="$CFLAGS -DNO_SYS_TYPES_H"
 
-            LINK_DEPS="$LINK_DEPS $OPENSSL/out32/libeay32.lib"
-            CORE_LIBS="$CORE_LIBS $OPENSSL/out32/libeay32.lib"
+            CORE_INCS="$CORE_INCS $OPENSSL/openssl/include"
+            CORE_DEPS="$CORE_DEPS $OPENSSL/openssl/include/openssl/ssl.h"
+            CORE_LIBS="$CORE_LIBS $OPENSSL/openssl/lib/ssleay32.lib"
+            CORE_LIBS="$CORE_LIBS $OPENSSL/openssl/lib/libeay32.lib"
 
             # libeay32.lib requires gdi32.lib
             CORE_LIBS="$CORE_LIBS gdi32.lib"
@@ -24,6 +24,8 @@ if [ $OPENSSL != NONE ]; then
         *)
             have=NGX_OPENSSL . auto/have
             have=NGX_SSL . auto/have
+
+            CORE_INCS="$CORE_INCS $OPENSSL/include"
             LINK_DEPS="$LINK_DEPS $OPENSSL/libssl.a $OPENSSL/libcrypto.a"
             CORE_LIBS="$CORE_LIBS $OPENSSL/libssl.a $OPENSSL/libcrypto.a"
         ;;
--- a/auto/lib/openssl/make
+++ b/auto/lib/openssl/make
@@ -3,7 +3,7 @@
 
 
 if test -n "$OPENSSL_OPT"; then
-    NGX_OPENSSL_CONFIG="./Configure \"$OPENSSL_OPT\""
+    NGX_OPENSSL_CONFIG="./Configure $OPENSSL_OPT"
 else
     NGX_OPENSSL_CONFIG="./config"
 fi
@@ -14,32 +14,37 @@ case $USE_THREADS in
 esac
 
 case "$CC" in
+
     cl)
+
         cat << END                                            >> $NGX_MAKEFILE
 
-$OPENSSL/out32/ssleay32.lib:
-	cd $OPENSSL
-	perl Configure VC-WIN32 no-shared
-	ms\\do_ms
-	\$(MAKE) -f ms\\nt.mak
-	cd \$(CURDIR)
+$OPENSSL/openssl/include/openssl/ssl.h:	$NGX_MAKEFILE
+	\$(MAKE) -f auto/lib/openssl/makefile.msvc			\
+		OPENSSL="$OPENSSL" OPENSSL_OPT="$OPENSSL_OPT"
 
 END
 
     ;;
 
-    bcc32)
+    cl | bcc32)
+
+        ngx_opt=`echo "-DOPENSSL=\"$OPENSSL\" -DOPENSSL_OPT=\"$OPENSSL_OPT\"" \
+            | sed -e "s/\//$ngx_regex_dirsep/g"`
+
         cat << END                                            >> $NGX_MAKEFILE
 
-`echo "$OPENSSL\\out32\\libeay32.lib:	$OPENSSL\\out32\\ssleay32.lib" \
+`echo "$OPENSSL\\openssl\\lib\\libeay32.lib:				\
+	$OPENSSL\\openssl\\include\\openssl\\ssl.h"			\
 	| sed -e "s/\//$ngx_regex_dirsep/g"`
 
-`echo "$OPENSSL\\out32\\ssleay32.lib:" | sed -e "s/\//$ngx_regex_dirsep/g"`
-	cd `echo "$OPENSSL" | sed -e "s/\//$ngx_regex_dirsep/g"`
-	perl Configure BC-32 no-shared
-	ms\\do_nasm
-	\$(MAKE) -f ms\\bcb.mak
-	cd \$(CURDIR)
+`echo "$OPENSSL\\openssl\\lib\\ssleay32.lib:				\
+	$OPENSSL\\openssl\\include\\openssl\\ssl.h"			\
+	| sed -e "s/\//$ngx_regex_dirsep/g"`
+
+`echo "$OPENSSL\\openssl\\include\\openssl\\ssl.h:	$NGX_MAKEFILE"	\
+	| sed -e "s/\//$ngx_regex_dirsep/g"`
+	\$(MAKE) -f auto/lib/openssl/makefile.bcc $ngx_opt
 
 END
 
@@ -48,7 +53,7 @@ END
     *)
         cat << END                                            >> $NGX_MAKEFILE
 
-$OPENSSL/libssl.a:
+$OPENSSL/libssl.a:	$NGX_MAKEFILE
 	cd $OPENSSL \\
 	&& \$(MAKE) clean \\
 	&& $NGX_OPENSSL_CONFIG no-shared \\
new file mode 100644
--- /dev/null
+++ b/auto/lib/openssl/makefile.bcc
@@ -0,0 +1,18 @@
+
+# Copyright (C) Igor Sysoev
+
+
+all:
+	cd $(OPENSSL)
+
+	perl Configure BC-32 no-shared --prefix=openssl -DNO_SYS_TYPES_H \
+		$(OPENSSL_OPT)
+
+	ms\do_nasm
+
+	$(MAKE) -f ms\bcb.mak
+	$(MAKE) -f ms\bcb.mak install
+
+	# Borland's make does not expand "[ch]" in
+	#    copy "inc32\openssl\*.[ch]" "openssl\include\openssl"
+	copy inc32\openssl\*.h openssl\include\openssl
new file mode 100644
--- /dev/null
+++ b/auto/lib/openssl/makefile.msvc
@@ -0,0 +1,14 @@
+
+# Copyright (C) Igor Sysoev
+
+
+all:
+	cd $(OPENSSL)
+
+	perl Configure VC-WIN32 no-shared --prefix=openssl -DNO_SYS_TYPES_H \
+		$(OPENSSL_OPT)
+
+	ms\do_ms
+
+	$(MAKE) -f ms\nt.mak
+	$(MAKE) -f ms\nt.mak install
--- a/auto/lib/pcre/make
+++ b/auto/lib/pcre/make
@@ -7,16 +7,19 @@ case "$NGX_CC_NAME" in
     msvc*)
         ngx_makefile=makefile.msvc
         ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC"
+        ngx_pcre="PCRE=\"$PCRE\""
     ;;
 
     owc*)
         ngx_makefile=makefile.owc
         ngx_opt="CPU_OPT=\"$CPU_OPT\""
+        ngx_pcre=`echo PCRE=\"$PCRE\" | sed -e "s/\//$ngx_regex_dirsep/g"`
     ;;
 
     bcc)
         ngx_makefile=makefile.bcc
         ngx_opt="-DCPU_OPT=\"$CPU_OPT\""
+        ngx_pcre=`echo \-DPCRE=\"$PCRE\" | sed -e "s/\//$ngx_regex_dirsep/g"`
     ;;
 
 esac
@@ -25,25 +28,14 @@ esac
 case "$NGX_PLATFORM" in
 
     win32)
-        cp auto/lib/pcre/patch.pcre.in $PCRE
-        cp auto/lib/pcre/patch.pcre.in.owc $PCRE
-        cp auto/lib/pcre/patch.config.in $PCRE
-        cp auto/lib/pcre/patch.pcre.c $PCRE
-        cp auto/lib/pcre/$ngx_makefile $PCRE
-
-        ngx_pcre=`echo $PCRE | sed -e "s/\//$ngx_regex_dirsep/g"`
 
         cat << END                                            >> $NGX_MAKEFILE
 
-`echo "$PCRE/pcre.h:	$NGX_MAKEFILE" | sed -e "s/\//$ngx_regex_dirsep/g"`
-	cd $ngx_pcre
-	\$(MAKE) -f $ngx_makefile pcre.h
-	cd \$(CURDIR)
+`echo "$PCRE/pcre.lib:	$NGX_MAKEFILE" | sed -e "s/\//$ngx_regex_dirsep/g"`
+	\$(MAKE) -f auto/lib/pcre/$ngx_makefile $ngx_pcre $ngx_opt
 
-`echo "$PCRE/pcre.lib:	$PCRE/pcre.h" | sed -e "s/\//$ngx_regex_dirsep/g"`
-	cd $ngx_pcre
-	\$(MAKE) -f $ngx_makefile $ngx_opt
-	cd \$(CURDIR)
+`echo "$PCRE/pcre.h:" | sed -e "s/\//$ngx_regex_dirsep/g"`
+	\$(MAKE) -f auto/lib/pcre/$ngx_makefile $ngx_pcre pcre.h
 
 END
 
@@ -60,7 +52,6 @@ END
 	&& CC="\$(CC)" CFLAGS="$PCRE_OPT" \\
 	./configure --disable-shared
 
-
 $PCRE/.libs/libpcre.a:	$PCRE/Makefile
 	cd $PCRE \\
 	&& \$(MAKE) libpcre.la
--- a/auto/lib/pcre/makefile.bcc
+++ b/auto/lib/pcre/makefile.bcc
@@ -3,19 +3,23 @@
 
 
 CFLAGS =	-q -O2 -tWM -w-8004 $(CPU_OPT)
-PCREFLAGS =	-DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10
+PCREFLAGS =	-DHAVE_CONFIG_H -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10
 
 
-pcre.lib:	pcre.h
-	bcc32 -q -edftables dftables.c
+pcre.lib:
+	cd $(PCRE)
+
+	bcc32 -c $(CFLAGS) -I. $(PCREFLAGS) pcre_*.c
 
-	dftables > chartables.c
+	> pcre.lst
+	for %n in (*.obj) do @echo +%n & >> pcre.lst
+	echo + >> pcre.lst
 
-	bcc32 -c $(CFLAGS) $(PCREFLAGS) maketables.c get.c study.c pcre.c
-
-	tlib pcre.lib +maketables.obj +get.obj +study.obj +pcre.obj
+	tlib pcre.lib @pcre.lst
 
 pcre.h:
-	patch -o pcre.h pcre.in patch.pcre.in
-	patch -o config.h config.in patch.config.in
-	patch < patch.pcre.c
+	cd $(PCRE)
+
+	copy /y pcre.h.generic pcre.h
+	copy /y config.h.generic config.h
+	copy /y pcre_chartables.c.dist pcre_chartables.c
--- a/auto/lib/pcre/makefile.msvc
+++ b/auto/lib/pcre/makefile.msvc
@@ -3,21 +3,19 @@
 
 
 CFLAGS =	-O2 -Ob1 -Oi -Gs $(LIBC) $(CPU_OPT)
-PCREFLAGS =	-DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10
+PCREFLAGS =	-DHAVE_CONFIG_H -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10
 
 
-pcre.lib:	pcre.h
-	cl -Fedftables dftables.c
-
-	dftables > chartables.c
+pcre.lib:
+	cd $(PCRE)
 
-	cl -nologo -c $(CFLAGS) $(PCREFLAGS)				\
-		maketables.c get.c study.c pcre.c
+	cl -nologo -c $(CFLAGS) -I . $(PCREFLAGS) pcre_*.c
 
-	link -lib -out:pcre.lib -verbose:lib				\
-		maketables.obj get.obj study.obj pcre.obj
+	link -lib -out:pcre.lib -verbose:lib pcre_*.obj
 
 pcre.h:
-	patch -o pcre.h pcre.in patch.pcre.in
-	patch -o config.h config.in patch.config.in
-	patch < patch.pcre.c
+	cd $(PCRE)
+
+	copy /y pcre.h.generic pcre.h
+	copy /y config.h.generic config.h
+	copy /y pcre_chartables.c.dist pcre_chartables.c
--- a/auto/lib/pcre/makefile.owc
+++ b/auto/lib/pcre/makefile.owc
@@ -3,17 +3,21 @@
 
 
 CFLAGS =	-c -zq -bt=nt -ot -op -oi -oe -s -bm $(CPU_OPT)
-PCREFLAGS =	-DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10
+PCREFLAGS =	-DHAVE_CONFIG_H -DPCRE_STATIC -DPOSIX_MALLOC_THRESHOLD=10
 
 
-pcre.lib:	pcre.h
-	wcl386 -zq -bt=nt -l=nt -fe=dftables dftables.c
-	dftables > chartables.c
+pcre.lib:
+	cd $(PCRE)
 
-	wcl386 $(CFLAGS) $(PCREFLAGS) maketables.c get.c study.c pcre.c
-	wlib -n pcre.lib maketables.obj get.obj study.obj pcre.obj
+	wcl386 $(CFLAGS) -i=. $(PCREFLAGS) pcre_*.c
 
+	dir /b *.obj > pcre.lst
+
+	wlib -n pcre.lib @pcre.lst
 
 pcre.h:
-	patch -o pcre.h pcre.in patch.pcre.in.owc
-	patch -o config.h config.in patch.config.in
+	cd $(PCRE)
+
+	copy /y pcre.h.generic pcre.h
+	copy /y config.h.generic config.h
+	copy /y pcre_chartables.c.dist pcre_chartables.c
deleted file mode 100644
--- a/auto/lib/pcre/patch.config.in
+++ /dev/null
@@ -1,11 +0,0 @@
---- config.in	Thu Aug 21 14:43:07 2003
-+++ config.in	Sun Mar  7 02:37:24 2004
-@@ -28,7 +28,7 @@
- found. */
- 
- #define HAVE_STRERROR 0
--#define HAVE_MEMMOVE  0
-+#define HAVE_MEMMOVE 1
- 
- /* There are some non-Unix systems that don't even have bcopy(). If this macro
- is false, an emulation is used. If HAVE_MEMMOVE is set to 1, the value of
deleted file mode 100644
--- a/auto/lib/pcre/patch.pcre.c
+++ /dev/null
@@ -1,13 +0,0 @@
---- pcre.c	Thu Aug 21 14:43:07 2003
-+++ pcre.c	Tue Mar 22 12:56:59 2005
-@@ -246,8 +246,8 @@
- extern "C" void  (*pcre_free)(void *) = free;
- extern "C" int   (*pcre_callout)(pcre_callout_block *) = NULL;
- #else
--void *(*pcre_malloc)(size_t) = malloc;
--void  (*pcre_free)(void *) = free;
-+void *(__cdecl *pcre_malloc)(size_t) = malloc;
-+void  (__cdecl *pcre_free)(void *) = free;
- int   (*pcre_callout)(pcre_callout_block *) = NULL;
- #endif
- #endif
deleted file mode 100644
--- a/auto/lib/pcre/patch.pcre.in
+++ /dev/null
@@ -1,26 +0,0 @@
---- pcre.in	Thu Aug 21 14:43:07 2003
-+++ pcre.h	Tue Mar 22 12:56:59 2005
-@@ -10,9 +10,9 @@
- /* The file pcre.h is build by "configure". Do not edit it; instead
- make changes to pcre.in. */
- 
--#define PCRE_MAJOR          @PCRE_MAJOR@
--#define PCRE_MINOR          @PCRE_MINOR@
--#define PCRE_DATE           @PCRE_DATE@
-+#define PCRE_MAJOR          4
-+#define PCRE_MINOR          4
-+#define PCRE_DATE           21-August-2003
- 
- /* Win32 uses DLL by default */
- 
-@@ -143,8 +143,8 @@
- have to be different again. */
- 
- #ifndef VPCOMPAT
--PCRE_DATA_SCOPE void *(*pcre_malloc)(size_t);
--PCRE_DATA_SCOPE void  (*pcre_free)(void *);
-+PCRE_DATA_SCOPE void *(__cdecl *pcre_malloc)(size_t);
-+PCRE_DATA_SCOPE void  (__cdecl *pcre_free)(void *);
- PCRE_DATA_SCOPE int   (*pcre_callout)(pcre_callout_block *);
- #else   /* VPCOMPAT */
- extern void *pcre_malloc(size_t);
deleted file mode 100644
--- a/auto/lib/pcre/patch.pcre.in.owc
+++ /dev/null
@@ -1,15 +0,0 @@
---- pcre.in	Thu Aug 21 14:43:07 2003
-+++ pcre.h	Tue Mar 22 12:56:59 2005
-@@ -10,9 +10,9 @@
- /* The file pcre.h is build by "configure". Do not edit it; instead
- make changes to pcre.in. */
- 
--#define PCRE_MAJOR          @PCRE_MAJOR@
--#define PCRE_MINOR          @PCRE_MINOR@
--#define PCRE_DATE           @PCRE_DATE@
-+#define PCRE_MAJOR          4
-+#define PCRE_MINOR          4
-+#define PCRE_DATE           21-August-2003
- 
- /* Win32 uses DLL by default */
- 
--- a/auto/lib/sha1/make
+++ b/auto/lib/sha1/make
@@ -7,16 +7,19 @@ case "$NGX_CC_NAME" in
     msvc*)
         ngx_makefile=makefile.msvc
         ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC SHA1_ASM=$SHA1_ASM"
+        ngx_sha1="SHA1=\"$SHA1\""
     ;;
 
     owc*)
         ngx_makefile=makefile.owc
         ngx_opt="CPU_OPT=\"$CPU_OPT\""
+        ngx_sha1=`echo SHA1=\"$SHA1\" | sed -e "s/\//$ngx_regex_dirsep/g"`
     ;;
 
     bcc)
         ngx_makefile=makefile.bcc
         ngx_opt="-DCPU_OPT=\"$CPU_OPT\" -DSHA1_ASM=$SHA1_ASM"
+        ngx_sha1=`echo \-DSHA1=\"$SHA1\" | sed -e "s/\//$ngx_regex_dirsep/g"`
     ;;
 
 esac
@@ -28,14 +31,10 @@ done=NO
 case "$NGX_PLATFORM" in
 
     win32)
-        cp auto/lib/sha1/$ngx_makefile $SHA1
-
         cat << END                                        >> $NGX_MAKEFILE
 
 `echo "$SHA1/sha1.lib:	$NGX_MAKEFILE" | sed -e "s/\//$ngx_regex_dirsep/g"`
-	cd `echo $SHA1 | sed -e "s/\//$ngx_regex_dirsep/g"`
-	\$(MAKE) -f $ngx_makefile $ngx_opt
-	cd \$(CURDIR)
+	\$(MAKE) -f auto/lib/sha1/$ngx_makefile $ngx_opt $ngx_sha1
 
 END
 
--- a/auto/lib/sha1/makefile.bcc
+++ b/auto/lib/sha1/makefile.bcc
@@ -7,12 +7,14 @@ CFLAGS = -q -O2 -tWM $(CPU_OPT) -DL_ENDI
 !if "$(SHA1_ASM)" == "YES"
 
 sha1.lib:
+	cd $(SHA1)
 	bcc32 -c $(CFLAGS) -DSHA1_ASM sha1dgst.c
 	tlib sha1.lib +sha1dgst.obj +"asm\s-win32.obj"
 
 !else
 
 sha1.lib:
+	cd $(SHA1)
 	bcc32 -c $(CFLAGS) sha1dgst.c
 	tlib sha1.lib +sha1dgst.obj
 
--- a/auto/lib/sha1/makefile.msvc
+++ b/auto/lib/sha1/makefile.msvc
@@ -7,12 +7,14 @@ CFLAGS = -nologo -O2 -Ob1 -Oi -Gs $(LIBC
 !IF "$(SHA1_ASM)" == "YES"
 
 sha1.lib:
+	cd $(SHA1)
 	cl -c $(CFLAGS) -D SHA1_ASM sha1dgst.c
 	link -lib -out:sha1.lib sha1dgst.obj asm/s-win32.obj
 
 !ELSE
 
 sha1.lib:
+	cd $(SHA1)
 	cl -c $(CFLAGS) sha1dgst.c
 	link -lib -out:sha1.lib sha1dgst.obj
 
--- a/auto/lib/sha1/makefile.owc
+++ b/auto/lib/sha1/makefile.owc
@@ -5,5 +5,6 @@
 CFLAGS = -zq -bt=nt -bm -ot -op -oi -oe -s $(CPU_OPT)
 
 sha1.lib:
+	cd $(SHA1)
 	wcl386 -c $(CFLAGS) -dL_ENDIAN sha1dgst.c
 	wlib -n sha1.lib sha1dgst.obj
--- a/auto/lib/zlib/make
+++ b/auto/lib/zlib/make
@@ -7,17 +7,20 @@ case "$NGX_CC_NAME" in
     msvc*)
         ngx_makefile=makefile.msvc
         ngx_opt="CPU_OPT=\"$CPU_OPT\" LIBC=$LIBC"
+        ngx_zlib="ZLIB=\"$ZLIB\""
 
     ;;
 
     owc*)
         ngx_makefile=makefile.owc
         ngx_opt="CPU_OPT=\"$CPU_OPT\""
+        ngx_zlib=`echo ZLIB=\"$ZLIB\" | sed -e "s/\//$ngx_regex_dirsep/g"`
     ;;
 
     bcc)
         ngx_makefile=makefile.bcc
         ngx_opt="-DCPU_OPT=\"$CPU_OPT\""
+        ngx_zlib=`echo \-DZLIB=\"$ZLIB\" | sed -e "s/\//$ngx_regex_dirsep/g"`
     ;;
 
 esac
@@ -29,14 +32,10 @@ done=NO
 case "$NGX_PLATFORM" in
 
     win32)
-        cp auto/lib/zlib/$ngx_makefile $ZLIB
-
         cat << END                                            >> $NGX_MAKEFILE
 
 `echo "$ZLIB/zlib.lib:	$NGX_MAKEFILE" | sed -e "s/\//$ngx_regex_dirsep/g"`
-	cd `echo $ZLIB | sed -e "s/\//$ngx_regex_dirsep/g"`
-	\$(MAKE) -f $ngx_makefile $ngx_opt
-	cd \$(CURDIR)
+	\$(MAKE) -f auto/lib/zlib/$ngx_makefile $ngx_opt $ngx_zlib
 
 END
 
--- a/auto/lib/zlib/makefile.bcc
+++ b/auto/lib/zlib/makefile.bcc
@@ -5,6 +5,8 @@
 CFLAGS = -q -O2 -tWM -w-8004 -w-8012 $(CPU_OPT)
 
 zlib.lib:
+	cd $(ZLIB)
+
 	bcc32 -c $(CFLAGS) adler32.c crc32.c deflate.c trees.c zutil.c \
 		compress.c
 
--- a/auto/lib/zlib/makefile.msvc
+++ b/auto/lib/zlib/makefile.msvc
@@ -5,6 +5,8 @@
 CFLAGS = -nologo -O2 -Ob1 -Oi -Gs $(LIBC) $(CPU_OPT)
 
 zlib.lib:
+	cd $(ZLIB)
+
 	cl -c $(CFLAGS) adler32.c crc32.c deflate.c trees.c zutil.c compress.c
 
 	link -lib -out:zlib.lib adler32.obj crc32.obj deflate.obj \
--- a/auto/lib/zlib/makefile.owc
+++ b/auto/lib/zlib/makefile.owc
@@ -5,5 +5,9 @@
 CFLAGS = -zq -bt=nt -ot -op -oi -oe -s -bm $(CPU_OPT)
 
 zlib.lib:
-	wcl386 -c $(CFLAGS) adler32.c crc32.c deflate.c trees.c zutil.c compress.c
-	wlib -n zlib.lib adler32.obj crc32.obj deflate.obj trees.obj zutil.obj compress.obj
+	cd $(ZLIB)
+
+	wcl386 -c $(CFLAGS) adler32.c crc32.c deflate.c trees.c zutil.c &
+		compress.c
+	wlib -n zlib.lib adler32.obj crc32.obj deflate.obj trees.obj &
+		zutil.obj compress.obj
--- a/auto/make
+++ b/auto/make
@@ -22,7 +22,6 @@ CC =	$CC
 CFLAGS = $CFLAGS
 CPP =	$CPP
 LINK =	$LINK
-CURDIR = `pwd`
 
 END
 
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,8 +8,8 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define nginx_version         7057
-#define NGINX_VERSION      "0.7.57"
+#define nginx_version         7058
+#define NGINX_VERSION      "0.7.58"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -446,7 +446,9 @@ ngx_conf_read_token(ngx_conf_t *cf)
     last_space = 1;
     sharp_comment = 0;
     variable = 0;
-    quoted = s_quoted = d_quoted = 0;
+    quoted = 0;
+    s_quoted = 0;
+    d_quoted = 0;
 
     cf->args->nelts = 0;
     b = cf->conf_file->buffer;
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -811,6 +811,66 @@ ngx_close_connection(ngx_connection_t *c
 
 
 ngx_int_t
+ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s,
+    ngx_uint_t port)
+{
+    socklen_t             len;
+    ngx_uint_t            addr;
+    u_char                sa[NGX_SOCKADDRLEN];
+    struct sockaddr_in   *sin;
+#if (NGX_HAVE_INET6)
+    ngx_uint_t            i;
+    struct sockaddr_in6  *sin6;
+#endif
+
+    switch (c->local_sockaddr->sa_family) {
+
+#if (NGX_HAVE_INET6)
+    case AF_INET6:
+        sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
+
+        for (addr = 0, i = 0; addr == 0 && i < 16; i++) {
+            addr |= sin6->sin6_addr.s6_addr[i];
+        }
+
+        break;
+#endif
+
+    default: /* AF_INET */
+        sin = (struct sockaddr_in *) c->local_sockaddr;
+        addr = sin->sin_addr.s_addr;
+        break;
+    }
+
+    if (addr == 0) {
+
+        len = NGX_SOCKADDRLEN;
+
+        if (getsockname(c->fd, (struct sockaddr *) &sa, &len) == -1) {
+            ngx_connection_error(c, ngx_socket_errno, "getsockname() failed");
+            return NGX_ERROR;
+        }
+
+        c->local_sockaddr = ngx_palloc(c->pool, len);
+        if (c->local_sockaddr == NULL) {
+            return NGX_ERROR;
+        }
+
+        c->local_socklen = len;
+        ngx_memcpy(c->local_sockaddr, &sa, len);
+    }
+
+    if (s == NULL) {
+        return NGX_OK;
+    }
+
+    s->len = ngx_sock_ntop(c->local_sockaddr, s->data, s->len, port);
+
+    return NGX_OK;
+}
+
+
+ngx_int_t
 ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text)
 {
     ngx_uint_t  level;
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -170,6 +170,8 @@ ngx_int_t ngx_open_listening_sockets(ngx
 void ngx_configure_listening_sockets(ngx_cycle_t *cycle);
 void ngx_close_listening_sockets(ngx_cycle_t *cycle);
 void ngx_close_connection(ngx_connection_t *c);
+ngx_int_t ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s,
+    ngx_uint_t port);
 ngx_int_t ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text);
 
 ngx_connection_t *ngx_get_connection(ngx_socket_t s, ngx_log_t *log);
--- a/src/core/ngx_inet.c
+++ b/src/core/ngx_inet.c
@@ -518,7 +518,6 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx
 
         (void) ngx_cpystrn(p, host, len);
 
-        u->addr.in_addr = inet_addr((const char *) p);
         sin->sin_addr.s_addr = inet_addr((const char *) p);
 
         if (sin->sin_addr.s_addr == INADDR_NONE) {
@@ -530,7 +529,6 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx
                 return NGX_ERROR;
             }
 
-            u->addr.in_addr = *(in_addr_t *) (h->h_addr_list[0]);
             sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[0]);
         }
 
@@ -541,7 +539,6 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx
         ngx_free(p);
 
     } else {
-        u->addr.in_addr = INADDR_ANY;
         sin->sin_addr.s_addr = INADDR_ANY;
         u->wildcard = 1;
     }
--- a/src/core/ngx_inet.h
+++ b/src/core/ngx_inet.h
@@ -61,11 +61,6 @@ typedef struct {
 } ngx_cidr_t;
 
 
-typedef union {
-    in_addr_t                 in_addr;
-} ngx_url_addr_t;
-
-
 typedef struct {
     struct sockaddr          *sockaddr;
     socklen_t                 socklen;
@@ -91,8 +86,6 @@ typedef struct {
     unsigned                  no_port:1;
     unsigned                  wildcard:1;
 
-    ngx_url_addr_t            addr;
-
     socklen_t                 socklen;
     u_char                    sockaddr[NGX_SOCKADDRLEN];
 
--- a/src/event/modules/ngx_aio_module.c
+++ b/src/event/modules/ngx_aio_module.c
@@ -134,12 +134,14 @@ ngx_aio_del_connection(ngx_connection_t 
     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "aio_cancel: %d", rc);
 
     if (rc == AIO_CANCELED) {
-        c->read->active = c->write->active = 0;
+        c->read->active = 0;
+        c->write->active = 0;
         return NGX_OK;
     }
 
     if (rc == AIO_ALLDONE) {
-        c->read->active = c->write->active = 0;
+        c->read->active = 0;
+        c->write->active = 0;
         ngx_log_error(NGX_LOG_ALERT, c->log, 0,
                       "aio_cancel() returned AIO_ALLDONE");
         return NGX_OK;
--- a/src/http/modules/ngx_http_autoindex_module.c
+++ b/src/http/modules/ngx_http_autoindex_module.c
@@ -25,8 +25,11 @@ typedef struct {
 typedef struct {
     ngx_str_t      name;
     size_t         utf_len;
-    ngx_uint_t     escape;
-    ngx_uint_t     dir;
+    size_t         escape;
+
+    unsigned       dir:1;
+    unsigned       colon:1;
+
     time_t         mtime;
     off_t          size;
 } ngx_http_autoindex_entry_t;
@@ -338,6 +341,8 @@ ngx_http_autoindex_handler(ngx_http_requ
             entry->utf_len = len;
         }
 
+        entry->colon = (ngx_strchr(entry->name.data, ':') != NULL);
+
         entry->dir = ngx_de_is_dir(&dir);
         entry->mtime = ngx_de_mtime(&dir);
         entry->size = ngx_de_size(&dir);
@@ -363,7 +368,7 @@ ngx_http_autoindex_handler(ngx_http_requ
             + entry[i].name.len + entry[i].escape
             + 1                                          /* 1 is for "/" */
             + sizeof("\">") - 1
-            + entry[i].name.len - entry[i].utf_len
+            + entry[i].name.len - entry[i].utf_len + entry[i].colon * 2
             + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof("&gt;") - 2
             + sizeof("</a>") - 1
             + sizeof(" 28-Sep-1970 12:00 ") - 1
@@ -396,6 +401,11 @@ ngx_http_autoindex_handler(ngx_http_requ
     for (i = 0; i < entries.nelts; i++) {
         b->last = ngx_cpymem(b->last, "<a href=\"", sizeof("<a href=\"") - 1);
 
+        if (entry[i].colon) {
+            *b->last++ = '.';
+            *b->last++ = '/';
+        }
+
         if (entry[i].escape) {
             ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len,
                            NGX_ESCAPE_HTML);
--- a/src/http/modules/ngx_http_image_filter_module.c
+++ b/src/http/modules/ngx_http_image_filter_module.c
@@ -38,6 +38,7 @@ typedef struct {
     ngx_uint_t                   filter;
     ngx_uint_t                   width;
     ngx_uint_t                   height;
+    ngx_int_t                    jpeg_quality;
 
     size_t                       buffer_size;
 } ngx_http_image_filter_conf_t;
@@ -98,6 +99,13 @@ static ngx_command_t  ngx_http_image_fil
       0,
       NULL },
 
+    { 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_LOC_CONF_OFFSET,
+      offsetof(ngx_http_image_filter_conf_t, jpeg_quality),
+      NULL },
+
     { ngx_string("image_filter_buffer"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
       ngx_conf_set_size_slot,
@@ -886,15 +894,17 @@ static u_char *
 ngx_http_image_out(ngx_http_request_t *r, ngx_uint_t type, gdImagePtr img,
     int *size)
 {
-    char    *failed;
-    u_char  *out;
+    char                          *failed;
+    u_char                        *out;
+    ngx_http_image_filter_conf_t  *conf;
 
     out = NULL;
 
     switch (type) {
 
     case NGX_HTTP_IMAGE_JPEG:
-        out = gdImageJpegPtr(img, size, /* default quality */ -1);
+        conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
+        out = gdImageJpegPtr(img, size, conf->jpeg_quality);
         failed = "gdImageJpegPtr() failed";
         break;
 
@@ -939,6 +949,7 @@ ngx_http_image_filter_create_conf(ngx_co
     }
 
     conf->filter = NGX_CONF_UNSET_UINT;
+    conf->jpeg_quality = NGX_CONF_UNSET;
     conf->buffer_size = NGX_CONF_UNSET_SIZE;
 
     return conf;
@@ -963,6 +974,9 @@ ngx_http_image_filter_merge_conf(ngx_con
         }
     }
 
+    /* 75 is libjpeg default quality */
+    ngx_conf_merge_value(conf->jpeg_quality, prev->jpeg_quality, 75);
+
     ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size,
                               1 * 1024 * 1024);
 
--- a/src/http/modules/ngx_http_userid_filter_module.c
+++ b/src/http/modules/ngx_http_userid_filter_module.c
@@ -390,12 +390,13 @@ ngx_http_userid_set_uid(ngx_http_request
 
         } else {
             if (conf->service == NGX_CONF_UNSET) {
-                if (ngx_http_server_addr(r, NULL) != NGX_OK) {
+
+                c = r->connection;
+
+                if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
                     return NGX_ERROR;
                 }
 
-                c = r->connection;
-
                 switch (c->local_sockaddr->sa_family) {
 
 #if (NGX_HAVE_INET6)
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -47,7 +47,7 @@ our @EXPORT = qw(
     HTTP_INSUFFICIENT_STORAGE
 );
 
-our $VERSION = '0.7.57';
+our $VERSION = '0.7.58';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -18,7 +18,7 @@ static ngx_int_t ngx_http_init_phase_han
     ngx_http_core_main_conf_t *cmcf);
 
 static ngx_int_t ngx_http_init_server_lists(ngx_conf_t *cf,
-    ngx_array_t *servers, ngx_array_t *in_ports);
+    ngx_array_t *servers, ngx_array_t *ports);
 static ngx_int_t ngx_http_add_ports(ngx_conf_t *cf,
     ngx_http_core_srv_conf_t *cscf, ngx_array_t *ports,
     ngx_http_listen_t *listen);
@@ -122,7 +122,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
     char                        *rv;
     ngx_uint_t                   mi, m, s;
     ngx_conf_t                   pcf;
-    ngx_array_t                  in_ports;
+    ngx_array_t                  ports;
     ngx_http_module_t           *module;
     ngx_http_conf_ctx_t         *ctx;
     ngx_http_core_loc_conf_t    *clcf;
@@ -367,14 +367,14 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
      * to find quickly the server core module configuration at run-time
      */
 
-    if (ngx_http_init_server_lists(cf, &cmcf->servers, &in_ports) != NGX_OK) {
+    if (ngx_http_init_server_lists(cf, &cmcf->servers, &ports) != NGX_OK) {
         return NGX_CONF_ERROR;
     }
 
 
     /* optimize the lists of ports, addresses and server names */
 
-    if (ngx_http_optimize_servers(cf, cmcf, &in_ports) != NGX_OK) {
+    if (ngx_http_optimize_servers(cf, cmcf, &ports) != NGX_OK) {
         return NGX_CONF_ERROR;
     }
 
@@ -1180,12 +1180,12 @@ ngx_http_add_ports(ngx_conf_t *cf, ngx_h
             continue;
         }
 
-        /* a port is already in the in_port list */
+        /* a port is already in the port list */
 
         return ngx_http_add_addresses(cf, cscf, &port[i], listen);
     }
 
-    /* add a port to the in_port list */
+    /* add a port to the port list */
 
     port = ngx_array_push(ports);
     if (port == NULL) {
@@ -1279,7 +1279,7 @@ ngx_http_add_addresses(ngx_conf_t *cf, n
 
 /*
  * add the server address, the server names and the server core module
- * configurations to the port (in_port)
+ * configurations to the port list
  */
 
 static ngx_int_t
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -355,12 +355,19 @@ static ngx_command_t  ngx_http_core_comm
       NULL },
 
     { ngx_string("client_body_in_file_only"),
-      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_enum_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_core_loc_conf_t, client_body_in_file_only),
       &ngx_http_core_request_body_in_file },
 
+    { ngx_string("client_body_in_single_buffer"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_core_loc_conf_t, client_body_in_single_buffer),
+      NULL },
+
     { ngx_string("sendfile"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
                         |NGX_CONF_TAKE1,
@@ -1317,6 +1324,8 @@ ngx_http_update_location_config(ngx_http
         r->request_body_file_log_level = NGX_LOG_WARN;
     }
 
+    r->request_body_in_single_buf = clcf->client_body_in_single_buffer;
+
     if (r->keepalive && clcf->keepalive_timeout == 0) {
         r->keepalive = 0;
     }
@@ -1819,68 +1828,6 @@ ngx_http_auth_basic_user(ngx_http_reques
 }
 
 
-ngx_int_t
-ngx_http_server_addr(ngx_http_request_t *r, ngx_str_t *s)
-{
-    socklen_t             len;
-    ngx_uint_t            addr;
-    ngx_connection_t     *c;
-    u_char                sa[NGX_SOCKADDRLEN];
-    struct sockaddr_in   *sin;
-#if (NGX_HAVE_INET6)
-    ngx_uint_t            i;
-    struct sockaddr_in6  *sin6;
-#endif
-
-    c = r->connection;
-
-    switch (c->local_sockaddr->sa_family) {
-
-#if (NGX_HAVE_INET6)
-    case AF_INET6:
-        sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
-
-        for (addr = 0, i = 0; addr == 0 && i < 16; i++) {
-            addr |= sin6->sin6_addr.s6_addr[i];
-        }
-
-        break;
-#endif
-
-    default: /* AF_INET */
-        sin = (struct sockaddr_in *) c->local_sockaddr;
-        addr = sin->sin_addr.s_addr;
-        break;
-    }
-
-    if (addr == 0) {
-
-        len = NGX_SOCKADDRLEN;
-
-        if (getsockname(c->fd, (struct sockaddr *) &sa, &len) == -1) {
-            ngx_connection_error(c, ngx_socket_errno, "getsockname() failed");
-            return NGX_ERROR;
-        }
-
-        c->local_sockaddr = ngx_palloc(r->connection->pool, len);
-        if (c->local_sockaddr == NULL) {
-            return NGX_ERROR;
-        }
-
-        c->local_socklen = len;
-        ngx_memcpy(c->local_sockaddr, &sa, len);
-    }
-
-    if (s == NULL) {
-        return NGX_OK;
-    }
-
-    s->len = ngx_sock_ntop(c->local_sockaddr, s->data, s->len, 0);
-
-    return NGX_OK;
-}
-
-
 #if (NGX_HTTP_GZIP)
 
 ngx_int_t
@@ -2953,8 +2900,9 @@ ngx_http_core_create_loc_conf(ngx_conf_t
     lcf->client_body_timeout = NGX_CONF_UNSET_MSEC;
     lcf->satisfy = NGX_CONF_UNSET_UINT;
     lcf->if_modified_since = NGX_CONF_UNSET_UINT;
+    lcf->client_body_in_file_only = NGX_CONF_UNSET_UINT;
+    lcf->client_body_in_single_buffer = NGX_CONF_UNSET;
     lcf->internal = NGX_CONF_UNSET;
-    lcf->client_body_in_file_only = NGX_CONF_UNSET;
     lcf->sendfile = NGX_CONF_UNSET;
     lcf->sendfile_max_chunk = NGX_CONF_UNSET_SIZE;
     lcf->directio = NGX_CONF_UNSET;
@@ -3144,9 +3092,11 @@ ngx_http_core_merge_loc_conf(ngx_conf_t 
                               NGX_HTTP_SATISFY_ALL);
     ngx_conf_merge_uint_value(conf->if_modified_since, prev->if_modified_since,
                               NGX_HTTP_IMS_EXACT);
+    ngx_conf_merge_uint_value(conf->client_body_in_file_only,
+                              prev->client_body_in_file_only, 0);
+    ngx_conf_merge_value(conf->client_body_in_single_buffer,
+                              prev->client_body_in_single_buffer, 0);
     ngx_conf_merge_value(conf->internal, prev->internal, 0);
-    ngx_conf_merge_value(conf->client_body_in_file_only,
-                              prev->client_body_in_file_only, 0);
     ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0);
     ngx_conf_merge_size_value(conf->sendfile_max_chunk,
                               prev->sendfile_max_chunk, 0);
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -339,9 +339,11 @@ struct ngx_http_core_loc_conf_s {
 
     ngx_uint_t    satisfy;                 /* satisfy */
     ngx_uint_t    if_modified_since;       /* if_modified_since */
+    ngx_uint_t    client_body_in_file_only; /* client_body_in_file_only */
 
+    ngx_flag_t    client_body_in_single_buffer;
+                                           /* client_body_in_singe_buffer */
     ngx_flag_t    internal;                /* internal */
-    ngx_flag_t    client_body_in_file_only; /* client_body_in_file_only */
     ngx_flag_t    sendfile;                /* sendfile */
     ngx_flag_t    tcp_nopush;              /* tcp_nopush */
     ngx_flag_t    tcp_nodelay;             /* tcp_nodelay */
@@ -438,7 +440,6 @@ ngx_int_t ngx_http_set_exten(ngx_http_re
 u_char *ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *name,
     size_t *root_length, size_t reserved);
 ngx_int_t ngx_http_auth_basic_user(ngx_http_request_t *r);
-ngx_int_t ngx_http_server_addr(ngx_http_request_t *r, ngx_str_t *s);
 #if (NGX_HTTP_GZIP)
 ngx_int_t ngx_http_gzip_ok(ngx_http_request_t *r);
 #endif
--- a/src/http/ngx_http_header_filter_module.c
+++ b/src/http/ngx_http_header_filter_module.c
@@ -165,6 +165,7 @@ ngx_http_header_filter(ngx_http_request_
     ngx_chain_t                out;
     ngx_list_part_t           *part;
     ngx_table_elt_t           *header;
+    ngx_connection_t          *c;
     ngx_http_core_loc_conf_t  *clcf;
     ngx_http_core_srv_conf_t  *cscf;
     struct sockaddr_in        *sin;
@@ -309,6 +310,8 @@ ngx_http_header_filter(ngx_http_request_
         len += sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1;
     }
 
+    c = r->connection;
+
     if (r->headers_out.location
         && r->headers_out.location->value.len
         && r->headers_out.location->value.data[0] == '/')
@@ -326,21 +329,21 @@ ngx_http_header_filter(ngx_http_request_
             host.len = NGX_SOCKADDR_STRLEN;
             host.data = addr;
 
-            if (ngx_http_server_addr(r, &host) != NGX_OK) {
+            if (ngx_connection_local_sockaddr(c, &host, 0) != NGX_OK) {
                 return NGX_ERROR;
             }
         }
 
-        switch (r->connection->local_sockaddr->sa_family) {
+        switch (c->local_sockaddr->sa_family) {
 
 #if (NGX_HAVE_INET6)
         case AF_INET6:
-            sin6 = (struct sockaddr_in6 *) r->connection->local_sockaddr;
+            sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
             port = ntohs(sin6->sin6_port);
             break;
 #endif
         default: /* AF_INET */
-            sin = (struct sockaddr_in *) r->connection->local_sockaddr;
+            sin = (struct sockaddr_in *) c->local_sockaddr;
             port = ntohs(sin->sin_port);
             break;
         }
@@ -352,7 +355,7 @@ ngx_http_header_filter(ngx_http_request_
         if (clcf->port_in_redirect) {
 
 #if (NGX_HTTP_SSL)
-            if (r->connection->ssl)
+            if (c->ssl)
                 port = (port == 443) ? 0 : port;
             else
 #endif
@@ -511,7 +514,7 @@ ngx_http_header_filter(ngx_http_request_
                              sizeof("Location: http") - 1);
 
 #if (NGX_HTTP_SSL)
-        if (r->connection->ssl) {
+        if (c->ssl) {
             *b->last++ ='s';
         }
 #endif
@@ -588,7 +591,7 @@ ngx_http_header_filter(ngx_http_request_
         *b->last++ = CR; *b->last++ = LF;
     }
 
-    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
                    "%*s", (size_t) (b->last - b->pos), b->pos);
 
     /* the end of HTTP header */
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -310,7 +310,7 @@ ngx_http_init_request(ngx_event_t *rev)
          * is required to determine a server address
          */
 
-        if (ngx_http_server_addr(r, NULL) != NGX_OK) {
+        if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
             ngx_http_close_connection(c);
             return;
         }
@@ -321,7 +321,7 @@ ngx_http_init_request(ngx_event_t *rev)
         case AF_INET6:
             sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
 
-            addr6 = (ngx_http_in6_addr_t *) port->addrs;
+            addr6 = port->addrs;
 
             /* the last address is "*" */
 
@@ -360,7 +360,7 @@ ngx_http_init_request(ngx_event_t *rev)
 
 #if (NGX_HAVE_INET6)
         case AF_INET6:
-            addr6 = (ngx_http_in6_addr_t *) port->addrs;
+            addr6 = port->addrs;
             addr_conf = &addr6[0].conf;
             break;
 #endif
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -972,7 +972,9 @@ ngx_http_upstream_connect(ngx_http_reque
     u->output.sendfile = c->sendfile;
 
     c->pool = r->pool;
-    c->read->log = c->write->log = c->log = r->connection->log;
+    c->log = r->connection->log;
+    c->read->log = c->log;
+    c->write->log = c->log;
 
     /* init or reinit the ngx_output_chain() and ngx_chain_writer() contexts */
 
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -62,6 +62,8 @@ static ngx_int_t ngx_http_variable_body_
     ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_variable_request_completion(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_variable_request_body(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_variable_request_body_file(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
 
@@ -202,6 +204,10 @@ static ngx_http_variable_t  ngx_http_cor
       ngx_http_variable_request_completion,
       0, 0, 0 },
 
+    { ngx_string("request_body"), NULL,
+      ngx_http_variable_request_body,
+      0, 0, 0 },
+
     { ngx_string("request_body_file"), NULL,
       ngx_http_variable_request_body_file,
       0, 0, 0 },
@@ -932,7 +938,7 @@ ngx_http_variable_server_addr(ngx_http_r
     s.len = NGX_SOCKADDR_STRLEN;
     s.data = addr;
 
-    if (ngx_http_server_addr(r, &s) != NGX_OK) {
+    if (ngx_connection_local_sockaddr(r->connection, &s, 0) != NGX_OK) {
         return NGX_ERROR;
     }
 
@@ -968,7 +974,7 @@ ngx_http_variable_server_port(ngx_http_r
     v->no_cacheable = 0;
     v->not_found = 0;
 
-    if (ngx_http_server_addr(r, NULL) != NGX_OK) {
+    if (ngx_connection_local_sockaddr(r->connection, NULL, 0) != NGX_OK) {
         return NGX_ERROR;
     }
 
@@ -1478,6 +1484,56 @@ ngx_http_variable_request_completion(ngx
 
 
 static ngx_int_t
+ngx_http_variable_request_body(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data)
+{
+    u_char       *p;
+    size_t        len;
+    ngx_buf_t    *buf, *next;
+    ngx_chain_t  *cl;
+
+    if (r->request_body == NULL || r->request_body->temp_file) {
+        v->not_found = 1;
+
+        return NGX_OK;
+    }
+
+    cl = r->request_body->bufs;
+    buf = cl->buf;
+
+    if (cl->next == NULL) {
+        v->len = buf->last - buf->pos;
+        v->valid = 1;
+        v->no_cacheable = 0;
+        v->not_found = 0;
+        v->data = buf->pos;
+
+        return NGX_OK;
+    }
+
+    next = cl->next->buf;
+    len = (buf->last - buf->pos) + (next->last - next->pos);
+
+    p = ngx_pnalloc(r->pool, len);
+    if (p == NULL) {
+        return NGX_ERROR;
+    }
+
+    v->data = p;
+
+    p = ngx_cpymem(p, buf->pos, buf->last - buf->pos);
+    ngx_memcpy(p, next->pos, next->last - next->pos);
+
+    v->len = len;
+    v->valid = 1;
+    v->no_cacheable = 0;
+    v->not_found = 0;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
 ngx_http_variable_request_body_file(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data)
 {
--- a/src/mail/ngx_mail.c
+++ b/src/mail/ngx_mail.c
@@ -11,7 +11,16 @@
 
 
 static char *ngx_mail_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-static ngx_int_t ngx_mail_cmp_conf_in_addrs(const void *one, const void *two);
+static ngx_int_t ngx_mail_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
+    ngx_mail_listen_t *listen);
+static char *ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports);
+static ngx_int_t ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport,
+    ngx_mail_conf_addr_t *addr);
+#if (NGX_HAVE_INET6)
+static ngx_int_t ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport,
+    ngx_mail_conf_addr_t *addr);
+#endif
+static ngx_int_t ngx_mail_cmp_conf_addrs(const void *one, const void *two);
 
 
 ngx_uint_t  ngx_mail_max_module;
@@ -64,19 +73,12 @@ static char *
 ngx_mail_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     char                        *rv;
-    u_char                      *text;
-    size_t                       len;
-    ngx_uint_t                   i, a, l, m, mi, s, p, last, bind_all, done;
+    ngx_uint_t                   i, m, mi, s;
     ngx_conf_t                   pcf;
-    ngx_array_t                  in_ports;
-    ngx_listening_t             *ls;
-    ngx_mail_listen_t           *mls;
+    ngx_array_t                  ports;
+    ngx_mail_listen_t           *listen;
     ngx_mail_module_t           *module;
-    struct sockaddr_in           sin;
-    ngx_mail_in_port_t          *mip;
     ngx_mail_conf_ctx_t         *ctx;
-    ngx_mail_conf_in_port_t     *in_port;
-    ngx_mail_conf_in_addr_t     *in_addr;
     ngx_mail_core_srv_conf_t   **cscfp;
     ngx_mail_core_main_conf_t   *cmcf;
 
@@ -217,98 +219,149 @@ ngx_mail_block(ngx_conf_t *cf, ngx_comma
     *cf = pcf;
 
 
-    if (ngx_array_init(&in_ports, cf->temp_pool, 4,
-                       sizeof(ngx_mail_conf_in_port_t))
+    if (ngx_array_init(&ports, cf->temp_pool, 4, sizeof(ngx_mail_conf_port_t))
         != NGX_OK)
     {
         return NGX_CONF_ERROR;
     }
 
-    mls = cmcf->listen.elts;
-
-    for (l = 0; l < cmcf->listen.nelts; l++) {
-
-        /* AF_INET only */
+    listen = cmcf->listen.elts;
 
-        in_port = in_ports.elts;
-        for (p = 0; p < in_ports.nelts; p++) {
-            if (in_port[p].port == mls[l].port) {
-                in_port = &in_port[p];
-                goto found;
-            }
-        }
-
-        in_port = ngx_array_push(&in_ports);
-        if (in_port == NULL) {
-            return NGX_CONF_ERROR;
-        }
-
-        in_port->port = mls[l].port;
-
-        if (ngx_array_init(&in_port->addrs, cf->temp_pool, 2,
-                           sizeof(ngx_mail_conf_in_addr_t))
-            != NGX_OK)
-        {
+    for (i = 0; i < cmcf->listen.nelts; i++) {
+        if (ngx_mail_add_ports(cf, &ports, &listen[i]) != NGX_OK) {
             return NGX_CONF_ERROR;
         }
+    }
 
-    found:
+    return ngx_mail_optimize_servers(cf, &ports);
+}
+
+
+static ngx_int_t
+ngx_mail_add_ports(ngx_conf_t *cf, ngx_array_t *ports,
+    ngx_mail_listen_t *listen)
+{
+    in_port_t              p;
+    ngx_uint_t             i;
+    struct sockaddr       *sa;
+    struct sockaddr_in    *sin;
+    ngx_mail_conf_port_t  *port;
+    ngx_mail_conf_addr_t  *addr;
+#if (NGX_HAVE_INET6)
+    struct sockaddr_in6   *sin6;
+#endif
+
+    sa = (struct sockaddr *) &listen->sockaddr;
 
-        in_addr = ngx_array_push(&in_port->addrs);
-        if (in_addr == NULL) {
-            return NGX_CONF_ERROR;
+    switch (sa->sa_family) {
+
+#if (NGX_HAVE_INET6)
+    case AF_INET6:
+        sin6 = (struct sockaddr_in6 *) sa;
+        p = sin6->sin6_port;
+        break;
+#endif
+
+    default: /* AF_INET */
+        sin = (struct sockaddr_in *) sa;
+        p = sin->sin_port;
+        break;
+    }
+
+    port = ports->elts;
+    for (i = 0; i < ports->nelts; i++) {
+        if (p == port[i].port && sa->sa_family == port[i].family) {
+
+            /* a port is already in the port list */
+
+            port = &port[i];
+            goto found;
         }
-
-        in_addr->addr = mls[l].addr;
-        in_addr->ctx = mls[l].ctx;
-        in_addr->bind = mls[l].bind;
-#if (NGX_MAIL_SSL)
-        in_addr->ssl = mls[l].ssl;
-#endif
     }
 
-    /* optimize the lists of ports and addresses */
+    /* add a port to the port list */
+
+    port = ngx_array_push(ports);
+    if (port == NULL) {
+        return NGX_ERROR;
+    }
+
+    port->family = sa->sa_family;
+    port->port = p;
 
-    /* AF_INET only */
+    if (ngx_array_init(&port->addrs, cf->temp_pool, 2,
+                       sizeof(ngx_mail_conf_addr_t))
+        != NGX_OK)
+    {
+        return NGX_ERROR;
+    }
+
+found:
+
+    addr = ngx_array_push(&port->addrs);
+    if (addr == NULL) {
+        return NGX_ERROR;
+    }
 
-    in_port = in_ports.elts;
-    for (p = 0; p < in_ports.nelts; p++) {
+    addr->sockaddr = (struct sockaddr *) &listen->sockaddr;
+    addr->socklen = listen->socklen;
+    addr->ctx = listen->ctx;
+    addr->bind = listen->bind;
+    addr->wildcard = listen->wildcard;
+#if (NGX_MAIL_SSL)
+    addr->ssl = listen->ssl;
+#endif
+#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
+    addr->ipv6only = listen->ipv6only;
+#endif
+
+    return NGX_OK;
+}
+
 
-        ngx_sort(in_port[p].addrs.elts, (size_t) in_port[p].addrs.nelts,
-                 sizeof(ngx_mail_conf_in_addr_t), ngx_mail_cmp_conf_in_addrs);
+static char *
+ngx_mail_optimize_servers(ngx_conf_t *cf, ngx_array_t *ports)
+{
+    ngx_uint_t             i, p, last, bind_wildcard;
+    ngx_listening_t       *ls;
+    ngx_mail_port_t       *mport;
+    ngx_mail_conf_port_t  *port;
+    ngx_mail_conf_addr_t  *addr;
 
-        in_addr = in_port[p].addrs.elts;
-        last = in_port[p].addrs.nelts;
+    port = ports->elts;
+    for (p = 0; p < ports->nelts; p++) {
+
+        ngx_sort(port[p].addrs.elts, (size_t) port[p].addrs.nelts,
+                 sizeof(ngx_mail_conf_addr_t), ngx_mail_cmp_conf_addrs);
+
+        addr = port[p].addrs.elts;
+        last = port[p].addrs.nelts;
 
         /*
          * if there is the binding to the "*:port" then we need to bind()
          * to the "*:port" only and ignore the other bindings
          */
 
-        if (in_addr[last - 1].addr == INADDR_ANY) {
-            in_addr[last - 1].bind = 1;
-            bind_all = 0;
+        if (addr[last - 1].wildcard) {
+            addr[last - 1].bind = 1;
+            bind_wildcard = 1;
 
         } else {
-            bind_all = 1;
+            bind_wildcard = 0;
         }
 
-        for (a = 0; a < last; /* void */ ) {
+        i = 0;
 
-            if (!bind_all && !in_addr[a].bind) {
-                a++;
+        while (i < last) {
+
+            if (bind_wildcard && !addr[i].bind) {
+                i++;
                 continue;
             }
 
-            ngx_memzero(&sin, sizeof(struct sockaddr_in));
-
-            sin.sin_family = AF_INET;
-            sin.sin_addr.s_addr = in_addr[a].addr;
-            sin.sin_port = htons(in_port[p].port);
-
-            ls = ngx_create_listening(cf, &sin, sizeof(struct sockaddr_in));
+            ls = ngx_create_listening(cf, addr[i].sockaddr, addr[i].socklen);
             if (ls == NULL) {
-                return NULL;
+                return NGX_CONF_ERROR;
             }
 
             ls->addr_ntop = 1;
@@ -320,75 +373,42 @@ ngx_mail_block(ngx_conf_t *cf, ngx_comma
             ls->log.data = &ls->addr_text;
             ls->log.handler = ngx_accept_log_error;
 
-            mip = ngx_palloc(cf->pool, sizeof(ngx_mail_in_port_t));
-            if (mip == NULL) {
+#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
+            ls->ipv6only = addr[i].ipv6only;
+#endif
+
+            mport = ngx_palloc(cf->pool, sizeof(ngx_mail_port_t));
+            if (mport == NULL) {
                 return NGX_CONF_ERROR;
             }
 
-            ls->servers = mip;
-
-            in_addr = in_port[p].addrs.elts;
+            ls->servers = mport;
 
-            if (in_addr[a].bind && in_addr[a].addr != INADDR_ANY) {
-                mip->naddrs = 1;
-                done = 0;
-
-            } else if (in_port[p].addrs.nelts > 1
-                       && in_addr[last - 1].addr == INADDR_ANY)
-            {
-                mip->naddrs = last;
-                done = 1;
+            if (i == last - 1) {
+                mport->naddrs = last;
 
             } else {
-                mip->naddrs = 1;
-                done = 0;
+                mport->naddrs = 1;
+                i = 0;
             }
 
-#if 0
-            ngx_log_error(NGX_LOG_ALERT, cf->log, 0,
-                          "%ui: %V %d %ui %ui",
-                          a, &ls->addr_text, in_addr[a].bind,
-                          mip->naddrs, last);
-#endif
-
-            mip->addrs = ngx_pcalloc(cf->pool,
-                                     mip->naddrs * sizeof(ngx_mail_in_addr_t));
-            if (mip->addrs == NULL) {
-                return NGX_CONF_ERROR;
-            }
-
-            for (i = 0; i < mip->naddrs; i++) {
-                mip->addrs[i].addr = in_addr[i].addr;
-                mip->addrs[i].ctx = in_addr[i].ctx;
-
-                text = ngx_pnalloc(cf->pool,
-                                   NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1);
-                if (text == NULL) {
+            switch (ls->sockaddr->sa_family) {
+#if (NGX_HAVE_INET6)
+            case AF_INET6:
+                if (ngx_mail_add_addrs6(cf, mport, addr) != NGX_OK) {
                     return NGX_CONF_ERROR;
                 }
-
-                len = ngx_inet_ntop(AF_INET, &in_addr[i].addr, text,
-                                    NGX_INET_ADDRSTRLEN);
-
-                len = ngx_sprintf(text + len, ":%d", in_port[p].port) - text;
-
-                mip->addrs[i].addr_text.len = len;
-                mip->addrs[i].addr_text.data = text;
-
-#if (NGX_MAIL_SSL)
-                mip->addrs[i].ssl = in_addr[i].ssl;
+                break;
 #endif
-            }
-
-            if (done) {
+            default: /* AF_INET */
+                if (ngx_mail_add_addrs(cf, mport, addr) != NGX_OK) {
+                    return NGX_CONF_ERROR;
+                }
                 break;
             }
 
-            in_addr++;
-            in_port[p].addrs.elts = in_addr;
+            addr++;
             last--;
-
-            a = 0;
         }
     }
 
@@ -397,15 +417,111 @@ ngx_mail_block(ngx_conf_t *cf, ngx_comma
 
 
 static ngx_int_t
-ngx_mail_cmp_conf_in_addrs(const void *one, const void *two)
+ngx_mail_add_addrs(ngx_conf_t *cf, ngx_mail_port_t *mport,
+    ngx_mail_conf_addr_t *addr)
 {
-    ngx_mail_conf_in_addr_t  *first, *second;
+    u_char              *p;
+    size_t               len;
+    ngx_uint_t           i;
+    ngx_mail_in_addr_t  *addrs;
+    struct sockaddr_in  *sin;
+    u_char               buf[NGX_SOCKADDR_STRLEN];
+
+    mport->addrs = ngx_pcalloc(cf->pool,
+                               mport->naddrs * sizeof(ngx_mail_in_addr_t));
+    if (mport->addrs == NULL) {
+        return NGX_ERROR;
+    }
+
+    addrs = mport->addrs;
+
+    for (i = 0; i < mport->naddrs; i++) {
+
+        sin = (struct sockaddr_in *) addr[i].sockaddr;
+        addrs[i].addr = sin->sin_addr.s_addr;
+
+        addrs[i].conf.ctx = addr[i].ctx;
+#if (NGX_MAIL_SSL)
+        addrs[i].conf.ssl = addr[i].ssl;
+#endif
+
+        len = ngx_sock_ntop(addr[i].sockaddr, buf, NGX_SOCKADDR_STRLEN, 1);
+
+        p = ngx_pnalloc(cf->pool, len);
+        if (p == NULL) {
+            return NGX_ERROR;
+        }
+
+        ngx_memcpy(p, buf, len);
+
+        addrs[i].conf.addr_text.len = len;
+        addrs[i].conf.addr_text.data = p;
+    }
+
+    return NGX_OK;
+}
+
+
+#if (NGX_HAVE_INET6)
 
-    first = (ngx_mail_conf_in_addr_t *) one;
-    second = (ngx_mail_conf_in_addr_t *) two;
+static ngx_int_t
+ngx_mail_add_addrs6(ngx_conf_t *cf, ngx_mail_port_t *mport,
+    ngx_mail_conf_addr_t *addr)
+{
+    u_char               *p;
+    size_t                len;
+    ngx_uint_t            i;
+    ngx_mail_in6_addr_t  *addrs6;
+    struct sockaddr_in6  *sin6;
+    u_char                buf[NGX_SOCKADDR_STRLEN];
+
+    mport->addrs = ngx_pcalloc(cf->pool,
+                               mport->naddrs * sizeof(ngx_mail_in6_addr_t));
+    if (mport->addrs == NULL) {
+        return NGX_ERROR;
+    }
+
+    addrs6 = mport->addrs;
+
+    for (i = 0; i < mport->naddrs; i++) {
+
+        sin6 = (struct sockaddr_in6 *) addr[i].sockaddr;
+        addrs6[i].addr6 = sin6->sin6_addr;
+
+        addrs6[i].conf.ctx = addr[i].ctx;
+#if (NGX_MAIL_SSL)
+        addrs6[i].conf.ssl = addr[i].ssl;
+#endif
 
-    if (first->addr == INADDR_ANY) {
-        /* the INADDR_ANY must be the last resort, shift it to the end */
+        len = ngx_sock_ntop(addr[i].sockaddr, buf, NGX_SOCKADDR_STRLEN, 1);
+
+        p = ngx_pnalloc(cf->pool, len);
+        if (p == NULL) {
+            return NGX_ERROR;
+        }
+
+        ngx_memcpy(p, buf, len);
+
+        addrs6[i].conf.addr_text.len = len;
+        addrs6[i].conf.addr_text.data = p;
+    }
+
+    return NGX_OK;
+}
+
+#endif
+
+
+static ngx_int_t
+ngx_mail_cmp_conf_addrs(const void *one, const void *two)
+{
+    ngx_mail_conf_addr_t  *first, *second;
+
+    first = (ngx_mail_conf_addr_t *) one;
+    second = (ngx_mail_conf_addr_t *) two;
+
+    if (first->wildcard) {
+        /* a wildcard must be the last resort, shift it to the end */
         return 1;
     }
 
--- a/src/mail/ngx_mail.h
+++ b/src/mail/ngx_mail.h
@@ -26,50 +26,76 @@ typedef struct {
 
 
 typedef struct {
-    in_addr_t               addr;
-    in_port_t               port;
-    int                     family;
+    u_char                  sockaddr[NGX_SOCKADDRLEN];
+    socklen_t               socklen;
 
     /* server ctx */
     ngx_mail_conf_ctx_t    *ctx;
 
     unsigned                bind:1;
+    unsigned                wildcard:1;
 #if (NGX_MAIL_SSL)
     unsigned                ssl:1;
 #endif
+#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
+    unsigned                ipv6only:2;
+#endif
 } ngx_mail_listen_t;
 
 
 typedef struct {
-    in_addr_t               addr;
     ngx_mail_conf_ctx_t    *ctx;
     ngx_str_t               addr_text;
 #if (NGX_MAIL_SSL)
     ngx_uint_t              ssl;    /* unsigned   ssl:1; */
 #endif
+} ngx_mail_addr_conf_t;
+
+typedef struct {
+    in_addr_t               addr;
+    ngx_mail_addr_conf_t    conf;
 } ngx_mail_in_addr_t;
 
 
+#if (NGX_HAVE_INET6)
+
 typedef struct {
-    ngx_mail_in_addr_t     *addrs;       /* array of ngx_mail_in_addr_t */
-    ngx_uint_t              naddrs;
-} ngx_mail_in_port_t;
+    struct in6_addr         addr6;
+    ngx_mail_addr_conf_t    conf;
+} ngx_mail_in6_addr_t;
+
+#endif
 
 
 typedef struct {
+    /* ngx_mail_in_addr_t or ngx_mail_in6_addr_t */
+    void                   *addrs;
+    ngx_uint_t              naddrs;
+} ngx_mail_port_t;
+
+
+typedef struct {
+    int                     family;
     in_port_t               port;
-    ngx_array_t             addrs;       /* array of ngx_mail_conf_in_addr_t */
-} ngx_mail_conf_in_port_t;
+    ngx_array_t             addrs;       /* array of ngx_mail_conf_addr_t */
+} ngx_mail_conf_port_t;
 
 
 typedef struct {
-    in_addr_t               addr;
+    struct sockaddr        *sockaddr;
+    socklen_t               socklen;
+
     ngx_mail_conf_ctx_t    *ctx;
+
     unsigned                bind:1;
+    unsigned                wildcard:1;
 #if (NGX_MAIL_SSL)
     unsigned                ssl:1;
 #endif
-} ngx_mail_conf_in_addr_t;
+#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
+    unsigned                ipv6only:2;
+#endif
+} ngx_mail_conf_addr_t;
 
 
 typedef struct {
--- a/src/mail/ngx_mail_auth_http_module.c
+++ b/src/mail/ngx_mail_auth_http_module.c
@@ -771,6 +771,8 @@ ngx_mail_auth_http_process_headers(ngx_m
                 return;
             }
 
+            /* AF_INET only */
+
             sin = ngx_pcalloc(s->connection->pool, sizeof(struct sockaddr_in));
             if (sin == NULL) {
                 ngx_destroy_pool(ctx->pool);
--- a/src/mail/ngx_mail_core_module.c
+++ b/src/mail/ngx_mail_core_module.c
@@ -274,19 +274,24 @@ ngx_mail_core_server(ngx_conf_t *cf, ngx
 }
 
 
-/* AF_INET only */
-
 static char *
 ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     ngx_mail_core_srv_conf_t  *cscf = conf;
 
+    size_t                      len, off;
+    in_port_t                   port;
     ngx_str_t                  *value;
     ngx_url_t                   u;
     ngx_uint_t                  i, m;
+    struct sockaddr            *sa;
     ngx_mail_listen_t          *ls;
     ngx_mail_module_t          *module;
+    struct sockaddr_in         *sin;
     ngx_mail_core_main_conf_t  *cmcf;
+#if (NGX_HAVE_INET6)
+    struct sockaddr_in6        *sin6;
+#endif
 
     value = cf->args->elts;
 
@@ -305,18 +310,42 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx
         return NGX_CONF_ERROR;
     }
 
-    if (u.family != AF_INET) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "listen supports IPv4 only");
-        return NGX_CONF_ERROR;
-    }
-
     cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module);
 
     ls = cmcf->listen.elts;
 
     for (i = 0; i < cmcf->listen.nelts; i++) {
 
-        if (ls[i].addr != u.addr.in_addr || ls[i].port != u.port) {
+        sa = (struct sockaddr *) ls[i].sockaddr;
+
+        if (sa->sa_family != u.family) {
+            continue;
+        }
+
+        switch (sa->sa_family) {
+
+#if (NGX_HAVE_INET6)
+        case AF_INET6:
+            off = offsetof(struct sockaddr_in6, sin6_addr);
+            len = 16;
+            sin6 = (struct sockaddr_in6 *) sa;
+            port = sin6->sin6_port;
+            break;
+#endif
+
+        default: /* AF_INET */
+            off = offsetof(struct sockaddr_in, sin_addr);
+            len = 4;
+            sin = (struct sockaddr_in *) sa;
+            port = sin->sin_port;
+            break;
+        }
+
+        if (ngx_memcmp(ls[i].sockaddr + off, u.sockaddr + off, len) != 0) {
+            continue;
+        }
+
+        if (port != u.port) {
             continue;
         }
 
@@ -332,9 +361,10 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx
 
     ngx_memzero(ls, sizeof(ngx_mail_listen_t));
 
-    ls->addr = u.addr.in_addr;
-    ls->port = u.port;
-    ls->family = u.family;
+    ngx_memcpy(ls->sockaddr, u.sockaddr, u.socklen);
+
+    ls->socklen = u.socklen;
+    ls->wildcard = u.wildcard;
     ls->ctx = cf->ctx;
 
     for (m = 0; ngx_modules[m]; m++) {
@@ -363,6 +393,47 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx
             continue;
         }
 
+        if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) {
+#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
+            struct sockaddr  *sa;
+            u_char            buf[NGX_SOCKADDR_STRLEN];
+
+            sa = (struct sockaddr *) ls->sockaddr;
+
+            if (sa->sa_family == AF_INET6) {
+
+                if (ngx_strcmp(&value[i].data[10], "n") == 0) {
+                    ls->ipv6only = 1;
+
+                } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) {
+                    ls->ipv6only = 2;
+
+                } else {
+                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                       "invalid ipv6only flags \"%s\"",
+                                       &value[i].data[9]);
+                    return NGX_CONF_ERROR;
+                }
+
+                ls->bind = 1;
+
+            } else {
+                len = ngx_sock_ntop(sa, buf, NGX_SOCKADDR_STRLEN, 1);
+
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                   "ipv6only is not supported "
+                                   "on addr \"%*s\", ignored", len, buf);
+            }
+
+            continue;
+#else
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "bind ipv6only is not supported "
+                               "on this platform");
+            return NGX_CONF_ERROR;
+#endif
+        }
+
         if (ngx_strcmp(value[i].data, "ssl") == 0) {
 #if (NGX_MAIL_SSL)
             ls->ssl = 1;
--- a/src/mail/ngx_mail_handler.c
+++ b/src/mail/ngx_mail_handler.c
@@ -21,25 +21,27 @@ static void ngx_mail_ssl_handshake_handl
 void
 ngx_mail_init_connection(ngx_connection_t *c)
 {
-    in_addr_t             in_addr;
-    socklen_t             len;
-    ngx_uint_t            i;
-    struct sockaddr_in    sin;
-    ngx_mail_log_ctx_t   *ctx;
-    ngx_mail_in_port_t   *mip;
-    ngx_mail_in_addr_t   *mia;
-    ngx_mail_session_t   *s;
+    ngx_uint_t             i;
+    ngx_mail_port_t       *port;
+    struct sockaddr       *sa;
+    struct sockaddr_in    *sin;
+    ngx_mail_log_ctx_t    *ctx;
+    ngx_mail_in_addr_t    *addr;
+    ngx_mail_session_t    *s;
+    ngx_mail_addr_conf_t  *addr_conf;
+#if (NGX_HAVE_INET6)
+    struct sockaddr_in6   *sin6;
+    ngx_mail_in6_addr_t   *addr6;
+#endif
+
 
     /* find the server configuration for the address:port */
 
     /* AF_INET only */
 
-    mip = c->listening->servers;
-    mia = mip->addrs;
+    port = c->listening->servers;
 
-    i = 0;
-
-    if (mip->naddrs > 1) {
+    if (port->naddrs > 1) {
 
         /*
          * There are several addresses on this port and one of them
@@ -49,45 +51,79 @@ ngx_mail_init_connection(ngx_connection_
          * AcceptEx() already gave this address.
          */
 
-#if (NGX_WIN32)
-        if (c->local_sockaddr) {
-            in_addr =
-                   ((struct sockaddr_in *) c->local_sockaddr)->sin_addr.s_addr;
+        if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
+            ngx_mail_close_connection(c);
+            return;
+        }
+
+        sa = c->local_sockaddr;
+
+        switch (sa->sa_family) {
 
-        } else
-#endif
-        {
-            len = sizeof(struct sockaddr_in);
-            if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) {
-                ngx_connection_error(c, ngx_socket_errno,
-                                     "getsockname() failed");
-                ngx_mail_close_connection(c);
-                return;
+#if (NGX_HAVE_INET6)
+        case AF_INET6:
+            sin6 = (struct sockaddr_in6 *) sa;
+
+            addr6 = port->addrs;
+
+            /* the last address is "*" */
+
+            for (i = 0; i < port->naddrs - 1; i++) {
+                if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) {
+                    break;
+                }
             }
 
-            in_addr = sin.sin_addr.s_addr;
+            addr_conf = &addr6[i].conf;
+
+            break;
+#endif
+
+        default: /* AF_INET */
+            sin = (struct sockaddr_in *) sa;
+
+            addr = port->addrs;
+
+            /* the last address is "*" */
+
+            for (i = 0; i < port->naddrs - 1; i++) {
+                if (addr[i].addr == sin->sin_addr.s_addr) {
+                    break;
+                }
+            }
+
+            addr_conf = &addr[i].conf;
+
+            break;
         }
 
-        /* the last address is "*" */
+    } else {
+        switch (c->local_sockaddr->sa_family) {
 
-        for ( /* void */ ; i < mip->naddrs - 1; i++) {
-            if (in_addr == mia[i].addr) {
-                break;
-            }
+#if (NGX_HAVE_INET6)
+        case AF_INET6:
+            addr6 = port->addrs;
+            addr_conf = &addr6[0].conf;
+            break;
+#endif
+
+        default: /* AF_INET */
+            addr = port->addrs;
+            addr_conf = &addr[0].conf;
+            break;
         }
     }
 
-
     s = ngx_pcalloc(c->pool, sizeof(ngx_mail_session_t));
     if (s == NULL) {
         ngx_mail_close_connection(c);
         return;
     }
 
-    s->main_conf = mia[i].ctx->main_conf;
-    s->srv_conf = mia[i].ctx->srv_conf;
+    s->main_conf = addr_conf->ctx->main_conf;
+    s->srv_conf = addr_conf->ctx->srv_conf;
 
-    s->addr_text = &mia[i].addr_text;
+    s->addr_text = &addr_conf->addr_text;
 
     c->data = s;
     s->connection = c;
@@ -124,7 +160,7 @@ ngx_mail_init_connection(ngx_connection_
         return;
     }
 
-    if (mia[i].ssl) {
+    if (addr_conf->ssl) {
 
         c->log->action = "SSL handshaking";
 
--- a/src/mail/ngx_mail_smtp_handler.c
+++ b/src/mail/ngx_mail_smtp_handler.c
@@ -66,6 +66,12 @@ ngx_mail_smtp_init_session(ngx_mail_sess
         return;
     }
 
+    if (c->sockaddr->sa_family != AF_INET) {
+        s->host = smtp_tempunavail;
+        ngx_mail_smtp_greeting(s, c);
+        return;
+    }
+
     c->log->action = "in resolving client address";
 
     ctx = ngx_resolve_start(cscf->resolver, NULL);