From: Bartosz Świątek Date: Mon, 15 Apr 2013 13:57:07 +0000 (+0200) Subject: - new, 5.3.24 X-Git-Url: https://git.tld-linux.org/?a=commitdiff_plain;h=aef9a98d7828aeb48703ab2429a6968173d1addf;p=packages%2Fphp.git - new, 5.3.24 --- aef9a98d7828aeb48703ab2429a6968173d1addf diff --git a/bug-test-pcntl-55479.patch b/bug-test-pcntl-55479.patch new file mode 100644 index 0000000..8f20b23 --- /dev/null +++ b/bug-test-pcntl-55479.patch @@ -0,0 +1,35 @@ +need to setup extension dir to current build instead of defaulting to system +defaults (which may be different php version) +also use preprocessed PHP.INI from test framework + +--- php-5.4.0alpha3/ext/pcntl/tests/pcntl_exec.phpt 2011-06-24 22:18:06.000000000 +0300 ++++ php-5.4.0alpha3/ext/pcntl/tests/pcntl_exec.phpt 2011-08-22 09:36:01.105334996 +0300 +@@ -8,7 +8,10 @@ + --FILE-- + + --EXPECT-- +--- php-5.4.0alpha3/ext/pcntl/tests/pcntl_exec_2.phpt~ 2011-06-24 22:18:06.000000000 +0300 ++++ php-5.4.0alpha3/ext/pcntl/tests/pcntl_exec_2.phpt 2011-08-22 19:57:12.780576314 +0300 +@@ -14,7 +14,13 @@ + exit; + } + echo "ok\n"; +-pcntl_exec(getenv("TEST_PHP_EXECUTABLE"), array(__FILE__), array( ++ ++$php = getenv("TEST_PHP_EXECUTABLE"); ++$extension_dir = ini_get("extension_dir"); ++$inipath = php_ini_loaded_file(); ++$args = array("-n", "-d$extension_dir", "-c$inipath", __FILE__); ++ ++pcntl_exec($php, $args, array( + b"PCNTL_EXEC_TEST_IS_CHILD" => b"1", + b"FOO" => b"BAR", + 1 => b"long") diff --git a/dep-tests.sh b/dep-tests.sh new file mode 100644 index 0000000..0a19c23 --- /dev/null +++ b/dep-tests.sh @@ -0,0 +1,57 @@ +#!/bin/sh +# inter-dependencies checker. + +with_mysqlnd=mysqlnd + +dep_spl="pcre simplexml" +dep_session="spl $dep_spl" +dep_filter='pcre' +dep_eaccelerator='session' +dep_mysql="$with_mysqlnd" +dep_mysqli="$dep_spl spl $with_mysqlnd" +dep_pdo="$dep_spl spl" +dep_pdo_sqlite="$dep_pdo pdo" +dep_pdo_pgsql="$dep_pdo pdo" +dep_pdo_oci="$dep_pdo pdo" +dep_pdo_odbc="$dep_pdo pdo" +dep_pdo_firebird="$dep_pdo pdo" +dep_pdo_dblib="$dep_pdo pdo" +dep_pdo_mysql="$dep_pdo pdo $with_mysqlnd" +dep_simplexml="$dep_spl spl" +dep_imap="pcre" +dep_phar="$dep_spl spl" +dep_sqlite="$dep_pdo pdo" +dep_fileinfo="pcre" +dep_wddx='xml' +dep_xmlreader='dom' +dep_xmlrpc='xml' +dep_xsl='dom' + +php=${PHP:-$(php-config --php-binary)} +ext_dir=${EXTENSION_DIR:-$(php-config --extension-dir)} +conf_dir=${CONFIG_DIR:-$(php-config --sysconfdir)/conf.d $(php-config --sysconfdir)/cli.d} +tmpini=$(mktemp) + +# poldek --sn ac-ready -u php-* +for ext in $ext_dir/*.so; do + [ -f $ext ] || continue + ext=${ext##*/}; ext=${ext%.so} + + deps=$(eval echo \$dep_$ext) + # add ext itself, if already not in list (spl case) + [[ $deps = *\ $ext\ * ]] || deps="$deps $ext" + + echo -n "$ext (deps: ${deps# })..." + + grep -rlE '^extension=('$(echo "${deps# }" | tr ' ' '|')').so$' $conf_dir | LC_CTYPE=C LC_ALL= sort | xargs cat > $tmpini + $php -n -d extension_dir=$ext_dir -c $tmpini -r "exit(extension_loaded('${ext}') ? 0 : 1);" + rc=$? + if [ $rc = 0 ]; then + echo OK + else + echo FAIL + echo "Failed config was:" + cat $tmpini + fi +done +rm -f $t diff --git a/embed.patch b/embed.patch new file mode 100644 index 0000000..44276de --- /dev/null +++ b/embed.patch @@ -0,0 +1,12 @@ +--- php-5.2.4/sapi/embed/config.m4.embed ++++ php-5.2.4/sapi/embed/config.m4 +@@ -12,7 +12,8 @@ if test "$PHP_EMBED" != "no"; then + case "$PHP_EMBED" in + yes|shared) + PHP_EMBED_TYPE=shared +- INSTALL_IT="\$(mkinstalldirs) \$(INSTALL_ROOT)\$(prefix)/lib; \$(INSTALL) -m 0755 $SAPI_SHARED \$(INSTALL_ROOT)\$(prefix)/lib" ++ EXTRA_LDFLAGS="$EXTRA_LDFLAGS -release \$(PHP_VERSION)" ++ INSTALL_IT="\$(mkinstalldirs) \$(INSTALL_ROOT)\$(libdir); \$(LIBTOOL) --mode=install \$(INSTALL) -m 0755 \$(OVERALL_TARGET) \$(INSTALL_ROOT)\$(libdir)" + ;; + static) + PHP_EMBED_TYPE=static diff --git a/extension-shared-optional-dep.patch b/extension-shared-optional-dep.patch new file mode 100644 index 0000000..be4597f --- /dev/null +++ b/extension-shared-optional-dep.patch @@ -0,0 +1,11 @@ +--- php-5.2.11/acinclude.m4~ 2009-09-21 22:31:13.000000000 +0300 ++++ php-5.2.11/acinclude.m4 2009-09-21 22:32:11.001106977 +0300 +@@ -1019,7 +1019,7 @@ + is_it_shared=$[PHP_]translit($2,a-z_-,A-Z__)[_SHARED] + is_it_enabled=$[PHP_]translit($2,a-z_-,A-Z__) + if test "$am_i_shared" = "no" && test "$is_it_shared" = "yes" ; then +- AC_MSG_ERROR([ ++ AC_MSG_WARN([ + You've configured extension $1 to build statically, but it + depends on extension $2, which you've configured to build shared. + You either need to build $1 shared or build $2 statically for the diff --git a/fix-test-run.patch b/fix-test-run.patch new file mode 100644 index 0000000..aa13506 --- /dev/null +++ b/fix-test-run.patch @@ -0,0 +1,45 @@ +--- php-5.3.2/configure.in~ 2010-03-16 12:16:56.000000000 +0200 ++++ php-5.3.2/configure.in 2010-03-16 16:13:24.926435546 +0200 +@@ -1224,6 +1224,11 @@ + PHP_SUBST(PHP_CLI_OBJS) + PHP_SUBST(PHP_GLOBAL_OBJS) + ++# shift so that pcre, spl, ... are loaded first ++PHP_MODULES=$(echo "$PHP_MODULES" | sed -e 's,\(.*\)\(\$(phplibdir)/xml.la \),\2\1,') ++PHP_MODULES=$(echo "$PHP_MODULES" | sed -e 's,\(.*\)\(\$(phplibdir)/spl.la \),\2\1,') ++PHP_MODULES=$(echo "$PHP_MODULES" | sed -e 's,\(.*\)\(\$(phplibdir)/pcre.la \),\2\1,') ++ + PHP_SUBST(PHP_MODULES) + PHP_SUBST(PHP_ZEND_EX) + +--- php-5.3.8/Makefile.global~ 2011-10-14 08:58:00.288329595 +0300 ++++ php-5.3.8/Makefile.global 2011-10-14 08:50:16.670234576 +0300 +@@ -77,8 +77,15 @@ + done; \ + fi + +-PHP_TEST_SETTINGS = -d 'open_basedir=' -d 'output_buffering=0' -d 'memory_limit=-1' ++PHP_TEST_SETTINGS = -d 'open_basedir=' -d 'output_buffering=0' -d 'memory_limit=-1' -d 'safe_mode=0' ++PHP_TEST_SHARED_SYSTEM_EXTENSIONS = + PHP_TEST_SHARED_EXTENSIONS = ` \ ++ if test "x$(PHP_TEST_SHARED_SYSTEM_EXTENSIONS)" != "x"; then \ ++ for i in $(PHP_TEST_SHARED_SYSTEM_EXTENSIONS)""; do \ ++ dlname=$$i.$(SHLIB_DL_SUFFIX_NAME); \ ++ $(top_srcdir)/build/shtool echo -n -- " -d extension=$(EXTENSION_DIR)/$$dlname"; \ ++ done; \ ++ fi; \ + if test "x$(PHP_MODULES)" != "x"; then \ + for i in $(PHP_MODULES)""; do \ + . $$i; $(top_srcdir)/build/shtool echo -n -- " -d extension=$$dlname"; \ +@@ -107,7 +114,10 @@ + TEST_PHP_EXECUTABLE=$(PHP_EXECUTABLE) \ + TEST_PHP_SRCDIR=$(top_srcdir) \ + CC="$(CC)" \ +- $(PHP_EXECUTABLE) -n -c $(top_builddir)/tmp-php.ini $(PHP_TEST_SETTINGS) $(top_srcdir)/run-tests.php -n -c $(top_builddir)/tmp-php.ini -d extension_dir=$(top_builddir)/modules/ $(PHP_TEST_SHARED_EXTENSIONS) $(TESTS); \ ++ $(PHP_EXECUTABLE) -n -c $(top_builddir)/tmp-php.ini \ ++ -d extension_dir=$(top_builddir)/modules/ -d 'extension=$(EXTENSION_DIR)/pcre.$(SHLIB_DL_SUFFIX_NAME)' \ ++ $(PHP_TEST_SETTINGS) $(top_srcdir)/run-tests.php -n -c $(top_builddir)/tmp-php.ini \ ++ -d extension_dir=$(top_builddir)/modules/ $(PHP_TEST_SHARED_EXTENSIONS) $(RUN_TESTS_SETTINGS) $(TESTS); \ + rm $(top_builddir)/tmp-php.ini; \ + else \ + echo "ERROR: Cannot run tests without CLI sapi."; \ diff --git a/mcrypt-libs.patch b/mcrypt-libs.patch new file mode 100644 index 0000000..2bc029c --- /dev/null +++ b/mcrypt-libs.patch @@ -0,0 +1,19 @@ +--- php-5.3.6/ext/mcrypt/config.m4~ 2010-01-15 23:02:20.000000000 +0200 ++++ php-5.3.6/ext/mcrypt/config.m4 2011-04-09 16:18:07.634572726 +0300 +@@ -36,7 +36,6 @@ + + PHP_CHECK_LIBRARY(mcrypt, mcrypt_module_open, + [ +- PHP_ADD_LIBRARY(ltdl,, MCRYPT_SHARED_LIBADD) + AC_DEFINE(HAVE_LIBMCRYPT,1,[ ]) + ],[ + PHP_CHECK_LIBRARY(mcrypt, mcrypt_module_open, +@@ -48,7 +47,7 @@ + -L$MCRYPT_DIR/$PHP_LIBDIR + ]) + ],[ +- -L$MCRYPT_DIR/$PHP_LIBDIR -lltdl ++ -L$MCRYPT_DIR/$PHP_LIBDIR + ]) + + PHP_ADD_LIBRARY_WITH_PATH(mcrypt, $MCRYPT_DIR/$PHP_LIBDIR, MCRYPT_SHARED_LIBADD) diff --git a/pcre-shared.patch b/pcre-shared.patch new file mode 100644 index 0000000..81b9ecf --- /dev/null +++ b/pcre-shared.patch @@ -0,0 +1,118 @@ +--- php-5.3.1/ext/pcre/php_pcre.h 2009-11-30 20:59:04.046581246 +0200 ++++ php-5.3.1.pcre/ext/pcre/php_pcre.h 2009-11-30 21:38:06.435493243 +0000 +@@ -34,7 +34,12 @@ + #endif + + PHPAPI char *php_pcre_replace(char *regex, int regex_len, char *subject, int subject_len, zval *replace_val, int is_callable_replace, int *result_len, int limit, int *replace_count TSRMLS_DC); ++#if COMPILE_DL_PCRE ++#define pcre_get_compiled_regex pcre_get_compiled_regex_p ++extern PHPAPI pcre* (*pcre_get_compiled_regex)(char *regex, pcre_extra **extra, int *options TSRMLS_DC); ++#else + PHPAPI pcre* pcre_get_compiled_regex(char *regex, pcre_extra **extra, int *options TSRMLS_DC); ++#endif + PHPAPI pcre* pcre_get_compiled_regex_ex(char *regex, pcre_extra **extra, int *preg_options, int *coptions TSRMLS_DC); + + extern zend_module_entry pcre_module_entry; +--- php-5.3.1/ext/pcre/php_pcre.c 2009-11-30 21:10:01.370473754 +0200 ++++ php-5.3.1.pcre/ext/pcre/php_pcre.c 2009-11-30 21:38:01.759684456 +0000 +@@ -27,6 +27,11 @@ + + #if HAVE_PCRE || HAVE_BUNDLED_PCRE + ++#if COMPILE_DL_PCRE ++#undef pcre_get_compiled_regex ++PHPAPI pcre* pcre_get_compiled_regex(char *regex, pcre_extra **extra, int *preg_options TSRMLS_DC); ++#endif ++ + #include "ext/standard/php_string.h" + + #define PREG_PATTERN_ORDER 1 +@@ -153,6 +158,10 @@ + REGISTER_LONG_CONSTANT("PREG_BAD_UTF8_OFFSET_ERROR", PHP_PCRE_BAD_UTF8_OFFSET_ERROR, CONST_CS | CONST_PERSISTENT); + REGISTER_STRING_CONSTANT("PCRE_VERSION", (char *)pcre_version(), CONST_CS | CONST_PERSISTENT); + ++#if COMPILE_DL_PCRE ++ pcre_get_compiled_regex_p = pcre_get_compiled_regex; ++#endif ++ + return SUCCESS; + } + /* }}} */ +@@ -429,6 +438,7 @@ + } + /* }}} */ + ++ + /* {{{ pcre_get_compiled_regex + */ + PHPAPI pcre* pcre_get_compiled_regex(char *regex, pcre_extra **extra, int *preg_options TSRMLS_DC) +--- php-5.3.1/ext/standard/browscap.c 2009-06-06 02:40:49.000000000 +0000 ++++ php-5.3.1.pcre/ext/standard/browscap.c 2009-11-30 21:33:00.775241138 +0000 +@@ -31,6 +31,11 @@ + static zval *current_section; + static char *current_section_name; + ++#if COMPILE_DL_PCRE ++// will be visible in here ++PHPAPI pcre* (*pcre_get_compiled_regex_p)(char *regex, pcre_extra **extra, int *options TSRMLS_DC); ++#endif ++ + #define DEFAULT_SECTION_NAME "Default Browser Capability Settings" + + /* OBJECTS_FIXME: This whole extension needs going through. The use of objects looks pretty broken here */ +--- php-5.3.2/sapi/cli/tests/018.phpt~ 2008-03-17 16:05:39.000000000 +0200 ++++ php-5.3.2/sapi/cli/tests/018.phpt 2010-03-16 20:41:11.341251246 +0200 +@@ -20,8 +20,6 @@ + --EXPECTF-- + [PHP Modules] + %a +-pcre +-%a + + [Zend Modules] + %aDone +--- php-5.3.24/ext/pcre/config0.m4.orig 2013-04-10 09:42:48.000000000 +0200 ++++ php-5.3.24/ext/pcre/config0.m4 2013-04-12 18:54:41.113531049 +0200 +@@ -11,7 +11,7 @@ + + if test "$PHP_PCRE_REGEX" != "yes" && test "$PHP_PCRE_REGEX" != "no"; then + AC_MSG_CHECKING([for PCRE headers location]) +- for i in $PHP_PCRE_REGEX $PHP_PCRE_REGEX/include $PHP_PCRE_REGEX/include/pcre $PHP_PCRE_REGEX/local/include; do ++ for i in $PHP_PCRE_REGEX $PHP_PCRE_REGEX/include $PHP_PCRE_REGEX/include/pcre $PHP_PCRE_REGEX/local/include /usr/include; do + test -f $i/pcre.h && PCRE_INCDIR=$i + done + +@@ -21,7 +21,7 @@ + AC_MSG_RESULT([$PCRE_INCDIR]) + + AC_MSG_CHECKING([for PCRE library location]) +- for j in $PHP_PCRE_REGEX $PHP_PCRE_REGEX/$PHP_LIBDIR; do ++ for j in $PHP_PCRE_REGEX $PHP_PCRE_REGEX/$PHP_LIBDIR /usr/$PHP_LIBDIR; do + test -f $j/libpcre.a || test -f $j/libpcre.$SHLIB_SUFFIX_NAME && PCRE_LIBDIR=$j + done + +@@ -43,12 +43,13 @@ + AC_MSG_ERROR([The PCRE extension requires PCRE library version >= 6.6]) + fi + +- PHP_ADD_LIBRARY_WITH_PATH(pcre, $PCRE_LIBDIR) ++ PHP_ADD_LIBRARY_WITH_PATH(pcre, $PCRE_LIBDIR, PCRE_SHARED_LIBADD) + + AC_DEFINE(HAVE_PCRE, 1, [ ]) + PHP_ADD_INCLUDE($PCRE_INCDIR) +- PHP_NEW_EXTENSION(pcre, php_pcre.c, no) ++ PHP_NEW_EXTENSION(pcre, php_pcre.c, $ext_shared) + PHP_INSTALL_HEADERS([ext/pcre], [php_pcre.h]) ++ EXTRA_LIBS="$EXTRA_LIBS -lpcre" + else + AC_MSG_CHECKING([for PCRE library to use]) + AC_MSG_RESULT([bundled]) +@@ -60,7 +61,7 @@ + pcrelib/pcre_tables.c pcrelib/pcre_valid_utf8.c \ + pcrelib/pcre_version.c pcrelib/pcre_xclass.c" + PHP_PCRE_CFLAGS="-DHAVE_CONFIG_H -I@ext_srcdir@/pcrelib" +- PHP_NEW_EXTENSION(pcre, $pcrelib_sources php_pcre.c, no,,$PHP_PCRE_CFLAGS) ++ PHP_NEW_EXTENSION(pcre, $pcrelib_sources php_pcre.c, $ext_shared,,-I@ext_srcdir@/pcrelib) + PHP_ADD_BUILD_DIR($ext_builddir/pcrelib) + PHP_INSTALL_HEADERS([ext/pcre], [php_pcre.h pcrelib/]) + AC_DEFINE(HAVE_BUNDLED_PCRE, 1, [ ]) diff --git a/pcre-shared.patch.diff b/pcre-shared.patch.diff new file mode 100644 index 0000000..27c6ed0 --- /dev/null +++ b/pcre-shared.patch.diff @@ -0,0 +1,102 @@ +diff --git a/pcre-shared.patch b/pcre-shared.patch +index 39632a0..81b9ecf 100644 +--- a/pcre-shared.patch ++++ b/pcre-shared.patch +@@ -1,48 +1,3 @@ +---- php-5.3.1/ext/pcre/config0.m4 2009-11-27 08:19:08.836025192 +0000 +-+++ php-5.3.1/ext/pcre/config0.m4 2009-11-30 22:09:24.385647500 +0000 +-@@ -11,7 +11,7 @@ +- +- if test "$PHP_PCRE_REGEX" != "yes" && test "$PHP_PCRE_REGEX" != "no"; then +- AC_MSG_CHECKING([for PCRE headers location]) +-- for i in $PHP_PCRE_REGEX $PHP_PCRE_REGEX/include $PHP_PCRE_REGEX/include/pcre $PHP_PCRE_REGEX/local/include; do +-+ for i in $PHP_PCRE_REGEX $PHP_PCRE_REGEX/include $PHP_PCRE_REGEX/include/pcre $PHP_PCRE_REGEX/local/include /usr/include; do +- test -f $i/pcre.h && PCRE_INCDIR=$i +- done +- +-@@ -21,7 +21,7 @@ +- AC_MSG_RESULT([$PCRE_INCDIR]) +- +- AC_MSG_CHECKING([for PCRE library location]) +-- for j in $PHP_PCRE_REGEX $PHP_PCRE_REGEX/$PHP_LIBDIR; do +-+ for j in $PHP_PCRE_REGEX $PHP_PCRE_REGEX/$PHP_LIBDIR /usr/$PHP_LIBDIR; do +- test -f $j/libpcre.a || test -f $j/libpcre.$SHLIB_SUFFIX_NAME && PCRE_LIBDIR=$j +- done +- +-@@ -43,12 +43,13 @@ +- AC_MSG_ERROR([The PCRE extension requires PCRE library version >= 6.6]) +- fi +- +-- PHP_ADD_LIBRARY_WITH_PATH(pcre, $PCRE_LIBDIR) +-+ PHP_ADD_LIBRARY_WITH_PATH(pcre, $PCRE_LIBDIR, PCRE_SHARED_LIBADD) +- +- AC_DEFINE(HAVE_PCRE, 1, [ ]) +- PHP_ADD_INCLUDE($PCRE_INCDIR) +-- PHP_NEW_EXTENSION(pcre, php_pcre.c, no) +-+ PHP_NEW_EXTENSION(pcre, php_pcre.c, $ext_shared) +- PHP_INSTALL_HEADERS([ext/pcre], [php_pcre.h]) +-+ EXTRA_LIBS="$EXTRA_LIBS -lpcre" +- else +- AC_MSG_CHECKING([for PCRE library to use]) +- AC_MSG_RESULT([bundled]) +-@@ -59,7 +60,7 @@ +- pcrelib/pcre_ord2utf8.c pcrelib/pcre_refcount.c pcrelib/pcre_study.c \ +- pcrelib/pcre_tables.c pcrelib/pcre_try_flipped.c pcrelib/pcre_valid_utf8.c \ +- pcrelib/pcre_version.c pcrelib/pcre_xclass.c" +-- PHP_NEW_EXTENSION(pcre, $pcrelib_sources php_pcre.c, no,,-I@ext_srcdir@/pcrelib) +-+ PHP_NEW_EXTENSION(pcre, $pcrelib_sources php_pcre.c, $ext_shared,,-I@ext_srcdir@/pcrelib) +- PHP_ADD_BUILD_DIR($ext_builddir/pcrelib) +- PHP_INSTALL_HEADERS([ext/pcre], [php_pcre.h pcrelib/]) +- AC_DEFINE(HAVE_BUNDLED_PCRE, 1, [ ]) + --- php-5.3.1/ext/pcre/php_pcre.h 2009-11-30 20:59:04.046581246 +0200 + +++ php-5.3.1.pcre/ext/pcre/php_pcre.h 2009-11-30 21:38:06.435493243 +0000 + @@ -34,7 +34,12 @@ +@@ -116,3 +71,48 @@ + + [Zend Modules] + %aDone ++--- php-5.3.24/ext/pcre/config0.m4.orig 2013-04-10 09:42:48.000000000 +0200 +++++ php-5.3.24/ext/pcre/config0.m4 2013-04-12 18:54:41.113531049 +0200 ++@@ -11,7 +11,7 @@ ++ ++ if test "$PHP_PCRE_REGEX" != "yes" && test "$PHP_PCRE_REGEX" != "no"; then ++ AC_MSG_CHECKING([for PCRE headers location]) ++- for i in $PHP_PCRE_REGEX $PHP_PCRE_REGEX/include $PHP_PCRE_REGEX/include/pcre $PHP_PCRE_REGEX/local/include; do +++ for i in $PHP_PCRE_REGEX $PHP_PCRE_REGEX/include $PHP_PCRE_REGEX/include/pcre $PHP_PCRE_REGEX/local/include /usr/include; do ++ test -f $i/pcre.h && PCRE_INCDIR=$i ++ done ++ ++@@ -21,7 +21,7 @@ ++ AC_MSG_RESULT([$PCRE_INCDIR]) ++ ++ AC_MSG_CHECKING([for PCRE library location]) ++- for j in $PHP_PCRE_REGEX $PHP_PCRE_REGEX/$PHP_LIBDIR; do +++ for j in $PHP_PCRE_REGEX $PHP_PCRE_REGEX/$PHP_LIBDIR /usr/$PHP_LIBDIR; do ++ test -f $j/libpcre.a || test -f $j/libpcre.$SHLIB_SUFFIX_NAME && PCRE_LIBDIR=$j ++ done ++ ++@@ -43,12 +43,13 @@ ++ AC_MSG_ERROR([The PCRE extension requires PCRE library version >= 6.6]) ++ fi ++ ++- PHP_ADD_LIBRARY_WITH_PATH(pcre, $PCRE_LIBDIR) +++ PHP_ADD_LIBRARY_WITH_PATH(pcre, $PCRE_LIBDIR, PCRE_SHARED_LIBADD) ++ ++ AC_DEFINE(HAVE_PCRE, 1, [ ]) ++ PHP_ADD_INCLUDE($PCRE_INCDIR) ++- PHP_NEW_EXTENSION(pcre, php_pcre.c, no) +++ PHP_NEW_EXTENSION(pcre, php_pcre.c, $ext_shared) ++ PHP_INSTALL_HEADERS([ext/pcre], [php_pcre.h]) +++ EXTRA_LIBS="$EXTRA_LIBS -lpcre" ++ else ++ AC_MSG_CHECKING([for PCRE library to use]) ++ AC_MSG_RESULT([bundled]) ++@@ -60,7 +61,7 @@ ++ pcrelib/pcre_tables.c pcrelib/pcre_valid_utf8.c \ ++ pcrelib/pcre_version.c pcrelib/pcre_xclass.c" ++ PHP_PCRE_CFLAGS="-DHAVE_CONFIG_H -I@ext_srcdir@/pcrelib" ++- PHP_NEW_EXTENSION(pcre, $pcrelib_sources php_pcre.c, no,,$PHP_PCRE_CFLAGS) +++ PHP_NEW_EXTENSION(pcre, $pcrelib_sources php_pcre.c, $ext_shared,,-I@ext_srcdir@/pcrelib) ++ PHP_ADD_BUILD_DIR($ext_builddir/pcrelib) ++ PHP_INSTALL_HEADERS([ext/pcre], [php_pcre.h pcrelib/]) ++ AC_DEFINE(HAVE_BUNDLED_PCRE, 1, [ ]) diff --git a/php-apache.ini b/php-apache.ini new file mode 100644 index 0000000..3b335f6 --- /dev/null +++ b/php-apache.ini @@ -0,0 +1,15 @@ +; php-apache.ini - configuration used only for apache SAPI +; +; Please note that, unlikely in original php distributions, this file +; is read AFTER (not instead of) reading global /etc/php/php.ini. +; +; It allows you to control global settings for all SAPIs in one place +; and override some settings in SAPI-specific files without need of +; copying whole large php.ini. + +[Session] +session.save_path = /var/run/php + ; argument passed to save_handler + ; in the case of files, this is the + ; path where data files are stored + diff --git a/php-both-apxs.patch b/php-both-apxs.patch new file mode 100644 index 0000000..8e7bd89 --- /dev/null +++ b/php-both-apxs.patch @@ -0,0 +1,15 @@ +--- php-5.2.4/Makefile.global~ 2007-08-31 19:35:54.000000000 +0300 ++++ php-5.2.4/Makefile.global 2007-08-31 19:40:18.287528480 +0300 +@@ -21,6 +21,12 @@ + $(LIBTOOL) --mode=link $(CC) -rpath $(phptempdir) $(EXTRA_LDFLAGS) $(LDFLAGS) $(PHP_RPATHS) $(phptempdir)/libphp_common.la $(PHP_SAPI_OBJS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -o $@ + -@$(LIBTOOL) --silent --mode=install cp $@ $(phptempdir)/$@ >/dev/null 2>&1 + ++$(LIBTOOL_SAPI): libphp_common.la $(PHP_SAPI_OBJS) ++ $(LIBTOOL) --mode=link $(CC) -rpath $(phptempdir) $(EXTRA_LDFLAGS) $(LDFLAGS) $(PHP_RPATHS) $(phptempdir)/libphp_common.la $(PHP_SAPI_OBJS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -o $@ ++ -@$(LIBTOOL) --silent --mode=install cp $@ $(phptempdir)/$@ >/dev/null 2>&1 ++ ++libtool-sapi: $(LIBTOOL_SAPI) ++ + libs/libphp$(PHP_MAJOR_VERSION).bundle: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) + $(CC) $(MH_BUNDLE_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) $(LDFLAGS) $(EXTRA_LDFLAGS) $(PHP_GLOBAL_OBJS:.lo=.o) $(PHP_SAPI_OBJS:.lo=.o) $(PHP_FRAMEWORKS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -o $@ && cp $@ libs/libphp$(PHP_MAJOR_VERSION).so + diff --git a/php-branch.sh b/php-branch.sh new file mode 100644 index 0000000..d9f5fbd --- /dev/null +++ b/php-branch.sh @@ -0,0 +1,25 @@ +#!/bin/sh +set -e +svn=http://svn.php.net/repository/php/php-src +tag=php_5_3_2 +branch=PHP_5_3 +out=php-branch.diff + +d=$- +filter() { + set -$d + # remove revno's for smaller diffs + sed -e 's,^\([-+]\{3\} .*\)\t(revision [0-9]\+)$,\1,' +} + +old=$svn/tags/$tag +new=$svn/branches/$branch +echo >&2 "Running diff: $old -> $new" +LC_ALL=C svn diff --old=$old --new=$new | filter > $out.tmp + +if cmp -s $out{,.tmp}; then + echo >&2 "No new diffs..." + rm -f $out.tmp + exit 0 +fi +mv -f $out{.tmp,} diff --git a/php-build_modules.patch b/php-build_modules.patch new file mode 100644 index 0000000..cf222ec --- /dev/null +++ b/php-build_modules.patch @@ -0,0 +1,9 @@ +diff -Naur php-4.1.2.orig/ext/skeleton/create_stubs php-4.1.2/ext/skeleton/create_stubs +--- php-4.1.2.orig/ext/skeleton/create_stubs Fri May 31 11:50:08 2002 ++++ php-4.1.2/ext/skeleton/create_stubs Fri May 31 11:52:00 2002 +@@ -1,4 +1,4 @@ +-#!/usr/bin/awk -f ++#!/bin/awk -f + + function gobble(s, x) + { diff --git a/php-builddir.patch b/php-builddir.patch new file mode 100644 index 0000000..783dc2b --- /dev/null +++ b/php-builddir.patch @@ -0,0 +1,24 @@ +diff -urbB php-5.0.5.org/scripts/Makefile.frag php-5.0.5/scripts/Makefile.frag +--- php-5.0.5.org/scripts/Makefile.frag 2005-09-10 21:29:04.884122000 +0200 ++++ php-5.0.5/scripts/Makefile.frag 2005-09-10 21:30:09.333324848 +0200 +@@ -4,7 +4,7 @@ + # + + phpincludedir = $(includedir)/php +-phpbuilddir = $(libdir)/build ++phpbuilddir = $(libdir)/php/build + + BUILD_FILES = \ + scripts/phpize.m4 \ +diff -urbB php-5.0.5.org/scripts/phpize.in php-5.0.5/scripts/phpize.in +--- php-5.0.5.org/scripts/phpize.in 2005-06-15 19:19:41.000000000 +0200 ++++ php-5.0.5/scripts/phpize.in 2005-09-10 21:51:45.523274024 +0200 +@@ -3,7 +3,7 @@ + # Variable declaration + prefix='@prefix@' + exec_prefix="`eval echo @exec_prefix@`" +-phpdir="`eval echo @libdir@`/build" ++phpdir="`eval echo @libdir@`/php/build" + includedir="`eval echo @includedir@`/php" + builddir="`pwd`" + diff --git a/php-cgi-fcgi.ini b/php-cgi-fcgi.ini new file mode 100644 index 0000000..809c7d3 --- /dev/null +++ b/php-cgi-fcgi.ini @@ -0,0 +1,50 @@ +; php-cgi-fcgi.ini - configuration used only for cgi-fcgi SAPI +; +; Please note that, unlikely in original php distributions, this file +; is read AFTER (not instead of) reading global /etc/php/php.ini. +; +; It allows you to control global settings for all SAPIs in one place +; and override some settings in SAPI-specific files without need of +; copying whole large php.ini. + +[PHP] +; Disable logging through FastCGI connection +; See http://bugs.php.net/bug.php?id=28074 +; fastcgi.logging = 0 + +; cgi.force_redirect is necessary to provide security running PHP as a CGI under +; most web servers. Left undefined, PHP turns this on by default. You can +; turn it off here AT YOUR OWN RISK +; **You CAN safely turn this off for IIS, in fact, you MUST.** +; cgi.force_redirect = 1 + +; if cgi.nph is enabled it will force cgi to always sent Status: 200 with +; every request. +; cgi.nph = 1 + +; if cgi.force_redirect is turned on, and you are not running under Apache or Netscape +; (iPlanet) web servers, you MAY need to set an environment variable name that PHP +; will look for to know it is OK to continue execution. Setting this variable MAY +; cause security issues, KNOW WHAT YOU ARE DOING FIRST. +; cgi.redirect_status_env = ; + +; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's +; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok +; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting +; this to 1 will cause PHP CGI to fix it's paths to conform to the spec. A setting +; of zero causes PHP to behave as before. Default is 1. You should fix your scripts +; to use SCRIPT_FILENAME rather than PATH_TRANSLATED. +cgi.fix_pathinfo=1 + +; cgi.rfc2616_headers configuration option tells PHP what type of headers to +; use when sending HTTP response code. If it's set 0 PHP sends Status: header that +; is supported by Apache. When this option is set to 1 PHP will send +; RFC2616 compliant header. +; Default is zero. +;cgi.rfc2616_headers = 0 + +[Session] +session.save_path = /tmp ; argument passed to save_handler + ; in the case of files, this is the + ; path where data files are stored + diff --git a/php-cli.ini b/php-cli.ini new file mode 100644 index 0000000..65e02e5 --- /dev/null +++ b/php-cli.ini @@ -0,0 +1,27 @@ +; php-cli.ini - configuration used only for cli SAPI +; +; Please note that, unlikely in original php distributions, this file +; is read AFTER (not instead of) reading global /etc/php/php.ini. +; +; It allows you to control global settings for all SAPIs in one place +; and override some settings in SAPI-specific files without need of +; copying whole large php.ini. + +[PHP] +; This combination (display_errors=off; log_errors=on; error_log ="") allows +; fatal errors go to STDERR only. We set these separately here, that we won't +; be affected by global php.ini +display_errors = Off +log_errors = On + +; Disable error logging, in case it was enabled in global php.ini +error_log = "" + +; Whether or not to enable the dl() function. +; http://php.net/enable-dl +enable_dl = On + +[Session] +; argument passed to save_handler in the case of files, this is the +; path where data files are stored. +session.save_path = /tmp diff --git a/php-config-dir.patch b/php-config-dir.patch new file mode 100644 index 0000000..b6abad5 --- /dev/null +++ b/php-config-dir.patch @@ -0,0 +1,27 @@ +--- php-5.2.0/scripts/php-config.in 2006-12-14 01:11:33.348180526 +0200 ++++ php-5.2.4/scripts/php-config.in 2007-08-31 19:43:04.061307670 +0300 +@@ -2,6 +2,7 @@ + + prefix="@prefix@" + exec_prefix="@exec_prefix@" ++sysconfdir='@sysconfdir@' + version="@PHP_VERSION@" + version_id="@PHP_VERSION_ID@" + includedir="@includedir@/php" +@@ -53,6 +54,8 @@ + echo $extension_dir;; + --include-dir) + echo $include_dir;; ++--sysconfdir) ++ echo $sysconfdir;; + --php-binary) + echo $php_binary;; + --php-sapis) +@@ -72,6 +75,7 @@ + --ldflags [$ldflags] + --libs [$libs] + --extension-dir [$extension_dir] ++ --sysconfdir [$sysconfdir] + --include-dir [$include_dir] + --php-binary [$php_binary] + --php-sapis [$php_sapis] diff --git a/php-config-file-scan-dir.patch b/php-config-file-scan-dir.patch new file mode 100644 index 0000000..12d15aa --- /dev/null +++ b/php-config-file-scan-dir.patch @@ -0,0 +1,157 @@ +--- php-src/main/php_ini.c 2009/05/18 21:28:42 1.173 ++++ php-src/main/php_ini.c 2009/06/27 15:22:06 1.174 +@@ -349,7 +349,8 @@ + char *open_basedir; + int free_ini_search_path = 0; + zend_file_handle fh; +- ++ static const char paths_separator[] = { ZEND_PATHS_SEPARATOR, 0 }; ++ + if (zend_hash_init(&configuration_hash, 0, NULL, (dtor_func_t) config_zval_dtor, 1) == FAILURE) { + return FAILURE; + } +@@ -372,7 +373,6 @@ + char *default_location; + char *env_location; + char *binary_location; +- static const char paths_separator[] = { ZEND_PATHS_SEPARATOR, 0 }; + #ifdef PHP_WIN32 + char *reg_location; + char phprc_path[MAXPATHLEN]; +@@ -608,72 +608,86 @@ + + /* Scan and parse any .ini files found in scan path if path not empty. */ + if (!sapi_module.php_ini_ignore && php_ini_scanned_path_len) { +- struct dirent **namelist; + int ndir, i; + struct stat sb; + char ini_file[MAXPATHLEN]; +- char *p; ++ char *p, *last, *path_copy, *ini_path = NULL; + zend_file_handle fh2; + zend_llist scanned_ini_list; + zend_llist_element *element; + int l, total_l = 0; + +- if ((ndir = php_scandir(php_ini_scanned_path, &namelist, 0, php_alphasort)) > 0) { +- zend_llist_init(&scanned_ini_list, sizeof(char *), (llist_dtor_func_t) free_estring, 1); +- memset(&fh2, 0, sizeof(fh2)); +- +- for (i = 0; i < ndir; i++) { +- +- /* check for any file with .ini extension */ +- if (!(p = strrchr(namelist[i]->d_name, '.')) || (p && strcmp(p, ".ini"))) { +- free(namelist[i]); +- continue; +- } +- /* Reset active ini section */ +- RESET_ACTIVE_INI_HASH(); +- +- if (IS_SLASH(php_ini_scanned_path[php_ini_scanned_path_len - 1])) { +- snprintf(ini_file, MAXPATHLEN, "%s%s", php_ini_scanned_path, namelist[i]->d_name); +- } else { +- snprintf(ini_file, MAXPATHLEN, "%s%c%s", php_ini_scanned_path, DEFAULT_SLASH, namelist[i]->d_name); +- } +- if (VCWD_STAT(ini_file, &sb) == 0) { +- if (S_ISREG(sb.st_mode)) { +- if ((fh2.handle.fp = VCWD_FOPEN(ini_file, "r"))) { +- fh2.filename = ini_file; +- fh2.type = ZEND_HANDLE_FP; +- +- if (zend_parse_ini_file(&fh2, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash TSRMLS_CC) == SUCCESS) { +- /* Here, add it to the list of ini files read */ +- l = strlen(ini_file); +- total_l += l + 2; +- p = estrndup(ini_file, l); +- zend_llist_add_element(&scanned_ini_list, &p); ++ /* List of found ini files */ ++ zend_llist_init(&scanned_ini_list, sizeof(char *), (llist_dtor_func_t) free_estring, 1); ++ ++ /* Split by paths_separator and load ini-files from all paths */ ++ path_copy = estrdup(php_ini_scanned_path); ++ ini_path = php_strtok_r(path_copy, paths_separator, &last); ++ ++ while (ini_path != NULL) { ++ struct dirent **namelist; ++ int ini_path_len = strlen(ini_path); ++ ++ if ((ndir = php_scandir(ini_path, &namelist, 0, php_alphasort)) > 0) { ++ memset(&fh2, 0, sizeof(fh2)); ++ ++ for (i = 0; i < ndir; i++) { ++ /* check for any file with .ini extension */ ++ if (!(p = strrchr(namelist[i]->d_name, '.')) || (p && strcmp(p, ".ini"))) { ++ free(namelist[i]); ++ continue; ++ } ++ /* Reset active ini section */ ++ RESET_ACTIVE_INI_HASH(); ++ ++ if (IS_SLASH(ini_path[ini_path_len - 1])) { ++ snprintf(ini_file, MAXPATHLEN, "%s%s", ini_path, namelist[i]->d_name); ++ } else { ++ snprintf(ini_file, MAXPATHLEN, "%s%c%s", ini_path, DEFAULT_SLASH, namelist[i]->d_name); ++ } ++ if (VCWD_STAT(ini_file, &sb) == 0) { ++ if (S_ISREG(sb.st_mode)) { ++ if ((fh2.handle.fp = VCWD_FOPEN(ini_file, "r"))) { ++ fh2.filename = ini_file; ++ fh2.type = ZEND_HANDLE_FP; ++ ++ /* Reset active ini section */ ++ RESET_ACTIVE_INI_HASH(); ++ ++ if (zend_parse_ini_file(&fh2, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash TSRMLS_CC) == SUCCESS) { ++ /* Here, add it to the list of ini files read */ ++ l = strlen(ini_file); ++ total_l += l + 2; ++ p = estrndup(ini_file, l); ++ zend_llist_add_element(&scanned_ini_list, &p); ++ } + } + } + } ++ free(namelist[i]); + } +- free(namelist[i]); ++ free(namelist); + } +- free(namelist); +- +- if (total_l) { +- int php_ini_scanned_files_len = (php_ini_scanned_files) ? strlen(php_ini_scanned_files) + 1 : 0; +- php_ini_scanned_files = (char *) realloc(php_ini_scanned_files, php_ini_scanned_files_len + total_l + 1); +- if (!php_ini_scanned_files_len) { +- *php_ini_scanned_files = '\0'; +- } +- total_l += php_ini_scanned_files_len; +- for (element = scanned_ini_list.head; element; element = element->next) { +- if (php_ini_scanned_files_len) { +- strlcat(php_ini_scanned_files, ",\n", total_l); +- } +- strlcat(php_ini_scanned_files, *(char **)element->data, total_l); +- strlcat(php_ini_scanned_files, element->next ? ",\n" : "\n", total_l); ++ ini_path = php_strtok_r(NULL, paths_separator, &last); ++ } ++ ++ if (total_l) { ++ int php_ini_scanned_files_len = (php_ini_scanned_files) ? strlen(php_ini_scanned_files) + 1 : 0; ++ php_ini_scanned_files = (char *) realloc(php_ini_scanned_files, php_ini_scanned_files_len + total_l + 1); ++ if (!php_ini_scanned_files_len) { ++ *php_ini_scanned_files = '\0'; ++ } ++ total_l += php_ini_scanned_files_len; ++ for (element = scanned_ini_list.head; element; element = element->next) { ++ if (php_ini_scanned_files_len) { ++ strlcat(php_ini_scanned_files, ",\n", total_l); + } ++ strlcat(php_ini_scanned_files, *(char **)element->data, total_l); ++ strlcat(php_ini_scanned_files, element->next ? ",\n" : "\n", total_l); + } +- zend_llist_destroy(&scanned_ini_list); + } ++ efree(path_copy); ++ zend_llist_destroy(&scanned_ini_list); + } else { + /* Make sure an empty php_ini_scanned_path ends up as NULL */ + php_ini_scanned_path = NULL; diff --git a/php-db.patch b/php-db.patch new file mode 100644 index 0000000..07032ec --- /dev/null +++ b/php-db.patch @@ -0,0 +1,26 @@ +--- php-5.3.16/ext/dba/config.m4.orig 2012-09-06 11:15:09.743002303 +0200 ++++ php-5.3.16/ext/dba/config.m4 2012-09-06 11:28:12.192974701 +0200 +@@ -287,6 +287,14 @@ + THIS_PREFIX=$i + THIS_INCLUDE=$i/db4/db.h + break ++ elif test -f "$i/include/db5.3/db.h"; then ++ THIS_PREFIX=$i ++ THIS_INCLUDE=$i/include/db5.3/db.h ++ break ++ elif test -f "$i/include/db5.2/db.h"; then ++ THIS_PREFIX=$i ++ THIS_INCLUDE=$i/include/db5.2/db.h ++ break + elif test -f "$i/include/db5.1/db.h"; then + THIS_PREFIX=$i + THIS_INCLUDE=$i/include/db5.1/db.h +@@ -329,7 +337,7 @@ + break + fi + done +- PHP_DBA_DB_CHECK(4, db-5.1 db-5.0 db-4.8 db-4.7 db-4.6 db-4.5 db-4.4 db-4.3 db-4.2 db-4.1 db-4.0 db-4 db4 db, [(void)db_create((DB**)0, (DB_ENV*)0, 0)]) ++ PHP_DBA_DB_CHECK(4, db-5.3 db-5.2 db-5.1 db-5.0 db-4.8 db-4.7 db-4.6 db-4.5 db-4.4 db-4.3 db-4.2 db-4.1 db-4.0 db-4 db4 db, [(void)db_create((DB**)0, (DB_ENV*)0, 0)]) + fi + PHP_DBA_STD_RESULT(db4,Berkeley DB4) + diff --git a/php-dba-link.patch b/php-dba-link.patch new file mode 100644 index 0000000..125e9dc --- /dev/null +++ b/php-dba-link.patch @@ -0,0 +1,11 @@ +--- php-5.2.3/ext/dba/config.m4~ 2007-06-01 10:47:16.524748906 +0300 ++++ php-5.2.3/ext/dba/config.m4 2007-06-01 10:51:16.450167741 +0300 +@@ -186,6 +186,8 @@ + #endif + ],[ + THIS_LIBS=$LIB ++ LDFLAGS=$old_LDFLAGS ++ LIBS=$old_LIBS + lib_found=1 + ]) + ]) diff --git a/php-fcgi-error_log-no-newlines.patch b/php-fcgi-error_log-no-newlines.patch new file mode 100644 index 0000000..e35648e --- /dev/null +++ b/php-fcgi-error_log-no-newlines.patch @@ -0,0 +1,16 @@ +--- ./sapi/cgi/cgi_main.c~ 2007-08-09 02:51:57.000000000 +0300 ++++ ./sapi/cgi/cgi_main.c 2007-09-05 20:54:19.390089070 +0300 +@@ -558,12 +558,7 @@ + request = (fcgi_request*) SG(server_context); + if (request) { + int len = strlen(message); +- char *buf = malloc(len+2); +- +- memcpy(buf, message, len); +- memcpy(buf + len, "\n", sizeof("\n")); +- fcgi_write(request, FCGI_STDERR, buf, len+1); +- free(buf); ++ fcgi_write(request, FCGI_STDERR, message, len); + } else { + fprintf(stderr, "%s\n", message); + } diff --git a/php-fcgi-graceful.patch b/php-fcgi-graceful.patch new file mode 100644 index 0000000..6cf0d2c --- /dev/null +++ b/php-fcgi-graceful.patch @@ -0,0 +1,77 @@ +Related links: + +http://bugs.php.net/bug.php?id=43224 this patch + +http://bugs.php.net/bug.php?id=41593 +http://bugs.php.net/bug.php?id=36158 +http://php-fpm.anight.org/ + +test script too: +\n"; +$i = 0; +while ($i < 35) { + echo (++$i), "
\n"; + flush(); + sleep(1); +} +echo "end!
\n"; +?> + +--- php5.3-200711090930/sapi/cgi/cgi_main.c 2007-11-01 13:32:38.000000000 +0200 ++++ php5.3-200711090930-graceful/sapi/cgi/cgi_main.c 2007-11-09 13:34:22.974559020 +0200 +@@ -101,6 +101,9 @@ + */ + static int parent = 1; + ++/* Socket we are listening on incoming connections */ ++static int fcgi_fd = 0; ++ + /** + * Process group + */ +@@ -1221,6 +1224,21 @@ + exit(0); + } + ++/** ++ * Graceful shutdown. Close listening sockets. ++ */ ++void fastcgi_graceful_shutdown(int signal) ++{ ++#ifdef DEBUG_FASTCGI ++ fprintf(stderr, "FastCGI graceful shutdown, pid %d\n", getpid()); ++#endif ++ ++ /* Close the listening socket so new processes can reuse the same port */ ++ closesocket(fcgi_fd); ++ fcgi_fd = 0; ++} ++ ++ + PHP_INI_BEGIN() + STD_PHP_INI_ENTRY("cgi.rfc2616_headers", "0", PHP_INI_ALL, OnUpdateBool, rfc2616_headers, php_cgi_globals_struct, php_cgi_globals) + STD_PHP_INI_ENTRY("cgi.nph", "0", PHP_INI_ALL, OnUpdateBool, nph, php_cgi_globals_struct, php_cgi_globals) +@@ -1328,7 +1346,6 @@ + int requests = 0; + int fastcgi = fcgi_is_fastcgi(); + char *bindpath = NULL; +- int fcgi_fd = 0; + fcgi_request request; + int repeats = 1; + int benchmark = 0; +@@ -1579,9 +1596,13 @@ + parent = 0; + + /* don't catch our signals */ +- sigaction(SIGTERM, &old_term, 0); + sigaction(SIGQUIT, &old_quit, 0); + sigaction(SIGINT, &old_int, 0); ++ ++ /* call graceful shutdown handler for SIGTERM */ ++ act.sa_flags = 0; ++ act.sa_handler = fastcgi_graceful_shutdown; ++ sigaction(SIGTERM, &act, &old_term); + break; + case -1: + perror("php (pre-forking)"); diff --git a/php-filter-shared.patch b/php-filter-shared.patch new file mode 100644 index 0000000..3983c3f --- /dev/null +++ b/php-filter-shared.patch @@ -0,0 +1,14 @@ +--- php-5.2.0/ext/filter/config.m4~ 2006-01-14 17:04:12.000000000 +0200 ++++ php-5.2.0/ext/filter/config.m4 2006-11-20 00:06:09.272529853 +0200 +@@ -10,10 +10,7 @@ + if test "$PHP_FILTER" != "no"; then + + dnl Check if configure is the PHP core configure +- if test -n "$PHP_VERSION"; then +- dnl This extension can not be build as shared when in PHP core +- ext_shared=no +- else ++ if test -z "$PHP_VERSION"; then + dnl This is PECL build, check if bundled PCRE library is used + old_CPPFLAGS=$CPPFLAGS + CPPFLAGS=$INCLUDES diff --git a/php-fpm-config.patch b/php-fpm-config.patch new file mode 100644 index 0000000..19aa0a5 --- /dev/null +++ b/php-fpm-config.patch @@ -0,0 +1,115 @@ +--- php-5.3.17/sapi/fpm/php-fpm.conf.in 2012-10-12 12:35:47.601602945 +0300 ++++ php-5.3.18/sapi/fpm/php-fpm.conf.in 2012-11-28 15:31:00.486871136 +0200 +@@ -1,3 +1,4 @@ ++; vim:ft=dosini + ;;;;;;;;;;;;;;;;;;;;; + ; FPM Configuration ; + ;;;;;;;;;;;;;;;;;;;;; +@@ -12,7 +13,7 @@ + ; Relative path can also be used. They will be prefixed by: + ; - the global prefix if it's been set (-p arguement) + ; - @prefix@ otherwise +-;include=etc/fpm.d/*.conf ++;include=/etc/php/fpm.d/*.conf + + ;;;;;;;;;;;;;;;;;; + ; Global Options ; +@@ -22,14 +23,14 @@ + ; Pid file + ; Note: the default prefix is @EXPANDED_LOCALSTATEDIR@ + ; Default Value: none +-;pid = run/php-fpm.pid ++pid = /var/run/@processname@.pid + + ; Error log file + ; If it's set to "syslog", log is sent to syslogd instead of being written + ; in a local file. + ; Note: the default prefix is @EXPANDED_LOCALSTATEDIR@ + ; Default Value: log/php-fpm.log +-;error_log = log/php-fpm.log ++error_log = /var/log/php/@processname@.log + + ; syslog_facility is used to specify what type of program is logging the + ; message. This lets syslogd specify that messages from different facilities +@@ -148,7 +149,7 @@ + ; specific port; + ; '/path/to/unix/socket' - to listen on a unix socket. + ; Note: This value is mandatory. +-listen = 127.0.0.1:9000 ++listen = /var/run/php/@processname@.sock + + ; Set listen(2) backlog. A value of '-1' means unlimited. + ; Default Value: 128 (-1 on FreeBSD and OpenBSD) +@@ -161,7 +162,7 @@ + ; must be separated by a comma. If this value is left blank, connections will be + ; accepted from any ip address. + ; Default Value: any +-;listen.allowed_clients = 127.0.0.1 ++listen.allowed_clients = 127.0.0.1 + + ; Choose how the process manager will control the number of child processes. + ; Possible Values: +@@ -208,12 +209,12 @@ + ; The desired minimum number of idle server processes. + ; Note: Used only when pm is set to 'dynamic' + ; Note: Mandatory when pm is set to 'dynamic' +-pm.min_spare_servers = 1 ++pm.min_spare_servers = 2 + + ; The desired maximum number of idle server processes. + ; Note: Used only when pm is set to 'dynamic' + ; Note: Mandatory when pm is set to 'dynamic' +-pm.max_spare_servers = 3 ++pm.max_spare_servers = 5 + + ; The number of seconds after which an idle process will be killed. + ; Note: Used only when pm is set to 'ondemand' +@@ -323,7 +324,7 @@ + ; anything, but it may not be a good idea to use the .php extension or it + ; may conflict with a real PHP file. + ; Default Value: not set +-;pm.status_path = /status ++;pm.status_path = /fpm-status + + ; The ping URI to call the monitoring page of FPM. If this value is not set, no + ; URI will be recognized as a ping page. This could be used to test from outside +@@ -449,7 +450,7 @@ + ; Note: on highloaded environement, this can cause some delay in the page + ; process time (several ms). + ; Default Value: no +-;catch_workers_output = yes ++catch_workers_output = yes + + ; Limits the extensions of the main script FPM will allow to parse. This can + ; prevent configuration mistakes on the web server side. You should only limit +@@ -463,7 +464,7 @@ + ; the current environment. + ; Default Value: clean env + ;env[HOSTNAME] = $HOSTNAME +-;env[PATH] = /usr/local/bin:/usr/bin:/bin ++env[PATH] = $PATH + ;env[TMP] = /tmp + ;env[TMPDIR] = /tmp + ;env[TEMP] = /tmp +--- php-5.3.9/sapi/fpm/status.html.in~ 2011-10-08 23:43:12.000000000 +0300 ++++ php-5.3.9/sapi/fpm/status.html.in 2012-01-12 02:19:09.573191879 +0200 +@@ -96,7 +96,7 @@ + var sort_index; + var sort_order; + +- doc_url.value = location.protocol + '//' + location.host + "/status?json&full"; ++ doc_url.value = location.protocol + '//' + location.host + "/fpm-status?json&full"; + + ths = document.getElementsByTagName("th"); + for (var i=0; i /dev/null + endscript +} diff --git a/php-fpm.patch b/php-fpm.patch new file mode 100644 index 0000000..aaa3682 --- /dev/null +++ b/php-fpm.patch @@ -0,0 +1,10539 @@ +diff -Naur php-src-vanilla/sapi/fpm/ac/fpm_build.m4 php-src/sapi/fpm/ac/fpm_build.m4 +--- php-src-vanilla/sapi/fpm/ac/fpm_build.m4 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/ac/fpm_build.m4 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,47 @@ ++ ++AC_DEFUN([AC_FPM_BUILD_SAPI], ++[ ++ PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/sapi/fpm/ac/Makefile.frag,$abs_srcdir/sapi/fpm,sapi/fpm) ++ ++ SAPI_FPM_PATH=sapi/fpm/$php_fpm_bin ++ PHP_SUBST(SAPI_FPM_PATH) ++ ++ mkdir -p sapi/fpm/cgi ++ PHP_FPM_SAPI_FILES=`cd $abs_srcdir/sapi/fpm && find cgi/ \( -name *.c \) -exec printf "{} " \;` ++ # PHP_FPM_SAPI_FILES="cgi/cgi_main.c cgi/fastcgi.c" ++ ++ mkdir -p sapi/fpm/fpm ++ PHP_FPM_CORE_FILES=`cd $abs_srcdir/sapi/fpm && find fpm/ \( -name *.c -not -name fpm_trace*.c \) -exec printf "{} " \;` ++ # PHP_FPM_CORE_FILES="fpm/fpm_process_ctl.c fpm/fpm_signals.c fpm/fpm_shm.c fpm/fpm.c fpm/fpm_worker_pool.c fpm/fpm_clock.c fpm/fpm_env.c fpm/fpm_shm_slots.c fpm/fpm_children.c fpm/fpm_events.c fpm/fpm_php.c fpm/fpm_unix.c fpm/fpm_request.c fpm/fpm_sockets.c fpm/fpm_php_trace.c fpm/zlog.c fpm/fpm_cleanup.c fpm/fpm_conf.c fpm/xml_config.c fpm/fpm_stdio.c" ++ ++ if test "$fpm_trace_type" ; then ++ PHP_FPM_TRACE_FILES=`cd $abs_srcdir/sapi/fpm && find fpm/ \( -name fpm_trace.c -or -name fpm_trace_$fpm_trace_type.c \) -exec printf "{} " \;` ++ fi ++ ++ PHP_FPM_CFLAGS="$LIBEVENT_CFLAGS -I$abs_srcdir/sapi/fpm" ++ ++ SAPI_EXTRA_LIBS="$LIBEVENT_LIBS" ++ PHP_SUBST(SAPI_EXTRA_LIBS) ++ ++ dnl Set install target and select SAPI ++ INSTALL_IT=":" ++ ++ PHP_SELECT_SAPI(fpm, program, $PHP_FPM_SAPI_FILES $PHP_FPM_CORE_FILES $PHP_FPM_TRACE_FILES, $PHP_FPM_CFLAGS, '$(SAPI_FPM_PATH)') ++ ++ case $host_alias in ++ *aix*) ++ BUILD_FPM="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(SAPI_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)" ++ ;; ++ *darwin*) ++ BUILD_FPM="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_SAPI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(SAPI_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)" ++ ;; ++ *) ++ BUILD_FPM="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(SAPI_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)" ++ ;; ++ esac ++ ++ ENDIF=endif ++ PHP_SUBST(ENDIF) ++ PHP_SUBST(BUILD_FPM) ++ ++]) +diff -Naur php-src-vanilla/sapi/fpm/ac/fpm_checks.m4 php-src/sapi/fpm/ac/fpm_checks.m4 +--- php-src-vanilla/sapi/fpm/ac/fpm_checks.m4 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/ac/fpm_checks.m4 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,299 @@ ++dnl ++dnl $Id$ ++dnl ++ ++AC_DEFUN([AC_FPM_CHECKS], ++[ ++ AC_FPM_STDLIBS ++ AC_FPM_PRCTL ++ AC_FPM_CLOCK ++ AC_FPM_TRACE ++]) ++ ++AC_DEFUN([AC_FPM_STDLIBS], ++[ ++ AC_CHECK_FUNCS(setenv clearenv) ++ ++ AC_SEARCH_LIBS(socket, socket) ++ AC_SEARCH_LIBS(inet_addr, nsl) ++ ++ AC_CHECK_HEADERS([errno.h fcntl.h stdio.h stdlib.h unistd.h sys/uio.h]) ++ AC_CHECK_HEADERS([sys/select.h sys/socket.h sys/time.h]) ++ AC_CHECK_HEADERS([arpa/inet.h netinet/in.h]) ++]) ++ ++AC_DEFUN([AC_FPM_PRCTL], ++[ ++ AC_MSG_CHECKING([for prctl]) ++ ++ AC_TRY_COMPILE([ #include ], [prctl(0, 0, 0, 0, 0);], [ ++ AC_DEFINE([HAVE_PRCTL], 1, [do we have prctl?]) ++ AC_MSG_RESULT([yes]) ++ ], [ ++ AC_MSG_RESULT([no]) ++ ]) ++]) ++ ++AC_DEFUN([AC_FPM_CLOCK], ++[ ++ have_clock_gettime=no ++ ++ AC_MSG_CHECKING([for clock_gettime]) ++ ++ AC_TRY_LINK([ #include ], [struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts);], [ ++ have_clock_gettime=yes ++ AC_MSG_RESULT([yes]) ++ ], [ ++ AC_MSG_RESULT([no]) ++ ]) ++ ++ if test "$have_clock_gettime" = "no"; then ++ AC_MSG_CHECKING([for clock_gettime in -lrt]) ++ ++ SAVED_LIBS="$LIBS" ++ LIBS="$LIBS -lrt" ++ ++ AC_TRY_LINK([ #include ], [struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts);], [ ++ have_clock_gettime=yes ++ AC_MSG_RESULT([yes]) ++ ], [ ++ LIBS="$SAVED_LIBS" ++ AC_MSG_RESULT([no]) ++ ]) ++ fi ++ ++ if test "$have_clock_gettime" = "yes"; then ++ AC_DEFINE([HAVE_CLOCK_GETTIME], 1, [do we have clock_gettime?]) ++ fi ++ ++ have_clock_get_time=no ++ ++ if test "$have_clock_gettime" = "no"; then ++ AC_MSG_CHECKING([for clock_get_time]) ++ ++ AC_TRY_RUN([ #include ++ #include ++ #include ++ ++ int main() ++ { ++ kern_return_t ret; clock_serv_t aClock; mach_timespec_t aTime; ++ ret = host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &aClock); ++ ++ if (ret != KERN_SUCCESS) { ++ return 1; ++ } ++ ++ ret = clock_get_time(aClock, &aTime); ++ if (ret != KERN_SUCCESS) { ++ return 2; ++ } ++ ++ return 0; ++ } ++ ], [ ++ have_clock_get_time=yes ++ AC_MSG_RESULT([yes]) ++ ], [ ++ AC_MSG_RESULT([no]) ++ ]) ++ fi ++ ++ if test "$have_clock_get_time" = "yes"; then ++ AC_DEFINE([HAVE_CLOCK_GET_TIME], 1, [do we have clock_get_time?]) ++ fi ++]) ++ ++AC_DEFUN([AC_FPM_TRACE], ++[ ++ have_ptrace=no ++ have_broken_ptrace=no ++ ++ AC_MSG_CHECKING([for ptrace]) ++ ++ AC_TRY_COMPILE([ ++ #include ++ #include ], [ptrace(0, 0, (void *) 0, 0);], [ ++ have_ptrace=yes ++ AC_MSG_RESULT([yes]) ++ ], [ ++ AC_MSG_RESULT([no]) ++ ]) ++ ++ if test "$have_ptrace" = "yes"; then ++ AC_MSG_CHECKING([whether ptrace works]) ++ ++ AC_TRY_RUN([ ++ #include ++ #include ++ #include ++ #include ++ #include ++ #include ++ ++ #if !defined(PTRACE_ATTACH) && defined(PT_ATTACH) ++ #define PTRACE_ATTACH PT_ATTACH ++ #endif ++ ++ #if !defined(PTRACE_DETACH) && defined(PT_DETACH) ++ #define PTRACE_DETACH PT_DETACH ++ #endif ++ ++ #if !defined(PTRACE_PEEKDATA) && defined(PT_READ_D) ++ #define PTRACE_PEEKDATA PT_READ_D ++ #endif ++ ++ int main() ++ { ++ long v1 = (unsigned int) -1; /* copy will fail if sizeof(long) == 8 and we've got "int ptrace()" */ ++ long v2; ++ pid_t child; ++ int status; ++ ++ if ( (child = fork()) ) { /* parent */ ++ int ret = 0; ++ ++ if (0 > ptrace(PTRACE_ATTACH, child, 0, 0)) { ++ return 1; ++ } ++ ++ waitpid(child, &status, 0); ++ ++ #ifdef PT_IO ++ struct ptrace_io_desc ptio = { ++ .piod_op = PIOD_READ_D, ++ .piod_offs = &v1, ++ .piod_addr = &v2, ++ .piod_len = sizeof(v1) ++ }; ++ ++ if (0 > ptrace(PT_IO, child, (void *) &ptio, 0)) { ++ ret = 1; ++ } ++ #else ++ errno = 0; ++ ++ v2 = ptrace(PTRACE_PEEKDATA, child, (void *) &v1, 0); ++ ++ if (errno) { ++ ret = 1; ++ } ++ #endif ++ ptrace(PTRACE_DETACH, child, (void *) 1, 0); ++ ++ kill(child, SIGKILL); ++ ++ return ret ? ret : (v1 != v2); ++ } ++ else { /* child */ ++ sleep(10); ++ return 0; ++ } ++ } ++ ], [ ++ AC_MSG_RESULT([yes]) ++ ], [ ++ have_ptrace=no ++ have_broken_ptrace=yes ++ AC_MSG_RESULT([no]) ++ ]) ++ fi ++ ++ if test "$have_ptrace" = "yes"; then ++ AC_DEFINE([HAVE_PTRACE], 1, [do we have ptrace?]) ++ fi ++ ++ have_mach_vm_read=no ++ ++ if test "$have_broken_ptrace" = "yes"; then ++ AC_MSG_CHECKING([for mach_vm_read]) ++ ++ AC_TRY_COMPILE([ #include ++ #include ++ ], [ ++ mach_vm_read((vm_map_t)0, (mach_vm_address_t)0, (mach_vm_size_t)0, (vm_offset_t *)0, (mach_msg_type_number_t*)0); ++ ], [ ++ have_mach_vm_read=yes ++ AC_MSG_RESULT([yes]) ++ ], [ ++ AC_MSG_RESULT([no]) ++ ]) ++ fi ++ ++ if test "$have_mach_vm_read" = "yes"; then ++ AC_DEFINE([HAVE_MACH_VM_READ], 1, [do we have mach_vm_read?]) ++ fi ++ ++ proc_mem_file="" ++ ++ if test -r /proc/$$/mem ; then ++ proc_mem_file="mem" ++ else ++ if test -r /proc/$$/as ; then ++ proc_mem_file="as" ++ fi ++ fi ++ ++ if test -n "$proc_mem_file" ; then ++ AC_MSG_CHECKING([for proc mem file]) ++ ++ AC_TRY_RUN([ ++ #define _GNU_SOURCE ++ #define _FILE_OFFSET_BITS 64 ++ #if HAVE_INTTYPES_H ++ #include ++ #else ++ #include ++ #endif ++ ++ #include ++ #include ++ #include ++ #include ++ #include ++ int main() ++ { ++ long v1 = (unsigned int) -1, v2 = 0; ++ char buf[128]; ++ int fd; ++ sprintf(buf, "/proc/%d/$proc_mem_file", getpid()); ++ fd = open(buf, O_RDONLY); ++ if (0 > fd) { ++ return 1; ++ } ++ if (sizeof(long) != pread(fd, &v2, sizeof(long), (uintptr_t) &v1)) { ++ close(fd); ++ return 1; ++ } ++ close(fd); ++ return v1 != v2; ++ } ++ ], [ ++ AC_MSG_RESULT([$proc_mem_file]) ++ ], [ ++ proc_mem_file="" ++ AC_MSG_RESULT([no]) ++ ]) ++ fi ++ ++ if test -n "$proc_mem_file"; then ++ AC_DEFINE_UNQUOTED([PROC_MEM_FILE], "$proc_mem_file", [/proc/pid/mem interface]) ++ fi ++ ++ fpm_trace_type="" ++ ++ if test "$have_ptrace" = "yes"; then ++ fpm_trace_type=ptrace ++ ++ elif test -n "$proc_mem_file"; then ++ fpm_trace_type=pread ++ ++ elif test "$have_mach_vm_read" = "yes" ; then ++ fpm_trace_type=mach ++ ++ else ++ AC_MSG_ERROR([FPM Trace - ptrace, pread, or mach: could not be found]) ++ fi ++ ++]) ++ +diff -Naur php-src-vanilla/sapi/fpm/ac/fpm_conf.m4 php-src/sapi/fpm/ac/fpm_conf.m4 +--- php-src-vanilla/sapi/fpm/ac/fpm_conf.m4 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/ac/fpm_conf.m4 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,188 @@ ++ ++AC_DEFUN([AC_FPM_ARGS], ++[ ++ PHP_ARG_WITH(fpm-bin,, ++ [ --with-fpm-bin[=PATH] Set the path for the php-fpm binary [/usr/local/bin/php-fpm]], yes, no) ++ ++ PHP_ARG_WITH(fpm-port,, ++ [ --with-fpm-port[=PORT] Set the tcp port number to listen for cgi requests [9000]], yes, no) ++ ++ PHP_ARG_WITH(fpm-conf,, ++ [ --with-fpm-conf[=PATH] Set the path for php-fpm configuration file [/etc/php-fpm.conf]], yes, no) ++ ++ PHP_ARG_WITH(fpm-init,, ++ [ --with-fpm-init[=PATH] Set the path for php-fpm init file [/etc/init.d/php-fpm]], yes, no) ++ ++ PHP_ARG_WITH(fpm-log,, ++ [ --with-fpm-log[=PATH] Set the path for php-fpm log file [/var/log/php-fpm.log]], yes, no) ++ ++ PHP_ARG_WITH(fpm-pid,, ++ [ --with-fpm-pid[=PATH] Set the path for php-fpm pid file [/var/run/php-fpm.pid]], yes, no) ++ ++ PHP_ARG_WITH(fpm-user,, ++ [ --with-fpm-user[=USER] Set the user for php-fpm to run as [nobody]], yes, no) ++ ++ PHP_ARG_WITH(fpm-group,, ++ [ --with-fpm-group[=GRP] Set the group for php-fpm to run as. For a system user, ++ this should be set to match the fpm username [nobody]], yes, no) ++]) ++ ++AC_DEFUN([AC_FPM_VARS], ++[ ++ fpm_prefix=$ac_default_prefix ++ if test $prefix != "NONE" -a $prefix != "" -a $prefix != "no" ; then ++ fpm_prefix=$prefix ++ else ++ prefix=$fpm_prefix ++ fi ++ ++ if test $exec_prefix = "NONE" -o $exec_prefix = "" -o $exec_prefix = "no" ; then ++ exec_prefix=$fpm_prefix ++ fi ++ ++ if test `echo "$bindir" | grep "exec_prefix"` ; then ++ bindir=$exec_prefix/bin ++ fi ++ ++ fpm_bin_prefix=$fpm_prefix/bin ++ if test $bindir != "NONE" -a $bindir != "" -a $bindir != "no" ; then ++ fpm_bin_prefix=$bindir ++ fi ++ ++ if test -z "$PHP_FPM_BIN" -o "$PHP_FPM_BIN" = "yes" -o "$PHP_FPM_BIN" = "no"; then ++ php_fpm_bin_path="$fpm_bin_prefix/php-fpm" ++ else ++ php_fpm_bin_path="$PHP_FPM_BIN" ++ fi ++ php_fpm_bin=`basename $php_fpm_bin_path` ++ php_fpm_bin_dir=`dirname $php_fpm_bin_path` ++ ++ if test -z "$PHP_FPM_PORT" -o "$PHP_FPM_PORT" = "yes" -o "$PHP_FPM_PORT" = "no"; then ++ php_fpm_port="9000" ++ else ++ php_fpm_port="$PHP_FPM_PORT" ++ fi ++ ++ if test -z "$PHP_FPM_CONF" -o "$PHP_FPM_CONF" = "yes"; then ++ case $host_os in ++ freebsd*|dragonfly*) php_fpm_conf_path="/usr/local/etc/php-fpm.conf" ;; ++ *) php_fpm_conf_path="/etc/php-fpm.conf" ;; ++ esac ++ elif test "$PHP_FPM_CONF" = "no"; then ++ php_fpm_conf_path="" ++ else ++ php_fpm_conf_path="$PHP_FPM_CONF" ++ fi ++ if test -z "$php_fpm_conf_path"; then ++ php_fpm_conf="" ++ php_fpm_conf_dir="" ++ else ++ php_fpm_conf=`basename $php_fpm_conf_path` ++ php_fpm_conf_dir=`dirname $php_fpm_conf_path` ++ fi ++ ++ if test -z "$PHP_FPM_INIT" -o "$PHP_FPM_INIT" = "yes"; then ++ case $host_os in ++ openbsd*) php_fpm_init_path="" ;; ++ netbsd*) php_fpm_init_path="/etc/rc.d/php-fpm" ;; ++ *bsd*|dragonfly*) php_fpm_init_path="/usr/local/etc/rc.d/php-fpm" ;; ++ *) php_fpm_init_path="/etc/init.d/php-fpm" ;; ++ esac ++ test -f /etc/arch-release && php_fpm_init_path="/etc/rc.d/php-fpm" # arch linux ++ ++ elif test "$PHP_FPM_INIT" = "no"; then ++ php_fpm_init_path="" ++ else ++ php_fpm_init_path="$PHP_FPM_INIT" ++ fi ++ if test -z "$php_fpm_init_path"; then ++ php_fpm_init="" ++ php_fpm_init_dir="" ++ else ++ php_fpm_init=`basename $php_fpm_init_path` ++ php_fpm_init_dir=`dirname $php_fpm_init_path` ++ fi ++ ++ if test -z "$PHP_FPM_LOG" -o "$PHP_FPM_LOG" = "yes" -o "$PHP_FPM_LOG" = "no"; then ++ php_fpm_log_path="/var/log/php-fpm.log" ++ else ++ php_fpm_log_path="$PHP_FPM_LOG" ++ fi ++ php_fpm_log_dir=`dirname $php_fpm_log_path` ++ ++ if test -z "$PHP_FPM_PID" -o "$PHP_FPM_PID" = "yes" -o "$PHP_FPM_PID" = "no"; then ++ php_fpm_pid_path="/var/run/php-fpm.pid" ++ else ++ php_fpm_pid_path="$PHP_FPM_PID" ++ fi ++ php_fpm_pid_dir=`dirname $php_fpm_pid_path` ++ ++ if test -z "$PHP_FPM_USER" -o "$PHP_FPM_USER" = "yes" -o "$PHP_FPM_USER" = "no"; then ++ php_fpm_user="nobody" ++ else ++ php_fpm_user="$PHP_FPM_USER" ++ fi ++ ++ if test -z "$PHP_FPM_GROUP" -o "$PHP_FPM_GROUP" = "yes" -o "$PHP_FPM_GROUP" = "no"; then ++ php_fpm_group="nobody" ++ else ++ php_fpm_group="$PHP_FPM_GROUP" ++ fi ++ ++ ++ PHP_SUBST_OLD(fpm_version) ++ PHP_SUBST_OLD(php_fpm_bin) ++ PHP_SUBST_OLD(php_fpm_bin_dir) ++ PHP_SUBST_OLD(php_fpm_bin_path) ++ PHP_SUBST_OLD(php_fpm_port) ++ PHP_SUBST_OLD(php_fpm_conf) ++ PHP_SUBST_OLD(php_fpm_conf_dir) ++ PHP_SUBST_OLD(php_fpm_conf_path) ++ PHP_SUBST_OLD(php_fpm_init) ++ PHP_SUBST_OLD(php_fpm_init_dir) ++ PHP_SUBST_OLD(php_fpm_init_path) ++ PHP_SUBST_OLD(php_fpm_log_dir) ++ PHP_SUBST_OLD(php_fpm_log_path) ++ PHP_SUBST_OLD(php_fpm_pid_dir) ++ PHP_SUBST_OLD(php_fpm_pid_path) ++ PHP_SUBST_OLD(php_fpm_user) ++ PHP_SUBST_OLD(php_fpm_group) ++ ++ ++ AC_DEFINE_UNQUOTED(PHP_FPM_VERSION, "$fpm_version", [fpm version]) ++ AC_DEFINE_UNQUOTED(PHP_FPM_BIN, "$php_fpm_bin", [fpm binary executable]) ++ AC_DEFINE_UNQUOTED(PHP_FPM_BIN_DIR, "$php_fpm_bin_dir", [fpm binary dir]) ++ AC_DEFINE_UNQUOTED(PHP_FPM_BIN_PATH, "$php_fpm_bin_path", [fpm bin file path]) ++ AC_DEFINE_UNQUOTED(PHP_FPM_PORT, "$php_fpm_port", [tcp port]) ++ AC_DEFINE_UNQUOTED(PHP_FPM_CONF, "$php_fpm_conf", [fpm conf file]) ++ AC_DEFINE_UNQUOTED(PHP_FPM_CONF_DIR, "$php_fpm_conf_dir", [fpm conf dir]) ++ AC_DEFINE_UNQUOTED(PHP_FPM_CONF_PATH, "$php_fpm_conf_path", [fpm conf file path]) ++ AC_DEFINE_UNQUOTED(PHP_FPM_INIT, "$php_fpm_init", [fpm init file]) ++ AC_DEFINE_UNQUOTED(PHP_FPM_INIT_DIR, "$php_fpm_init_dir", [fpm init dir]) ++ AC_DEFINE_UNQUOTED(PHP_FPM_INIT_PATH, "$php_fpm_init_path", [fpm init file path]) ++ AC_DEFINE_UNQUOTED(PHP_FPM_LOG_DIR, "$php_fpm_log_dir", [fpm log dir]) ++ AC_DEFINE_UNQUOTED(PHP_FPM_LOG_PATH, "$php_fpm_log_path", [fpm log file path]) ++ AC_DEFINE_UNQUOTED(PHP_FPM_PID_DIR, "$php_fpm_pid_dir", [fpm pid dir]) ++ AC_DEFINE_UNQUOTED(PHP_FPM_PID_PATH, "$php_fpm_pid_path", [fpm pid file path]) ++ AC_DEFINE_UNQUOTED(PHP_FPM_USER, "$php_fpm_user", [fpm user name]) ++ AC_DEFINE_UNQUOTED(PHP_FPM_GROUP, "$php_fpm_group", [fpm group name]) ++ ++]) ++ ++ ++AC_DEFUN([AC_FPM_OUTPUT], ++[ ++ PHP_OUTPUT(sapi/fpm/php_fpm.conf:sapi/fpm/conf/php-fpm.conf.in) ++ PHP_OUTPUT(sapi/fpm/init.d.php_fpm:sapi/fpm/conf/init.d.php-fpm.in) ++ PHP_OUTPUT(sapi/fpm/nginx-site-conf.sample:sapi/fpm/conf/nginx-site-conf.sample.in) ++ PHP_OUTPUT(sapi/fpm/$php_fpm_bin.1:sapi/fpm/man/php-fpm.1.in) ++]) ++ ++ ++AC_DEFUN([AC_FPM_CONF], ++[ ++ AC_FPM_ARGS ++ AC_FPM_VARS ++ AC_FPM_OUTPUT ++]) ++ +diff -Naur php-src-vanilla/sapi/fpm/ac/fpm_libevent.m4 php-src/sapi/fpm/ac/fpm_libevent.m4 +--- php-src-vanilla/sapi/fpm/ac/fpm_libevent.m4 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/ac/fpm_libevent.m4 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,250 @@ ++dnl @synopsis AC_LIB_EVENT([MINIMUM-VERSION],[REQUIRED-VERSION]) ++dnl ++dnl Test for the libevent library of a particular version (or newer). ++dnl Source: http://svn.apache.org/repos/asf/incubator/thrift/trunk/aclocal/ax_lib_event.m4 ++dnl Modified: This file was modified for autoconf-2.13 and the PHP_ARG_WITH macro. ++dnl ++dnl If no path to the installed libevent is given, the macro will first try ++dnl using no -I or -L flags, then searches under /usr, /usr/local, /opt, ++dnl and /opt/libevent. ++dnl If these all fail, it will try the $LIBEVENT_ROOT environment variable. ++dnl ++dnl This macro requires that #include works and defines u_char. ++dnl ++dnl This macro calls: ++dnl AC_SUBST(LIBEVENT_CFLAGS) ++dnl AC_SUBST(LIBEVENT_LIBS) ++dnl ++dnl And (if libevent is found): ++dnl AC_DEFINE(HAVE_LIBEVENT) ++dnl ++dnl It also leaves the shell variables "success" and "ac_have_libevent" ++dnl set to "yes" or "no". ++dnl ++dnl NOTE: This macro does not currently work for cross-compiling, ++dnl but it can be easily modified to allow it. (grep "cross"). ++dnl ++dnl @category InstalledPackages ++dnl @category C ++dnl @version 2007-09-12 ++dnl @license AllPermissive ++dnl ++dnl Copyright (C) 2009 David Reiss ++dnl Copying and distribution of this file, with or without modification, ++dnl are permitted in any medium without royalty provided the copyright ++dnl notice and this notice are preserved. ++ ++AC_DEFUN([AC_LIB_EVENT_DO_CHECK], ++[ ++# Save our flags. ++CPPFLAGS_SAVED="$CPPFLAGS" ++LDFLAGS_SAVED="$LDFLAGS" ++LIBS_SAVED="$LIBS" ++LD_LIBRARY_PATH_SAVED="$LD_LIBRARY_PATH" ++ ++# Set our flags if we are checking a specific directory. ++if test -n "$ac_libevent_path" ; then ++ LIBEVENT_CPPFLAGS="-I$ac_libevent_path/include" ++ LIBEVENT_LDFLAGS="-L$ac_libevent_path/lib" ++ LD_LIBRARY_PATH="$ac_libevent_path/lib:$LD_LIBRARY_PATH" ++else ++ LIBEVENT_CPPFLAGS="" ++ LIBEVENT_LDFLAGS="" ++fi ++ ++# Required flag for libevent. ++LIBEVENT_LIBS="-levent" ++ ++# Prepare the environment for compilation. ++CPPFLAGS="$CPPFLAGS $LIBEVENT_CPPFLAGS" ++LDFLAGS="$LDFLAGS $LIBEVENT_LDFLAGS" ++LIBS="$LIBS $LIBEVENT_LIBS" ++export CPPFLAGS ++export LDFLAGS ++export LIBS ++export LD_LIBRARY_PATH ++ ++success=no ++ ++# Compile, link, and run the program. This checks: ++# - event.h is available for including. ++# - event_get_version() is available for linking. ++# - The event version string is lexicographically greater ++# than the required version. ++AC_TRY_RUN([ ++#include ++#include ++ ++int main(int argc, char *argv[]) ++{ ++ const char* lib_version = event_get_version(); ++ const char* wnt_version = "$WANT_LIBEVENT_VERSION"; ++ for (;;) { ++ /* If we reached the end of the want version. We have it. */ ++ if (*wnt_version == '\0' || *wnt_version == '-') { ++ return 0; ++ } ++ /* If the want version continues but the lib version does not, */ ++ /* we are missing a letter. We don't have it. */ ++ if (*lib_version == '\0' || *lib_version == '-') { ++ return 1; ++ } ++ ++ /* In the 1.4 version numbering style, if there are more digits */ ++ /* in one version than the other, that one is higher. */ ++ int lib_digits; ++ for (lib_digits = 0; ++ lib_version[lib_digits] >= '0' && ++ lib_version[lib_digits] <= '9'; ++ lib_digits++) ++ ; ++ int wnt_digits; ++ for (wnt_digits = 0; ++ wnt_version[wnt_digits] >= '0' && ++ wnt_version[wnt_digits] <= '9'; ++ wnt_digits++) ++ ; ++ if (lib_digits > wnt_digits) { ++ return 0; ++ } ++ if (lib_digits < wnt_digits) { ++ return 1; ++ } ++ /* If we have greater than what we want. We have it. */ ++ if (*lib_version > *wnt_version) { ++ return 0; ++ } ++ /* If we have less, we don't. */ ++ if (*lib_version < *wnt_version) { ++ return 1; ++ } ++ lib_version++; ++ wnt_version++; ++ } ++ return 0; ++} ++],[ ++success=yes ++]) ++ ++# Restore flags. ++LIBEVENT_LIBS="" ++CPPFLAGS="$CPPFLAGS_SAVED" ++LDFLAGS="$LDFLAGS_SAVED" ++LIBS="$LIBS_SAVED" ++LD_LIBRARY_PATH="$LD_LIBRARY_PATH_SAVED" ++]) ++ ++AC_DEFUN([AC_LIB_EVENT], ++[ ++ ++PHP_ARG_WITH(libevent,, ++[ --with-libevent[=PATH] Path to the libevent, needed for fpm SAPI [/usr/local]], yes, yes) ++ ++if test "$PHP_LIBEVENT" != "no"; then ++ LIBEVENT_MIN_VERSION=ifelse([$1], ,1.4.3,$1) ++ LIBEVENT_REQ_VERSION=ifelse([$2], ,1.4.11,$2) ++ ++ # Default library search paths ($sys_lib_search_path_spec) ++ AC_LIBTOOL_SYS_DYNAMIC_LINKER ++ ++ libevent_prefix=$ac_default_prefix ++ if test $prefix != "NONE" -a $prefix != "" -a $prefix != "no" ; then ++ libevent_prefix=$prefix ++ fi ++ ++ if test "$PHP_LIBEVENT" = "yes"; then ++ PHP_LIBEVENT=$libevent_prefix ++ fi ++ ++ AC_MSG_CHECKING(for libevent >= $LIBEVENT_REQ_VERSION) ++ for ac_libevent_path in "" $PHP_LIBEVENT /usr /usr/local /opt /opt/local /opt/libevent ; do ++ WANT_LIBEVENT_VERSION="$LIBEVENT_REQ_VERSION" ++ AC_LIB_EVENT_DO_CHECK ++ if test "$success" = "yes"; then ++ break; ++ fi ++ done ++ if test "$success" = "no"; then ++ ++ AC_MSG_RESULT(no) ++ AC_MSG_WARN([Could not find libevent $LIBEVENT_REQ_VERSION.]) ++ AC_MSG_WARN([The use of earlier versions of libevent is not recommended]) ++ AC_MSG_WARN([and can result in unspecified or unsupported behaviour.]) ++ ++ AC_MSG_CHECKING(for minimum libevent version >= $LIBEVENT_MIN_VERSION) ++ for ac_libevent_path in "" $PHP_LIBEVENT /usr /usr/local /opt /opt/local /opt/libevent ; do ++ WANT_LIBEVENT_VERSION="$LIBEVENT_MIN_VERSION" ++ AC_LIB_EVENT_DO_CHECK ++ if test "$success" = "yes"; then ++ break; ++ fi ++ done ++ if test "$success" = "no"; then ++ AC_MSG_RESULT(no) ++ LIBEVENT_LIBS="" ++ ac_have_libevent=no ++ AC_MSG_WARN([Syntax:]) ++ AC_MSG_WARN([--with-libevent=yes|[path] - link to libevent.a (static library)]) ++ AC_MSG_WARN([--with-libevent=shared[,path] - link to libevent.so (shared library)]) ++ AC_MSG_ERROR([Libevent minimum version >= $LIBEVENT_MIN_VERSION could not be found.]) ++ fi ++ fi ++ ++ if test "$ext_shared" = "yes"; then ++ if test -n "$ac_libevent_path"; then ++ LIBEVENT_LIBS="-L$ac_libevent_path/lib -levent" ++ else ++ LIBEVENT_LIBS="-levent" ++ fi ++ else ++ libevent_a="libevent.a" ++ if test -n "$ac_libevent_path"; then ++ if test -f "$ac_libevent_path/lib/$libevent_a" ; then ++ LIBEVENT_LIBS="$ac_libevent_path/lib/$libevent_a" ++ fi ++ if test -z "$LIBEVENT_LIBS"; then ++ AC_MSG_RESULT(no) ++ AC_MSG_WARN([libevent.a could not be found. We looked in:]) ++ AC_MSG_WARN([\"$ac_libevent_path\"]) ++ fi ++ else ++ for search_path in $sys_lib_search_path_spec ; do ++ if test -f "$search_path$libevent_a" ; then ++ LIBEVENT_LIBS="$search_path$libevent_a" ++ break; ++ fi ++ done ++ if test -z "$LIBEVENT_LIBS"; then ++ AC_MSG_RESULT(no) ++ AC_MSG_WARN([libevent.a could not be found. We looked in:]) ++ AC_MSG_WARN([\"$sys_lib_search_path_spec\"]) ++ fi ++ fi ++ if test -z "$LIBEVENT_LIBS"; then ++ AC_MSG_WARN([Install libevent system-wide (make install)]) ++ AC_MSG_WARN([Syntax:]) ++ AC_MSG_WARN([--with-libevent=yes|[path] - link to libevent.a (static library)]) ++ AC_MSG_WARN([--with-libevent=shared[,path] - link to libevent.so (shared library)]) ++ AC_MSG_ERROR([libevent.a could not be found. Stop.]) ++ fi ++ fi ++ ++ if test "$success" = "yes" ; then ++ AC_MSG_RESULT(yes) ++ ac_have_libevent=yes ++ AC_DEFINE(HAVE_LIBEVENT, 1, [define if libevent is available]) ++ fi ++ ++ if test -n "$ac_libevent_path"; then ++ LIBEVENT_CFLAGS="-I$ac_libevent_path/include" ++ fi ++ ++ AC_SUBST(LIBEVENT_CFLAGS) ++ AC_SUBST(LIBEVENT_LIBS) ++ ++else ++ AC_MSG_ERROR([FPM Requires Libevent. You must build this target --with-libevent. Stop.]) ++fi ++ ++]) +diff -Naur php-src-vanilla/sapi/fpm/ac/Makefile.frag php-src/sapi/fpm/ac/Makefile.frag +--- php-src-vanilla/sapi/fpm/ac/Makefile.frag 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/ac/Makefile.frag 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,61 @@ ++fpm: $(SAPI_FPM_PATH) ++ ++$(SAPI_FPM_PATH): $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(SAPI_EXTRA_DEPS) ++ $(BUILD_FPM) ++ ++install: install-fpm ++ ++install-fpm: all ++ @echo "Installing PHP FPM binary: $(INSTALL_ROOT)$(php_fpm_bin_path)" ++ @$(mkinstalldirs) $(INSTALL_ROOT)$(php_fpm_bin_dir) ++ @$(mkinstalldirs) $(INSTALL_ROOT)$(php_fpm_pid_dir) ++ @$(mkinstalldirs) $(INSTALL_ROOT)$(php_fpm_log_dir) ++ @$(INSTALL) -m 0755 $(SAPI_FPM_PATH) $(INSTALL_ROOT)$(php_fpm_bin_path)$(program_suffix)$(EXEEXT) ++ ++ @test "$(php_fpm_conf)" && \ ++ echo "Installing PHP FPM config: $(INSTALL_ROOT)$(php_fpm_conf_path)" && \ ++ $(mkinstalldirs) $(INSTALL_ROOT)$(php_fpm_conf_dir) || : ++ ++ @test "$(php_fpm_conf)" && \ ++ test -f "$(INSTALL_ROOT)$(php_fpm_conf_path)" && \ ++ $(INSTALL_DATA) --backup=numbered $(INSTALL_ROOT)$(php_fpm_conf_path) $(INSTALL_ROOT)$(php_fpm_conf_path).old || : ++ ++ @test "$(php_fpm_conf)" && \ ++ $(INSTALL_DATA) sapi/fpm/php_fpm.conf $(INSTALL_ROOT)$(php_fpm_conf_path).default && \ ++ ln -sf $(INSTALL_ROOT)$(php_fpm_conf_path).default $(INSTALL_ROOT)$(php_fpm_conf_path) || : ++ ++ @echo "Installing PHP FPM man page: $(INSTALL_ROOT)$(mandir)/man1/$(php_fpm_bin)$(program_suffix).1" ++ @$(mkinstalldirs) $(INSTALL_ROOT)$(mandir)/man1 ++ @$(INSTALL_DATA) sapi/fpm/$(php_fpm_bin).1 $(INSTALL_ROOT)$(mandir)/man1/$(php_fpm_bin)$(program_suffix).1 ++ ++ @test "$(php_fpm_init)" && \ ++ echo "Installing PHP FPM init script: $(INSTALL_ROOT)$(php_fpm_init_path)" && \ ++ $(mkinstalldirs) $(INSTALL_ROOT)$(php_fpm_init_dir) && \ ++ $(INSTALL) -m 0755 sapi/fpm/init.d.php_fpm $(INSTALL_ROOT)$(php_fpm_init_path) || : ++ ++ @test -d /etc/nginx/ && \ ++ echo "Installing NGINX sample config: /etc/nginx/nginx-site-conf.sample" && \ ++ $(mkinstalldirs) $(INSTALL_ROOT)/etc/nginx && \ ++ $(INSTALL_DATA) -b sapi/fpm/nginx-site-conf.sample $(INSTALL_ROOT)/etc/nginx/nginx-site-conf.sample || : ++ ++ @test -d /usr/local/etc/nginx/ && \ ++ echo "Installing NGINX sample config: /usr/local/etc/nginx/nginx-site-conf.sample" && \ ++ $(mkinstalldirs) $(INSTALL_ROOT)/usr/local/etc/nginx && \ ++ $(INSTALL_DATA) -b sapi/fpm/nginx-site-conf.sample $(INSTALL_ROOT)/usr/local/etc/nginx/nginx-site-conf.sample || : ++ ++ @test -d /usr/local/nginx/conf/ && \ ++ echo "Installing NGINX sample config: /usr/local/nginx/conf/nginx-site-conf.sample" && \ ++ $(mkinstalldirs) $(INSTALL_ROOT)/usr/local/nginx/conf && \ ++ $(INSTALL_DATA) -b sapi/fpm/nginx-site-conf.sample $(INSTALL_ROOT)/usr/local/nginx/conf/nginx-site-conf.sample || : ++ ++ @echo "" ++ @echo "*** FPM Installation complete. ***" ++ @echo "" ++ ++ @test "$(php_fpm_init)" && \ ++ echo "run:" && \ ++ echo "\`update-rc.d $(php_fpm_init) defaults; invoke-rc.d $(php_fpm_init) start\`" && \ ++ echo "" && \ ++ echo "or system equivalent to start the $(php_fpm_init) service." && \ ++ echo "" || : ++ +diff -Naur php-src-vanilla/sapi/fpm/cgi/cgi_main.c php-src/sapi/fpm/cgi/cgi_main.c +--- php-src-vanilla/sapi/fpm/cgi/cgi_main.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/cgi/cgi_main.c 2009-10-18 21:05:39.302497288 +0100 +@@ -0,0 +1,1660 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | PHP Version 5 | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 1997-2008 The PHP Group | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 3.01 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available through the world-wide-web at the following url: | ++ | http://www.php.net/license/3_01.txt | ++ | If you did not receive a copy of the PHP license and are unable to | ++ | obtain it through the world-wide-web, please send a note to | ++ | license@php.net so we can mail you a copy immediately. | ++ +----------------------------------------------------------------------+ ++ | Authors: Rasmus Lerdorf | ++ | Stig Bakken | ++ | Zeev Suraski | ++ | FastCGI: Ben Mansell | ++ | Shane Caraveo | ++ | Dmitry Stogov | ++ +----------------------------------------------------------------------+ ++*/ ++ ++/* $Id$ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++#ifdef PHP_WIN32 ++#include "win32/time.h" ++#include "win32/signal.h" ++#include ++#endif ++#if HAVE_SYS_TIME_H ++#include ++#endif ++#if HAVE_UNISTD_H ++#include ++#endif ++#if HAVE_SIGNAL_H ++#include ++#endif ++#if HAVE_SETLOCALE ++#include ++#endif ++#if HAVE_SYS_TYPES_H ++#include ++#endif ++#if HAVE_SYS_WAIT_H ++#include ++#endif ++#if HAVE_FCNTL_H ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef PHP_WIN32 ++#include ++#include ++#include "win32/php_registry.h" ++#endif ++ ++#ifdef __riscos__ ++#include ++int __riscosify_control = __RISCOSIFY_STRICT_UNIX_SPECS; ++#endif ++ ++#include "zend_compile.h" ++#include "zend_execute.h" ++#include "zend_highlight.h" ++#include "zend_indent.h" ++ ++#include "php_getopt.h" ++ ++#include "fastcgi.h" ++ ++#ifdef FPM_AUTOCONFIG_H ++#include ++#else ++#include ++#endif ++#include ++#include ++ ++ ++static void (*php_php_import_environment_variables)(zval *array_ptr TSRMLS_DC); ++ ++static int parent = 1; ++ ++static int request_body_fd; ++ ++static char *sapi_cgibin_getenv(char *name, size_t name_len TSRMLS_DC); ++ ++static char *php_optarg = NULL; ++static int php_optind = 1; ++static zend_module_entry cgi_module_entry; ++ ++static const opt_struct OPTIONS[] = { ++ {'a', 0, "interactive"}, ++ {'b', 1, "bindpath"}, ++ {'C', 0, "no-chdir"}, ++ {'c', 1, "php-ini"}, ++ {'d', 1, "define"}, ++ {'e', 0, "profile-info"}, ++ {'f', 1, "file"}, ++ {'h', 0, "help"}, ++ {'i', 0, "info"}, ++ {'l', 0, "syntax-check"}, ++ {'m', 0, "modules"}, ++ {'n', 0, "no-php-ini"}, ++ {'q', 0, "no-header"}, ++ {'s', 0, "syntax-highlight"}, ++ {'s', 0, "syntax-highlighting"}, ++ {'w', 0, "strip"}, ++ {'?', 0, "usage"},/* help alias (both '?' and 'usage') */ ++ {'v', 0, "version"}, ++ {'x', 0, "fpm"}, ++ {'y', 1, "fpm-config"}, ++ {'z', 1, "zend-extension"}, ++ {'-', 0, NULL} /* end of args */ ++}; ++ ++typedef struct _php_cgi_globals_struct { ++ zend_bool rfc2616_headers; ++ zend_bool nph; ++ zend_bool check_shebang_line; ++#if ENABLE_PATHINFO_CHECK ++ zend_bool fix_pathinfo; ++#endif ++ zend_bool fcgi_logging; ++# ifdef PHP_WIN32 ++ zend_bool impersonate; ++# endif ++ char *error_header; ++} php_cgi_globals_struct; ++ ++#ifdef ZTS ++static int php_cgi_globals_id; ++#define CGIG(v) TSRMG(php_cgi_globals_id, php_cgi_globals_struct *, v) ++#else ++static php_cgi_globals_struct php_cgi_globals; ++#define CGIG(v) (php_cgi_globals.v) ++#endif ++ ++#ifdef PHP_WIN32 ++#define TRANSLATE_SLASHES(path) \ ++ { \ ++ char *tmp = path; \ ++ while (*tmp) { \ ++ if (*tmp == '\\') *tmp = '/'; \ ++ tmp++; \ ++ } \ ++ } ++#else ++#define TRANSLATE_SLASHES(path) ++#endif ++ ++static int print_module_info(zend_module_entry *module, void *arg TSRMLS_DC) ++{ ++ php_printf("%s\n", module->name); ++ return 0; ++} ++ ++static int module_name_cmp(const void *a, const void *b TSRMLS_DC) ++{ ++ Bucket *f = *((Bucket **) a); ++ Bucket *s = *((Bucket **) b); ++ ++ return strcasecmp(((zend_module_entry *)f->pData)->name, ++ ((zend_module_entry *)s->pData)->name); ++} ++ ++static void print_modules(TSRMLS_D) ++{ ++ HashTable sorted_registry; ++ zend_module_entry tmp; ++ ++ zend_hash_init(&sorted_registry, 50, NULL, NULL, 1); ++ zend_hash_copy(&sorted_registry, &module_registry, NULL, &tmp, sizeof(zend_module_entry)); ++ zend_hash_sort(&sorted_registry, zend_qsort, module_name_cmp, 0 TSRMLS_CC); ++ zend_hash_apply_with_argument(&sorted_registry, (apply_func_arg_t) print_module_info, NULL TSRMLS_CC); ++ zend_hash_destroy(&sorted_registry); ++} ++ ++static int print_extension_info(zend_extension *ext, void *arg TSRMLS_DC) ++{ ++ php_printf("%s\n", ext->name); ++ return 0; ++} ++ ++static int extension_name_cmp(const zend_llist_element **f, ++ const zend_llist_element **s TSRMLS_DC) ++{ ++ return strcmp(((zend_extension *)(*f)->data)->name, ++ ((zend_extension *)(*s)->data)->name); ++} ++ ++static void print_extensions(TSRMLS_D) ++{ ++ zend_llist sorted_exts; ++ ++ zend_llist_copy(&sorted_exts, &zend_extensions); ++ sorted_exts.dtor = NULL; ++ zend_llist_sort(&sorted_exts, extension_name_cmp TSRMLS_CC); ++ zend_llist_apply_with_argument(&sorted_exts, (llist_apply_with_arg_func_t) print_extension_info, NULL TSRMLS_CC); ++ zend_llist_destroy(&sorted_exts); ++} ++ ++#ifndef STDOUT_FILENO ++#define STDOUT_FILENO 1 ++#endif ++ ++static inline size_t sapi_cgibin_single_write(const char *str, uint str_length TSRMLS_DC) ++{ ++ long ret; ++ ++ if (fcgi_is_fastcgi()) { ++ fcgi_request *request = (fcgi_request*) SG(server_context); ++ long ret = fcgi_write(request, FCGI_STDOUT, str, str_length); ++ if (ret <= 0) { ++ return 0; ++ } ++ return ret; ++ } ++ ret = write(STDOUT_FILENO, str, str_length); ++ if (ret <= 0) return 0; ++ return ret; ++} ++ ++static int sapi_cgibin_ub_write(const char *str, uint str_length TSRMLS_DC) ++{ ++ const char *ptr = str; ++ uint remaining = str_length; ++ size_t ret; ++ ++ while (remaining > 0) { ++ ret = sapi_cgibin_single_write(ptr, remaining TSRMLS_CC); ++ if (!ret) { ++ php_handle_aborted_connection(); ++ return str_length - remaining; ++ } ++ ptr += ret; ++ remaining -= ret; ++ } ++ ++ return str_length; ++} ++ ++ ++static void sapi_cgibin_flush(void *server_context) ++{ ++ if (fcgi_is_fastcgi()) { ++ fcgi_request *request = (fcgi_request*) server_context; ++ if ( ++#ifndef PHP_WIN32 ++ !parent && ++#endif ++ request && !fcgi_flush(request, 0)) { ++ php_handle_aborted_connection(); ++ } ++ return; ++ } ++ if (fflush(stdout) == EOF) { ++ php_handle_aborted_connection(); ++ } ++} ++ ++#define SAPI_CGI_MAX_HEADER_LENGTH 1024 ++ ++typedef struct _http_error { ++ int code; ++ const char* msg; ++} http_error; ++ ++static const http_error http_error_codes[] = { ++ {100, "Continue"}, ++ {101, "Switching Protocols"}, ++ {200, "OK"}, ++ {201, "Created"}, ++ {202, "Accepted"}, ++ {203, "Non-Authoritative Information"}, ++ {204, "No Content"}, ++ {205, "Reset Content"}, ++ {206, "Partial Content"}, ++ {300, "Multiple Choices"}, ++ {301, "Moved Permanently"}, ++ {302, "Moved Temporarily"}, ++ {303, "See Other"}, ++ {304, "Not Modified"}, ++ {305, "Use Proxy"}, ++ {400, "Bad Request"}, ++ {401, "Unauthorized"}, ++ {402, "Payment Required"}, ++ {403, "Forbidden"}, ++ {404, "Not Found"}, ++ {405, "Method Not Allowed"}, ++ {406, "Not Acceptable"}, ++ {407, "Proxy Authentication Required"}, ++ {408, "Request Time-out"}, ++ {409, "Conflict"}, ++ {410, "Gone"}, ++ {411, "Length Required"}, ++ {412, "Precondition Failed"}, ++ {413, "Request Entity Too Large"}, ++ {414, "Request-URI Too Large"}, ++ {415, "Unsupported Media Type"}, ++ {500, "Internal Server Error"}, ++ {501, "Not Implemented"}, ++ {502, "Bad Gateway"}, ++ {503, "Service Unavailable"}, ++ {504, "Gateway Time-out"}, ++ {505, "HTTP Version not supported"}, ++ {0, NULL} ++}; ++ ++static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) ++{ ++ char buf[SAPI_CGI_MAX_HEADER_LENGTH]; ++ sapi_header_struct *h; ++ zend_llist_position pos; ++ zend_bool ignore_status = 0; ++ int response_status = SG(sapi_headers).http_response_code; ++ ++ if (SG(request_info).no_headers == 1) { ++ return SAPI_HEADER_SENT_SUCCESSFULLY; ++ } ++ ++ if (CGIG(nph) || SG(sapi_headers).http_response_code != 200) ++ { ++ int len; ++ zend_bool has_status = 0; ++ ++ if (CGIG(rfc2616_headers) && SG(sapi_headers).http_status_line) { ++ char *s; ++ len = slprintf(buf, SAPI_CGI_MAX_HEADER_LENGTH, "%s\r\n", SG(sapi_headers).http_status_line); ++ if ((s = strchr(SG(sapi_headers).http_status_line, ' '))) { ++ response_status = atoi((s + 1)); ++ } ++ ++ if (len > SAPI_CGI_MAX_HEADER_LENGTH) { ++ len = SAPI_CGI_MAX_HEADER_LENGTH; ++ } ++ ++ } else { ++ char *s; ++ ++ if (SG(sapi_headers).http_status_line && ++ (s = strchr(SG(sapi_headers).http_status_line, ' ')) != 0 && ++ (s - SG(sapi_headers).http_status_line) >= 5 && ++ strncasecmp(SG(sapi_headers).http_status_line, "HTTP/", 5) == 0) { ++ len = slprintf(buf, sizeof(buf), "Status:%s\r\n", s); ++ response_status = atoi((s + 1)); ++ } else { ++ h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos); ++ while (h) { ++ if (h->header_len > sizeof("Status:")-1 && ++ strncasecmp(h->header, "Status:", sizeof("Status:")-1) == 0) { ++ has_status = 1; ++ break; ++ } ++ h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos); ++ } ++ if (!has_status) { ++ http_error *err = (http_error*)http_error_codes; ++ ++ while (err->code != 0) { ++ if (err->code == SG(sapi_headers).http_response_code) { ++ break; ++ } ++ err++; ++ } ++ if (err->msg) { ++ len = slprintf(buf, sizeof(buf), "Status: %d %s\r\n", SG(sapi_headers).http_response_code, err->msg); ++ } else { ++ len = slprintf(buf, sizeof(buf), "Status: %d\r\n", SG(sapi_headers).http_response_code); ++ } ++ } ++ } ++ } ++ if (!has_status) { ++ PHPWRITE_H(buf, len); ++ ignore_status = 1; ++ } ++ } ++ ++ h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos); ++ while (h) { ++ /* prevent CRLFCRLF */ ++ if (h->header_len) { ++ if (h->header_len > sizeof("Status:")-1 && ++ strncasecmp(h->header, "Status:", sizeof("Status:")-1) == 0) { ++ if (!ignore_status) { ++ ignore_status = 1; ++ PHPWRITE_H(h->header, h->header_len); ++ PHPWRITE_H("\r\n", 2); ++ } ++ } else if (response_status == 304 && h->header_len > sizeof("Content-Type:")-1 && ++ strncasecmp(h->header, "Content-Type:", sizeof("Content-Type:")-1) == 0) { ++ h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos); ++ continue; ++ } else { ++ PHPWRITE_H(h->header, h->header_len); ++ PHPWRITE_H("\r\n", 2); ++ } ++ } ++ h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos); ++ } ++ PHPWRITE_H("\r\n", 2); ++ ++ return SAPI_HEADER_SENT_SUCCESSFULLY; ++} ++ ++ ++static int sapi_cgi_read_post(char *buffer, uint count_bytes TSRMLS_DC) ++{ ++ int read_bytes=0, tmp_read_bytes; ++ ++ count_bytes = MIN(count_bytes, (uint) SG(request_info).content_length - SG(read_post_bytes)); ++ while (read_bytes < count_bytes) { ++ if (fcgi_is_fastcgi()) { ++ fcgi_request *request = (fcgi_request*) SG(server_context); ++ ++ if (request_body_fd == -1) { ++ char *request_body_filename = sapi_cgibin_getenv((char *) "REQUEST_BODY_FILE", ++ sizeof("REQUEST_BODY_FILE")-1 TSRMLS_CC); ++ ++ if (request_body_filename && *request_body_filename) { ++ request_body_fd = open(request_body_filename, O_RDONLY); ++ ++ if (0 > request_body_fd) { ++ php_error(E_WARNING, "REQUEST_BODY_FILE: open('%s') failed: %s (%d)", ++ request_body_filename, strerror(errno), errno); ++ return 0; ++ } ++ } ++ } ++ ++ /* If REQUEST_BODY_FILE variable not available - read post body from fastcgi stream */ ++ if (request_body_fd < 0) { ++ tmp_read_bytes = fcgi_read(request, buffer + read_bytes, count_bytes - read_bytes); ++ } else { ++ tmp_read_bytes = read(request_body_fd, buffer + read_bytes, count_bytes - read_bytes); ++ } ++ } else { ++ tmp_read_bytes = read(0, buffer + read_bytes, count_bytes - read_bytes); ++ } ++ ++ if (tmp_read_bytes <= 0) { ++ break; ++ } ++ read_bytes += tmp_read_bytes; ++ } ++ return read_bytes; ++} ++ ++static char *sapi_cgibin_getenv(char *name, size_t name_len TSRMLS_DC) ++{ ++ /* when php is started by mod_fastcgi, no regular environment ++ is provided to PHP. It is always sent to PHP at the start ++ of a request. So we have to do our own lookup to get env ++ vars. This could probably be faster somehow. */ ++ if (fcgi_is_fastcgi()) { ++ fcgi_request *request = (fcgi_request*) SG(server_context); ++ return fcgi_getenv(request, name, name_len); ++ } ++ /* if cgi, or fastcgi and not found in fcgi env ++ check the regular environment */ ++ return getenv(name); ++} ++ ++static char *_sapi_cgibin_putenv(char *name, char *value TSRMLS_DC) ++{ ++ int name_len; ++#if !HAVE_SETENV || !HAVE_UNSETENV ++ int len; ++ char *buf; ++#endif ++ ++ if (!name) { ++ return NULL; ++ } ++ name_len = strlen(name); ++ ++ /* when php is started by mod_fastcgi, no regular environment ++ is provided to PHP. It is always sent to PHP at the start ++ of a request. So we have to do our own lookup to get env ++ vars. This could probably be faster somehow. */ ++ if (fcgi_is_fastcgi()) { ++ fcgi_request *request = (fcgi_request*) SG(server_context); ++ return fcgi_putenv(request, name, name_len, value); ++ } ++#if HAVE_SETENV ++ if (value) { ++ setenv(name, value, 1); ++ } ++#endif ++#if HAVE_UNSETENV ++ if (!value) { ++ unsetenv(name); ++ } ++#endif ++ ++#if !HAVE_SETENV || !HAVE_UNSETENV ++ /* if cgi, or fastcgi and not found in fcgi env ++ check the regular environment ++ this leaks, but it's only cgi anyway, we'll fix ++ it for 5.0 ++ */ ++ len = name_len + (value ? strlen(value) : 0) + sizeof("=") + 2; ++ buf = (char *) malloc(len); ++ if (buf == NULL) { ++ return getenv(name); ++ } ++#endif ++#if !HAVE_SETENV ++ if (value) { ++ len = slprintf(buf, len - 1, "%s=%s", name, value); ++ putenv(buf); ++ } ++#endif ++#if !HAVE_UNSETENV ++ if (!value) { ++ len = slprintf(buf, len - 1, "%s=", name); ++ putenv(buf); ++ } ++#endif ++ return getenv(name); ++} ++ ++static char *sapi_cgi_read_cookies(TSRMLS_D) ++{ ++ return sapi_cgibin_getenv((char *) "HTTP_COOKIE", sizeof("HTTP_COOKIE")-1 TSRMLS_CC); ++} ++ ++void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC) ++{ ++ if (PG(http_globals)[TRACK_VARS_ENV] && ++ array_ptr != PG(http_globals)[TRACK_VARS_ENV] && ++ Z_TYPE_P(PG(http_globals)[TRACK_VARS_ENV]) == IS_ARRAY && ++ zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_ENV])) > 0) { ++ zval_dtor(array_ptr); ++ *array_ptr = *PG(http_globals)[TRACK_VARS_ENV]; ++ INIT_PZVAL(array_ptr); ++ zval_copy_ctor(array_ptr); ++ return; ++ } else if (PG(http_globals)[TRACK_VARS_SERVER] && ++ array_ptr != PG(http_globals)[TRACK_VARS_SERVER] && ++ Z_TYPE_P(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY && ++ zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER])) > 0) { ++ zval_dtor(array_ptr); ++ *array_ptr = *PG(http_globals)[TRACK_VARS_SERVER]; ++ INIT_PZVAL(array_ptr); ++ zval_copy_ctor(array_ptr); ++ return; ++ } ++ ++ /* call php's original import as a catch-all */ ++ php_php_import_environment_variables(array_ptr TSRMLS_CC); ++ ++ if (fcgi_is_fastcgi()) { ++ fcgi_request *request = (fcgi_request*) SG(server_context); ++ HashPosition pos; ++ int magic_quotes_gpc = PG(magic_quotes_gpc); ++ char *var, **val; ++ uint var_len; ++ ulong idx; ++ int filter_arg = (array_ptr == PG(http_globals)[TRACK_VARS_ENV])?PARSE_ENV:PARSE_SERVER; ++ ++ /* turn off magic_quotes while importing environment variables */ ++ PG(magic_quotes_gpc) = 0; ++ for (zend_hash_internal_pointer_reset_ex(&request->env, &pos); ++ zend_hash_get_current_key_ex(&request->env, &var, &var_len, &idx, 0, &pos) == HASH_KEY_IS_STRING && ++ zend_hash_get_current_data_ex(&request->env, (void **) &val, &pos) == SUCCESS; ++ zend_hash_move_forward_ex(&request->env, &pos)) { ++ unsigned int new_val_len; ++ if (sapi_module.input_filter(filter_arg, var, val, strlen(*val), &new_val_len TSRMLS_CC)) { ++ php_register_variable_safe(var, *val, new_val_len, array_ptr TSRMLS_CC); ++ } ++ } ++ PG(magic_quotes_gpc) = magic_quotes_gpc; ++ } ++} ++ ++static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC) ++{ ++ unsigned int php_self_len; ++ char *php_self; ++ ++ /* In CGI mode, we consider the environment to be a part of the server ++ * variables ++ */ ++ php_import_environment_variables(track_vars_array TSRMLS_CC); ++ ++#if ENABLE_PATHINFO_CHECK ++ if (CGIG(fix_pathinfo)) { ++ char *script_name = SG(request_info).request_uri; ++ unsigned int script_name_len = script_name ? strlen(script_name) : 0; ++ char *path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO")-1 TSRMLS_CC); ++ unsigned int path_info_len = path_info ? strlen(path_info) : 0; ++ ++ php_self_len = script_name_len + path_info_len; ++ php_self = emalloc(php_self_len + 1); ++ if (script_name) { ++ memcpy(php_self, script_name, script_name_len + 1); ++ } ++ if (path_info) { ++ memcpy(php_self + script_name_len, path_info, path_info_len + 1); ++ } ++ ++ /* Build the special-case PHP_SELF variable for the CGI version */ ++ if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len TSRMLS_CC)) { ++ php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array TSRMLS_CC); ++ } ++ efree(php_self); ++ return; ++ } ++#endif ++ ++ php_self = SG(request_info).request_uri ? SG(request_info).request_uri : ""; ++ php_self_len = strlen(php_self); ++ if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len TSRMLS_CC)) { ++ php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array TSRMLS_CC); ++ } ++} ++ ++static void sapi_cgi_log_message(char *message) ++{ ++ TSRMLS_FETCH(); ++ ++ if (fcgi_is_fastcgi() && CGIG(fcgi_logging)) { ++ fcgi_request *request; ++ ++ request = (fcgi_request*) SG(server_context); ++ if (request) { ++ int len = strlen(message); ++ char *buf = malloc(len+2); ++ ++ memcpy(buf, message, len); ++ memcpy(buf + len, "\n", sizeof("\n")); ++ fcgi_write(request, FCGI_STDERR, buf, len+1); ++ free(buf); ++ } else { ++ fprintf(stderr, "%s\n", message); ++ } ++ /* ignore return code */ ++ } else ++ fprintf(stderr, "%s\n", message); ++} ++ ++static int sapi_cgi_deactivate(TSRMLS_D) ++{ ++ /* flush only when SAPI was started. The reasons are: ++ 1. SAPI Deactivate is called from two places: module init and request shutdown ++ 2. When the first call occurs and the request is not set up, flush fails on ++ FastCGI. ++ */ ++ if (SG(sapi_started)) { ++ sapi_cgibin_flush(SG(server_context)); ++ } ++ return SUCCESS; ++} ++ ++static int php_cgi_startup(sapi_module_struct *sapi_module) ++{ ++ if (php_module_startup(sapi_module, &cgi_module_entry, 1) == FAILURE) { ++ return FAILURE; ++ } ++ return SUCCESS; ++} ++ ++ ++/* {{{ sapi_module_struct cgi_sapi_module ++ */ ++static sapi_module_struct cgi_sapi_module = { ++ "cgi-fcgi", /* name */ ++ "CGI/FastCGI", /* pretty name */ ++ ++ php_cgi_startup, /* startup */ ++ php_module_shutdown_wrapper, /* shutdown */ ++ ++ NULL, /* activate */ ++ sapi_cgi_deactivate, /* deactivate */ ++ ++ sapi_cgibin_ub_write, /* unbuffered write */ ++ sapi_cgibin_flush, /* flush */ ++ NULL, /* get uid */ ++ sapi_cgibin_getenv, /* getenv */ ++ ++ php_error, /* error handler */ ++ ++ NULL, /* header handler */ ++ sapi_cgi_send_headers, /* send headers handler */ ++ NULL, /* send header handler */ ++ ++ sapi_cgi_read_post, /* read POST data */ ++ sapi_cgi_read_cookies, /* read Cookies */ ++ ++ sapi_cgi_register_variables, /* register server variables */ ++ sapi_cgi_log_message, /* Log message */ ++ NULL, /* Get request time */ ++ ++ STANDARD_SAPI_MODULE_PROPERTIES ++}; ++/* }}} */ ++ ++/* {{{ php_cgi_usage ++ */ ++static void php_cgi_usage(char *argv0) ++{ ++ char *prog; ++ ++ prog = strrchr(argv0, '/'); ++ if (prog) { ++ prog++; ++ } else { ++ prog = "php"; ++ } ++ ++ php_printf("Usage: %s [options]\n" ++ "\n" ++ " -C Do not chdir to the script's directory\n" ++ " -c | Look for php.ini file in this directory\n" ++ " -n No php.ini file will be used\n" ++ " -d foo[=bar] Define INI entry foo with value 'bar'\n" ++ " -e Generate extended information for debugger/profiler\n" ++ " -h This help\n" ++ " -i PHP information\n" ++ " -m Show compiled in modules\n" ++ " -v Version number\n" ++ " -y, --fpm-config \n" ++ " Specify alternative path to FastCGI process manager config file.\n" ++ " -z Load Zend extension .\n" ++ , ++ prog); ++} ++/* }}} */ ++ ++/* {{{ is_valid_path ++ * ++ * some server configurations allow '..' to slip through in the ++ * translated path. We'll just refuse to handle such a path. ++ */ ++static int is_valid_path(const char *path) ++{ ++ const char *p; ++ ++ if (!path) { ++ return 0; ++ } ++ p = strstr(path, ".."); ++ if (p) { ++ if ((p == path || IS_SLASH(*(p-1))) && ++ (*(p+2) == 0 || IS_SLASH(*(p+2)))) { ++ return 0; ++ } ++ while (1) { ++ p = strstr(p+1, ".."); ++ if (!p) { ++ break; ++ } ++ if (IS_SLASH(*(p-1)) && ++ (*(p+2) == 0 || IS_SLASH(*(p+2)))) { ++ return 0; ++ } ++ } ++ } ++ return 1; ++} ++/* }}} */ ++ ++/* {{{ init_request_info ++ ++ initializes request_info structure ++ ++ specificly in this section we handle proper translations ++ for: ++ ++ PATH_INFO ++ derived from the portion of the URI path following ++ the script name but preceding any query data ++ may be empty ++ ++ PATH_TRANSLATED ++ derived by taking any path-info component of the ++ request URI and performing any virtual-to-physical ++ translation appropriate to map it onto the server's ++ document repository structure ++ ++ empty if PATH_INFO is empty ++ ++ The env var PATH_TRANSLATED **IS DIFFERENT** than the ++ request_info.path_translated variable, the latter should ++ match SCRIPT_FILENAME instead. ++ ++ SCRIPT_NAME ++ set to a URL path that could identify the CGI script ++ rather than the interpreter. PHP_SELF is set to this. ++ ++ REQUEST_URI ++ uri section following the domain:port part of a URI ++ ++ SCRIPT_FILENAME ++ The virtual-to-physical translation of SCRIPT_NAME (as per ++ PATH_TRANSLATED) ++ ++ These settings are documented at ++ http://cgi-spec.golux.com/ ++ ++ ++ Based on the following URL request: ++ ++ http://localhost/info.php/test?a=b ++ ++ should produce, which btw is the same as if ++ we were running under mod_cgi on apache (ie. not ++ using ScriptAlias directives): ++ ++ PATH_INFO=/test ++ PATH_TRANSLATED=/docroot/test ++ SCRIPT_NAME=/info.php ++ REQUEST_URI=/info.php/test?a=b ++ SCRIPT_FILENAME=/docroot/info.php ++ QUERY_STRING=a=b ++ ++ but what we get is (cgi/mod_fastcgi under apache): ++ ++ PATH_INFO=/info.php/test ++ PATH_TRANSLATED=/docroot/info.php/test ++ SCRIPT_NAME=/php/php-cgi (from the Action setting I suppose) ++ REQUEST_URI=/info.php/test?a=b ++ SCRIPT_FILENAME=/path/to/php/bin/php-cgi (Action setting translated) ++ QUERY_STRING=a=b ++ ++ Comments in the code below refer to using the above URL in a request ++ ++ */ ++static void init_request_info(TSRMLS_D) ++{ ++ char *env_script_filename = sapi_cgibin_getenv("SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME")-1 TSRMLS_CC); ++ char *env_path_translated = sapi_cgibin_getenv("PATH_TRANSLATED", sizeof("PATH_TRANSLATED")-1 TSRMLS_CC); ++ char *script_path_translated = env_script_filename; ++ ++#if !DISCARD_PATH ++ /* some broken servers do not have script_filename or argv0 ++ an example, IIS configured in some ways. then they do more ++ broken stuff and set path_translated to the cgi script location */ ++ if (!script_path_translated && env_path_translated) { ++ script_path_translated = env_path_translated; ++ } ++#endif ++ ++ /* initialize the defaults */ ++ SG(request_info).path_translated = NULL; ++ SG(request_info).request_method = NULL; ++ SG(request_info).proto_num = 1000; ++ SG(request_info).query_string = NULL; ++ SG(request_info).request_uri = NULL; ++ SG(request_info).content_type = NULL; ++ SG(request_info).content_length = 0; ++ SG(sapi_headers).http_response_code = 200; ++ ++ /* script_path_translated being set is a good indication that ++ we are running in a cgi environment, since it is always ++ null otherwise. otherwise, the filename ++ of the script will be retreived later via argc/argv */ ++ if (script_path_translated) { ++ const char *auth; ++ char *content_length = sapi_cgibin_getenv("CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1 TSRMLS_CC); ++ char *content_type = sapi_cgibin_getenv("CONTENT_TYPE", sizeof("CONTENT_TYPE")-1 TSRMLS_CC); ++ char *env_path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO")-1 TSRMLS_CC); ++ char *env_script_name = sapi_cgibin_getenv("SCRIPT_NAME", sizeof("SCRIPT_NAME")-1 TSRMLS_CC); ++#if ENABLE_PATHINFO_CHECK ++ struct stat st; ++ char *env_redirect_url = sapi_cgibin_getenv("REDIRECT_URL", sizeof("REDIRECT_URL")-1 TSRMLS_CC); ++ char *env_document_root = sapi_cgibin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")-1 TSRMLS_CC); ++ int script_path_translated_len; ++ ++ /* Hack for buggy IIS that sets incorrect PATH_INFO */ ++ char *env_server_software = sapi_cgibin_getenv("SERVER_SOFTWARE", sizeof("SERVER_SOFTWARE")-1 TSRMLS_CC); ++ if (env_server_software && ++ env_script_name && ++ env_path_info && ++ strncmp(env_server_software, "Microsoft-IIS", sizeof("Microsoft-IIS")-1) == 0 && ++ strncmp(env_path_info, env_script_name, strlen(env_script_name)) == 0) { ++ env_path_info = _sapi_cgibin_putenv("ORIG_PATH_INFO", env_path_info TSRMLS_CC); ++ env_path_info += strlen(env_script_name); ++ if (*env_path_info == 0) { ++ env_path_info = NULL; ++ } ++ env_path_info = _sapi_cgibin_putenv("PATH_INFO", env_path_info TSRMLS_CC); ++ } ++ ++ if (CGIG(fix_pathinfo)) { ++ char *real_path = NULL; ++ char *orig_path_translated = env_path_translated; ++ char *orig_path_info = env_path_info; ++ char *orig_script_name = env_script_name; ++ char *orig_script_filename = env_script_filename; ++ ++ if (!env_document_root && PG(doc_root)) { ++ env_document_root = _sapi_cgibin_putenv("DOCUMENT_ROOT", PG(doc_root) TSRMLS_CC); ++ /* fix docroot */ ++ TRANSLATE_SLASHES(env_document_root); ++ } ++ ++ if (env_path_translated != NULL && env_redirect_url != NULL) { ++ /* ++ pretty much apache specific. If we have a redirect_url ++ then our script_filename and script_name point to the ++ php executable ++ */ ++ script_path_translated = env_path_translated; ++ /* we correct SCRIPT_NAME now in case we don't have PATH_INFO */ ++ env_script_name = env_redirect_url; ++ } ++ ++#ifdef __riscos__ ++ /* Convert path to unix format*/ ++ __riscosify_control |= __RISCOSIFY_DONT_CHECK_DIR; ++ script_path_translated = __unixify(script_path_translated, 0, NULL, 1, 0); ++#endif ++ ++ /* ++ * if the file doesn't exist, try to extract PATH_INFO out ++ * of it by stat'ing back through the '/' ++ * this fixes url's like /info.php/test ++ */ ++ if (script_path_translated && ++ (script_path_translated_len = strlen(script_path_translated)) > 0 && ++ (script_path_translated[script_path_translated_len-1] == '/' || ++#ifdef PHP_WIN32 ++ script_path_translated[script_path_translated_len-1] == '\\' || ++#endif ++ (real_path = tsrm_realpath(script_path_translated, NULL TSRMLS_CC)) == NULL)) { ++ char *pt = estrndup(script_path_translated, script_path_translated_len); ++ int len = script_path_translated_len; ++ char *ptr; ++ ++ while ((ptr = strrchr(pt, '/')) || (ptr = strrchr(pt, '\\'))) { ++ *ptr = 0; ++ if (stat(pt, &st) == 0 && S_ISREG(st.st_mode)) { ++ /* ++ * okay, we found the base script! ++ * work out how many chars we had to strip off; ++ * then we can modify PATH_INFO ++ * accordingly ++ * ++ * we now have the makings of ++ * PATH_INFO=/test ++ * SCRIPT_FILENAME=/docroot/info.php ++ * ++ * we now need to figure out what docroot is. ++ * if DOCUMENT_ROOT is set, this is easy, otherwise, ++ * we have to play the game of hide and seek to figure ++ * out what SCRIPT_NAME should be ++ */ ++ int slen = len - strlen(pt); ++ int pilen = env_path_info ? strlen(env_path_info) : 0; ++ char *path_info = env_path_info ? env_path_info + pilen - slen : NULL; ++ ++ if (orig_path_info != path_info) { ++ if (orig_path_info) { ++ char old; ++ ++ _sapi_cgibin_putenv("ORIG_PATH_INFO", orig_path_info TSRMLS_CC); ++ old = path_info[0]; ++ path_info[0] = 0; ++ if (!orig_script_name || ++ strcmp(orig_script_name, env_path_info) != 0) { ++ if (orig_script_name) { ++ _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC); ++ } ++ SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_path_info TSRMLS_CC); ++ } else { ++ SG(request_info).request_uri = orig_script_name; ++ } ++ path_info[0] = old; ++ } ++ env_path_info = _sapi_cgibin_putenv("PATH_INFO", path_info TSRMLS_CC); ++ } ++ if (!orig_script_filename || ++ strcmp(orig_script_filename, pt) != 0) { ++ if (orig_script_filename) { ++ _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC); ++ } ++ script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", pt TSRMLS_CC); ++ } ++ TRANSLATE_SLASHES(pt); ++ ++ /* figure out docroot ++ SCRIPT_FILENAME minus SCRIPT_NAME ++ */ ++ ++ if (env_document_root) { ++ int l = strlen(env_document_root); ++ int path_translated_len = 0; ++ char *path_translated = NULL; ++ ++ if (l && env_document_root[l - 1] == '/') { ++ --l; ++ } ++ ++ /* we have docroot, so we should have: ++ * DOCUMENT_ROOT=/docroot ++ * SCRIPT_FILENAME=/docroot/info.php ++ */ ++ ++ /* PATH_TRANSLATED = DOCUMENT_ROOT + PATH_INFO */ ++ path_translated_len = l + (env_path_info ? strlen(env_path_info) : 0); ++ path_translated = (char *) emalloc(path_translated_len + 1); ++ memcpy(path_translated, env_document_root, l); ++ if (env_path_info) { ++ memcpy(path_translated + l, env_path_info, (path_translated_len - l)); ++ } ++ path_translated[path_translated_len] = '\0'; ++ if (orig_path_translated) { ++ _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC); ++ } ++ env_path_translated = _sapi_cgibin_putenv("PATH_TRANSLATED", path_translated TSRMLS_CC); ++ efree(path_translated); ++ } else if (env_script_name && ++ strstr(pt, env_script_name) ++ ) { ++ /* PATH_TRANSLATED = PATH_TRANSLATED - SCRIPT_NAME + PATH_INFO */ ++ int ptlen = strlen(pt) - strlen(env_script_name); ++ int path_translated_len = ptlen + (env_path_info ? strlen(env_path_info) : 0); ++ char *path_translated = NULL; ++ ++ path_translated = (char *) emalloc(path_translated_len + 1); ++ memcpy(path_translated, pt, ptlen); ++ if (env_path_info) { ++ memcpy(path_translated + ptlen, env_path_info, path_translated_len - ptlen); ++ } ++ path_translated[path_translated_len] = '\0'; ++ if (orig_path_translated) { ++ _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC); ++ } ++ env_path_translated = _sapi_cgibin_putenv("PATH_TRANSLATED", path_translated TSRMLS_CC); ++ efree(path_translated); ++ } ++ break; ++ } ++ } ++ if (!ptr) { ++ /* ++ * if we stripped out all the '/' and still didn't find ++ * a valid path... we will fail, badly. of course we would ++ * have failed anyway... we output 'no input file' now. ++ */ ++ if (orig_script_filename) { ++ _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC); ++ } ++ script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", NULL TSRMLS_CC); ++ SG(sapi_headers).http_response_code = 404; ++ } ++ if (!SG(request_info).request_uri) { ++ if (!orig_script_name || ++ strcmp(orig_script_name, env_script_name) != 0) { ++ if (orig_script_name) { ++ _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC); ++ } ++ SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name TSRMLS_CC); ++ } else { ++ SG(request_info).request_uri = orig_script_name; ++ } ++ } ++ if (pt) { ++ efree(pt); ++ } ++ if (is_valid_path(script_path_translated)) { ++ SG(request_info).path_translated = estrdup(script_path_translated); ++ } ++ } else { ++ /* make sure path_info/translated are empty */ ++ if (!orig_script_filename || ++ (script_path_translated != orig_script_filename && ++ strcmp(script_path_translated, orig_script_filename) != 0)) { ++ if (orig_script_filename) { ++ _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC); ++ } ++ script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", script_path_translated TSRMLS_CC); ++ } ++ if (env_redirect_url) { ++ if (orig_path_info) { ++ _sapi_cgibin_putenv("ORIG_PATH_INFO", orig_path_info TSRMLS_CC); ++ _sapi_cgibin_putenv("PATH_INFO", NULL TSRMLS_CC); ++ } ++ if (orig_path_translated) { ++ _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC); ++ _sapi_cgibin_putenv("PATH_TRANSLATED", NULL TSRMLS_CC); ++ } ++ } ++ if (env_script_name != orig_script_name) { ++ if (orig_script_name) { ++ _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC); ++ } ++ SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name TSRMLS_CC); ++ } else { ++ SG(request_info).request_uri = env_script_name; ++ } ++ if (is_valid_path(script_path_translated)) { ++ SG(request_info).path_translated = estrdup(script_path_translated); ++ } ++ free(real_path); ++ } ++ } else { ++#endif ++ /* pre 4.3 behaviour, shouldn't be used but provides BC */ ++ if (env_path_info) { ++ SG(request_info).request_uri = env_path_info; ++ } else { ++ SG(request_info).request_uri = env_script_name; ++ } ++#if !DISCARD_PATH ++ if (env_path_translated) { ++ script_path_translated = env_path_translated; ++ } ++#endif ++ if (is_valid_path(script_path_translated)) { ++ SG(request_info).path_translated = estrdup(script_path_translated); ++ } ++#if ENABLE_PATHINFO_CHECK ++ } ++#endif ++ SG(request_info).request_method = sapi_cgibin_getenv("REQUEST_METHOD", sizeof("REQUEST_METHOD")-1 TSRMLS_CC); ++ /* FIXME - Work out proto_num here */ ++ SG(request_info).query_string = sapi_cgibin_getenv("QUERY_STRING", sizeof("QUERY_STRING")-1 TSRMLS_CC); ++ SG(request_info).content_type = (content_type ? content_type : "" ); ++ SG(request_info).content_length = (content_length ? atoi(content_length) : 0); ++ ++ /* The CGI RFC allows servers to pass on unvalidated Authorization data */ ++ auth = sapi_cgibin_getenv("HTTP_AUTHORIZATION", sizeof("HTTP_AUTHORIZATION")-1 TSRMLS_CC); ++ php_handle_auth_data(auth TSRMLS_CC); ++ } ++} ++/* }}} */ ++ ++ ++PHP_INI_BEGIN() ++ STD_PHP_INI_ENTRY("cgi.rfc2616_headers", "0", PHP_INI_ALL, OnUpdateBool, rfc2616_headers, php_cgi_globals_struct, php_cgi_globals) ++ STD_PHP_INI_ENTRY("cgi.nph", "0", PHP_INI_ALL, OnUpdateBool, nph, php_cgi_globals_struct, php_cgi_globals) ++ STD_PHP_INI_ENTRY("cgi.check_shebang_line", "1", PHP_INI_SYSTEM, OnUpdateBool, check_shebang_line, php_cgi_globals_struct, php_cgi_globals) ++#if ENABLE_PATHINFO_CHECK ++ STD_PHP_INI_ENTRY("cgi.fix_pathinfo", "1", PHP_INI_SYSTEM, OnUpdateBool, fix_pathinfo, php_cgi_globals_struct, php_cgi_globals) ++#endif ++ STD_PHP_INI_ENTRY("fastcgi.logging", "1", PHP_INI_SYSTEM, OnUpdateBool, fcgi_logging, php_cgi_globals_struct, php_cgi_globals) ++# ifdef PHP_WIN32 ++ STD_PHP_INI_ENTRY("fastcgi.impersonate", "0", PHP_INI_SYSTEM, OnUpdateBool, impersonate, php_cgi_globals_struct, php_cgi_globals) ++# endif ++ STD_PHP_INI_ENTRY("fastcgi.error_header", NULL, PHP_INI_SYSTEM, OnUpdateString, error_header, php_cgi_globals_struct, php_cgi_globals) ++PHP_INI_END() ++ ++/* {{{ php_cgi_globals_ctor ++ */ ++static void php_cgi_globals_ctor(php_cgi_globals_struct *php_cgi_globals TSRMLS_DC) ++{ ++ php_cgi_globals->rfc2616_headers = 0; ++ php_cgi_globals->nph = 0; ++ php_cgi_globals->check_shebang_line = 1; ++#if ENABLE_PATHINFO_CHECK ++ php_cgi_globals->fix_pathinfo = 1; ++#endif ++ php_cgi_globals->fcgi_logging = 1; ++# ifdef PHP_WIN32 ++ php_cgi_globals->impersonate = 0; ++# endif ++ php_cgi_globals->error_header = NULL; ++} ++/* }}} */ ++ ++/* {{{ PHP_MINIT_FUNCTION ++ */ ++static PHP_MINIT_FUNCTION(cgi) ++{ ++#ifdef ZTS ++ ts_allocate_id(&php_cgi_globals_id, sizeof(php_cgi_globals_struct), (ts_allocate_ctor) php_cgi_globals_ctor, NULL); ++#else ++ php_cgi_globals_ctor(&php_cgi_globals TSRMLS_CC); ++#endif ++ REGISTER_INI_ENTRIES(); ++ return SUCCESS; ++} ++/* }}} */ ++ ++/* {{{ PHP_MSHUTDOWN_FUNCTION ++ */ ++static PHP_MSHUTDOWN_FUNCTION(cgi) ++{ ++ UNREGISTER_INI_ENTRIES(); ++ return SUCCESS; ++} ++/* }}} */ ++ ++/* {{{ PHP_MINFO_FUNCTION ++ */ ++static PHP_MINFO_FUNCTION(cgi) ++{ ++ DISPLAY_INI_ENTRIES(); ++ ++ php_info_print_table_start(); ++ php_info_print_table_row(2, "php-fpm", "active"); ++ php_info_print_table_row(2, "php-fpm version", PHP_FPM_VERSION); ++ php_info_print_table_end(); ++ ++} ++/* }}} */ ++ ++PHP_FUNCTION(fastcgi_finish_request) ++{ ++ fcgi_request *request = (fcgi_request*) SG(server_context); ++ ++ if (fcgi_is_fastcgi() && request->fd >= 0) { ++ ++ php_end_ob_buffers(1 TSRMLS_CC); ++ php_header(TSRMLS_C); ++ ++ fcgi_flush(request, 1); ++ fcgi_close(request, 0, 0); ++ RETURN_TRUE; ++ } ++ ++ RETURN_FALSE; ++ ++} ++ ++function_entry cgi_fcgi_sapi_functions[] = { ++ PHP_FE(fastcgi_finish_request, NULL) ++ {NULL, NULL, NULL} ++}; ++ ++static zend_module_entry cgi_module_entry = { ++ STANDARD_MODULE_HEADER, ++ "cgi-fcgi", ++ cgi_fcgi_sapi_functions, ++ PHP_MINIT(cgi), ++ PHP_MSHUTDOWN(cgi), ++ NULL, ++ NULL, ++ PHP_MINFO(cgi), ++ NO_VERSION_YET, ++ STANDARD_MODULE_PROPERTIES ++}; ++ ++/* {{{ main ++ */ ++int main(int argc, char *argv[]) ++{ ++ int free_query_string = 0; ++ int exit_status = SUCCESS; ++ int c; ++ zend_file_handle file_handle = {}; ++ int retval; ++/* temporary locals */ ++ int orig_optind = php_optind; ++ char *orig_optarg = php_optarg; ++ int ini_entries_len = 0; ++ ++/* end of temporary locals */ ++#ifdef ZTS ++ void ***tsrm_ls; ++#endif ++ ++ int max_requests = 500; ++ int requests = 0; ++ int fcgi_fd = 0; ++ fcgi_request request; ++ char *fpm_config = NULL; ++ ++#ifdef HAVE_SIGNAL_H ++#if defined(SIGPIPE) && defined(SIG_IGN) ++ signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE in standalone mode so ++ that sockets created via fsockopen() ++ don't kill PHP if the remote site ++ closes it. in apache|apxs mode apache ++ does that for us! thies@thieso.net ++ 20000419 */ ++#endif ++#endif ++ ++#ifdef ZTS ++ tsrm_startup(1, 1, 0, NULL); ++ tsrm_ls = ts_resource(0); ++#endif ++ ++ sapi_startup(&cgi_sapi_module); ++ cgi_sapi_module.php_ini_path_override = NULL; ++ ++#ifdef PHP_WIN32 ++ _fmode = _O_BINARY; /* sets default for file streams to binary */ ++ setmode(_fileno(stdin), O_BINARY); /* make the stdio mode be binary */ ++ setmode(_fileno(stdout), O_BINARY); /* make the stdio mode be binary */ ++ setmode(_fileno(stderr), O_BINARY); /* make the stdio mode be binary */ ++#endif ++ ++ while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0)) != -1) { ++ switch (c) { ++ ++ case 'c': ++ if (cgi_sapi_module.php_ini_path_override) { ++ free(cgi_sapi_module.php_ini_path_override); ++ } ++ cgi_sapi_module.php_ini_path_override = strdup(php_optarg); ++ break; ++ ++ case 'n': ++ cgi_sapi_module.php_ini_ignore = 1; ++ break; ++ ++ case 'C': /* don't chdir to the script directory */ ++ SG(options) |= SAPI_OPTION_NO_CHDIR; ++ break; ++ ++ case 'd': { ++ /* define ini entries on command line */ ++ int len = strlen(php_optarg); ++ char *val; ++ ++ if ((val = strchr(php_optarg, '='))) { ++ val++; ++ if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') { ++ cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\"\"\n\0")); ++ memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, (val - php_optarg)); ++ ini_entries_len += (val - php_optarg); ++ memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"", 1); ++ ini_entries_len++; ++ memcpy(cgi_sapi_module.ini_entries + ini_entries_len, val, len - (val - php_optarg)); ++ ini_entries_len += len - (val - php_optarg); ++ memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"\n\0", sizeof("\"\n\0")); ++ ini_entries_len += sizeof("\n\0\"") - 2; ++ } else { ++ cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\n\0")); ++ memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len); ++ memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "\n\0", sizeof("\n\0")); ++ ini_entries_len += len + sizeof("\n\0") - 2; ++ } ++ } else { ++ cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("=1\n\0")); ++ memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len); ++ memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "=1\n\0", sizeof("=1\n\0")); ++ ini_entries_len += len + sizeof("=1\n\0") - 2; ++ } ++ break; ++ } ++ ++ case 'y': ++ fpm_config = php_optarg; ++ break; ++ ++ case 'e': /* enable extended info output */ ++ /* CG(extended_info) = 1; */ /* 5_2 */ ++ CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO; /* 5_3 */ ++ break; ++ ++ case 'm': /* list compiled in modules */ ++ cgi_sapi_module.startup(&cgi_sapi_module); ++ php_output_startup(); ++ php_output_activate(TSRMLS_C); ++ SG(headers_sent) = 1; ++ php_printf("[PHP Modules]\n"); ++ print_modules(TSRMLS_C); ++ php_printf("\n[Zend Modules]\n"); ++ print_extensions(TSRMLS_C); ++ php_printf("\n"); ++ php_end_ob_buffers(1 TSRMLS_CC); ++ exit_status = 0; ++ goto out; ++ ++ case 'i': /* php info & quit */ ++ cgi_sapi_module.startup(&cgi_sapi_module); ++ if (php_request_startup(TSRMLS_C) == FAILURE) { ++ SG(server_context) = NULL; ++ php_module_shutdown(TSRMLS_C); ++ return FAILURE; ++ } ++ SG(headers_sent) = 1; ++ SG(request_info).no_headers = 1; ++ php_print_info(0xFFFFFFFF TSRMLS_CC); ++ php_request_shutdown((void *) 0); ++ exit_status = 0; ++ goto out; ++ ++ case 'h': ++ case '?': ++ cgi_sapi_module.startup(&cgi_sapi_module); ++ php_output_startup(); ++ php_output_activate(TSRMLS_C); ++ SG(headers_sent) = 1; ++ php_cgi_usage(argv[0]); ++ php_end_ob_buffers(1 TSRMLS_CC); ++ exit_status = 0; ++ goto out; ++ ++ case 'v': /* show php version & quit */ ++ cgi_sapi_module.startup(&cgi_sapi_module); ++ if (php_request_startup(TSRMLS_C) == FAILURE) { ++ SG(server_context) = NULL; ++ php_module_shutdown(TSRMLS_C); ++ return FAILURE; ++ } ++ SG(headers_sent) = 1; ++ SG(request_info).no_headers = 1; ++ ++#if SUHOSIN_PATCH ++#if ZEND_DEBUG ++ php_printf("PHP %s with Suhosin-Patch %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2009 The PHP Group\n%s", PHP_VERSION, SUHOSIN_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++#else ++ php_printf("PHP %s with Suhosin-Patch %s (%s) (built: %s %s)\nCopyright (c) 1997-2009 The PHP Group\n%s", PHP_VERSION, SUHOSIN_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++#endif ++#else ++#if ZEND_DEBUG ++ php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2009 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++#else ++ php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2009 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++#endif ++#endif ++ php_request_shutdown((void *) 0); ++ exit_status = 0; ++ goto out; ++ ++ } ++ ++ } ++ php_optind = orig_optind; ++ php_optarg = orig_optarg; ++ ++#ifdef ZTS ++ SG(request_info).path_translated = NULL; ++#endif ++ ++ cgi_sapi_module.executable_location = argv[0]; ++ ++ /* startup after we get the above ini override se we get things right */ ++ if (cgi_sapi_module.startup(&cgi_sapi_module) == FAILURE) { ++#ifdef ZTS ++ tsrm_shutdown(); ++#endif ++ return FAILURE; ++ } ++ ++ if (0 > fpm_init(argc, argv, fpm_config)) { ++ return FAILURE; ++ } ++ ++ fcgi_fd = fpm_run(&max_requests); ++ ++ parent = 0; ++ ++ fcgi_set_is_fastcgi(1); ++ ++ /* make php call us to get _ENV vars */ ++ php_php_import_environment_variables = php_import_environment_variables; ++ php_import_environment_variables = cgi_php_import_environment_variables; ++ ++ /* library is already initialized, now init our request */ ++ fcgi_init_request(&request, fcgi_fd); ++ ++ zend_first_try { ++ ++ /* start of FAST CGI loop */ ++ /* Initialise FastCGI request structure */ ++#ifdef PHP_WIN32 ++ /* attempt to set security impersonation for fastcgi ++ will only happen on NT based OS, others will ignore it. */ ++ if (fastcgi && CGIG(impersonate)) { ++ fcgi_impersonate(); ++ } ++#endif ++ while (fcgi_accept_request(&request) >= 0) { ++ ++ request_body_fd = -1; ++ ++ SG(server_context) = (void *) &request; ++ ++ init_request_info(TSRMLS_C); ++ ++ CG(interactive) = 0; ++ ++ fpm_request_info(); ++ ++ /* ++ we never take stdin if we're (f)cgi, always ++ rely on the web server giving us the info ++ we need in the environment. ++ */ ++ if (SG(request_info).path_translated) { ++ file_handle.type = ZEND_HANDLE_FILENAME; ++ file_handle.filename = SG(request_info).path_translated; ++ file_handle.handle.fp = NULL; ++ } ++ file_handle.opened_path = NULL; ++ file_handle.free_filename = 0; ++ ++ /* request startup only after we've done all we can to ++ get path_translated */ ++ if (php_request_startup(TSRMLS_C) == FAILURE) { ++ fcgi_finish_request(&request); ++ SG(server_context) = NULL; ++ php_module_shutdown(TSRMLS_C); ++ return FAILURE; ++ } ++ ++ /* ++ at this point path_translated will be set if: ++ 1. we are running from shell and got filename was there ++ 2. we are running as cgi or fastcgi ++ */ ++ retval = FAILURE; ++ if (SG(request_info).path_translated) { ++ if (!php_check_open_basedir(SG(request_info).path_translated TSRMLS_CC)) { ++ retval = php_fopen_primary_script(&file_handle TSRMLS_CC); ++ } ++ } ++ /* ++ if we are unable to open path_translated and we are not ++ running from shell (so fp == NULL), then fail. ++ */ ++ if (retval == FAILURE && file_handle.handle.fp == NULL) { ++ if (errno == EACCES) { ++ SG(sapi_headers).http_response_code = 403; ++ PUTS("Access denied.\n"); ++ } else { ++ SG(sapi_headers).http_response_code = 404; ++ PUTS("No input file specified.\n"); ++ } ++ /* we want to serve more requests if this is fastcgi ++ so cleanup and continue, request shutdown is ++ handled later */ ++ goto fastcgi_request_done; ++ ++ STR_FREE(SG(request_info).path_translated); ++ ++ if (free_query_string && SG(request_info).query_string) { ++ free(SG(request_info).query_string); ++ SG(request_info).query_string = NULL; ++ } ++ ++ php_request_shutdown((void *) 0); ++ SG(server_context) = NULL; ++ php_module_shutdown(TSRMLS_C); ++ sapi_shutdown(); ++#ifdef ZTS ++ tsrm_shutdown(); ++#endif ++ return FAILURE; ++ } ++ ++ fpm_request_executing(); ++ ++ php_execute_script(&file_handle TSRMLS_CC); ++ ++fastcgi_request_done: ++ ++ if (request_body_fd != -1) close(request_body_fd); ++ ++ request_body_fd = -2; ++ ++ { ++ char *path_translated; ++ ++ /* Go through this trouble so that the memory manager doesn't warn ++ * about SG(request_info).path_translated leaking ++ */ ++ if (SG(request_info).path_translated) { ++ path_translated = strdup(SG(request_info).path_translated); ++ STR_FREE(SG(request_info).path_translated); ++ SG(request_info).path_translated = path_translated; ++ } ++ ++ if (EG(exit_status) == 255) { ++ if (CGIG(error_header) && *CGIG(error_header)) { ++ sapi_header_line ctr = {0}; ++ ++ ctr.line = CGIG(error_header); ++ ctr.line_len = strlen(CGIG(error_header)); ++ sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC); ++ } ++ } ++ ++ php_request_shutdown((void *) 0); ++ if (exit_status == 0) { ++ exit_status = EG(exit_status); ++ } ++ ++ if (SG(request_info).path_translated) { ++ free(SG(request_info).path_translated); ++ SG(request_info).path_translated = NULL; ++ } ++ if (free_query_string && SG(request_info).query_string) { ++ free(SG(request_info).query_string); ++ SG(request_info).query_string = NULL; ++ } ++ ++ } ++ ++ requests++; ++ if (max_requests && (requests == max_requests)) { ++ fcgi_finish_request(&request); ++ break; ++ } ++ ++ /* end of fastcgi loop */ ++ } ++ ++ fcgi_shutdown(); ++ ++ if (fcgi_in_shutdown() || /* graceful shutdown by a signal */ ++ (max_requests && (requests == max_requests)) /* we were told to process max_requests and we are done */ ++ ) { ++ exit_status = 0; ++ } ++ else { ++ exit_status = 255; ++ } ++ ++ if (cgi_sapi_module.php_ini_path_override) { ++ free(cgi_sapi_module.php_ini_path_override); ++ } ++ if (cgi_sapi_module.ini_entries) { ++ free(cgi_sapi_module.ini_entries); ++ } ++ } zend_catch { ++ exit_status = 255; ++ } zend_end_try(); ++ ++out: ++ ++ SG(server_context) = NULL; ++ php_module_shutdown(TSRMLS_C); ++ sapi_shutdown(); ++ ++#ifdef ZTS ++ /*tsrm_shutdown();*/ ++#endif ++ ++#if defined(PHP_WIN32) && ZEND_DEBUG && 0 ++ _CrtDumpMemoryLeaks(); ++#endif ++ ++ return exit_status; ++} ++/* }}} */ ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * End: ++ * vim600: sw=4 ts=4 fdm=marker ++ * vim<600: sw=4 ts=4 ++ */ +diff -Naur php-src-vanilla/sapi/fpm/cgi/CREDITS php-src/sapi/fpm/cgi/CREDITS +--- php-src-vanilla/sapi/fpm/cgi/CREDITS 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/cgi/CREDITS 2009-10-18 21:05:39.302497288 +0100 +@@ -0,0 +1,2 @@ ++CGI / FastCGI ++Rasmus Lerdorf, Stig Bakken, Shane Caraveo, Dmitry Stogov +diff -Naur php-src-vanilla/sapi/fpm/cgi/fastcgi.c php-src/sapi/fpm/cgi/fastcgi.c +--- php-src-vanilla/sapi/fpm/cgi/fastcgi.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/cgi/fastcgi.c 2009-10-18 21:05:39.302497288 +0100 +@@ -0,0 +1,1319 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | PHP Version 5 | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 1997-2008 The PHP Group | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 3.01 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available through the world-wide-web at the following url: | ++ | http://www.php.net/license/3_01.txt | ++ | If you did not receive a copy of the PHP license and are unable to | ++ | obtain it through the world-wide-web, please send a note to | ++ | license@php.net so we can mail you a copy immediately. | ++ +----------------------------------------------------------------------+ ++ | Authors: Dmitry Stogov | ++ +----------------------------------------------------------------------+ ++*/ ++ ++/* $Id$ */ ++ ++#include ++#include "fastcgi.h" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef FPM_AUTOCONFIG_H ++#include ++#else ++#include ++#endif ++#include ++#include ++ ++#ifdef _WIN32 ++ ++#include ++ ++ typedef unsigned int in_addr_t; ++ ++ struct sockaddr_un { ++ short sun_family; ++ char sun_path[MAXPATHLEN]; ++ }; ++ ++ static HANDLE fcgi_accept_mutex = INVALID_HANDLE_VALUE; ++ static int is_impersonate = 0; ++ ++#define FCGI_LOCK(fd) \ ++ if (fcgi_accept_mutex != INVALID_HANDLE_VALUE) { \ ++ DWORD ret; \ ++ while ((ret = WaitForSingleObject(fcgi_accept_mutex, 1000)) == WAIT_TIMEOUT) { \ ++ if (in_shutdown) return -1; \ ++ } \ ++ if (ret == WAIT_FAILED) { \ ++ fprintf(stderr, "WaitForSingleObject() failed\n"); \ ++ return -1; \ ++ } \ ++ } ++ ++#define FCGI_UNLOCK(fd) \ ++ if (fcgi_accept_mutex != INVALID_HANDLE_VALUE) { \ ++ ReleaseMutex(fcgi_accept_mutex); \ ++ } ++ ++#else ++ ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++# include ++ ++# define closesocket(s) close(s) ++ ++# if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL) ++# include ++# endif ++# if defined(HAVE_SYS_SELECT_H) ++# include ++# endif ++ ++#ifndef INADDR_NONE ++#define INADDR_NONE ((unsigned long) -1) ++#endif ++ ++# ifndef HAVE_SOCKLEN_T ++ typedef unsigned int socklen_t; ++# endif ++ ++# ifdef USE_LOCKING ++# define FCGI_LOCK(fd) \ ++ do { \ ++ struct flock lock; \ ++ lock.l_type = F_WRLCK; \ ++ lock.l_start = 0; \ ++ lock.l_whence = SEEK_SET; \ ++ lock.l_len = 0; \ ++ if (fcntl(fd, F_SETLKW, &lock) != -1) { \ ++ break; \ ++ } else if (errno != EINTR || in_shutdown) { \ ++ return -1; \ ++ } \ ++ } while (1) ++ ++# define FCGI_UNLOCK(fd) \ ++ do { \ ++ int orig_errno = errno; \ ++ while (1) { \ ++ struct flock lock; \ ++ lock.l_type = F_UNLCK; \ ++ lock.l_start = 0; \ ++ lock.l_whence = SEEK_SET; \ ++ lock.l_len = 0; \ ++ if (fcntl(fd, F_SETLK, &lock) != -1) { \ ++ break; \ ++ } else if (errno != EINTR) { \ ++ return -1; \ ++ } \ ++ } \ ++ errno = orig_errno; \ ++ } while (0) ++# else ++# define FCGI_LOCK(fd) ++# define FCGI_UNLOCK(fd) ++# endif ++ ++#endif ++ ++typedef union _sa_t { ++ struct sockaddr sa; ++ struct sockaddr_un sa_unix; ++ struct sockaddr_in sa_inet; ++} sa_t; ++ ++static HashTable *fcgi_mgmt_vars; ++ ++static int is_initialized = 0; ++static int is_fastcgi = 0; ++static int in_shutdown = 0; ++static in_addr_t *allowed_clients = NULL; ++ ++#ifdef _WIN32 ++ ++static DWORD WINAPI fcgi_shutdown_thread(LPVOID arg) ++{ ++ HANDLE shutdown_event = (HANDLE) arg; ++ WaitForSingleObject(shutdown_event, INFINITE); ++ in_shutdown = 1; ++ return 0; ++} ++ ++#else ++ ++static void fcgi_signal_handler(int signo) ++{ ++ if (signo == SIGUSR1 || signo == SIGTERM) { ++ in_shutdown = 1; ++ } ++} ++ ++static void fcgi_setup_signals(void) ++{ ++ struct sigaction new_sa, old_sa; ++ ++ sigemptyset(&new_sa.sa_mask); ++ new_sa.sa_flags = 0; ++ new_sa.sa_handler = fcgi_signal_handler; ++ sigaction(SIGUSR1, &new_sa, NULL); ++ sigaction(SIGTERM, &new_sa, NULL); ++ sigaction(SIGPIPE, NULL, &old_sa); ++ if (old_sa.sa_handler == SIG_DFL) { ++ sigaction(SIGPIPE, &new_sa, NULL); ++ } ++} ++#endif ++ ++int fcgi_in_shutdown(void) ++{ ++ return in_shutdown; ++} ++ ++int fcgi_init(void) ++{ ++ if (!is_initialized) { ++ fcgi_mgmt_vars = pemalloc(sizeof(HashTable), 1); ++ zend_hash_init(fcgi_mgmt_vars, 3, NULL, fcgi_free_mgmt_var_cb, 1); ++ fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, "1", sizeof("1")-1); ++ fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, "1", sizeof("1")-1); ++ fcgi_set_mgmt_var("FCGI_MPXS_CONNS", sizeof("FCGI_MPXS_CONNS")-1, "0", sizeof("0")-1); ++#ifdef _WIN32 ++# if 0 ++ /* TODO: Support for TCP sockets */ ++ WSADATA wsaData; ++ ++ if (WSAStartup(MAKEWORD(2,0), &wsaData)) { ++ fprintf(stderr, "Error starting Windows Sockets. Error: %d", WSAGetLastError()); ++ return 0; ++ } ++# endif ++ is_initialized = 1; ++ ++ if ((GetStdHandle(STD_OUTPUT_HANDLE) == INVALID_HANDLE_VALUE) && ++ (GetStdHandle(STD_ERROR_HANDLE) == INVALID_HANDLE_VALUE) && ++ (GetStdHandle(STD_INPUT_HANDLE) != INVALID_HANDLE_VALUE)) { ++ char *str; ++ DWORD pipe_mode = PIPE_READMODE_BYTE | PIPE_WAIT; ++ HANDLE pipe = GetStdHandle(STD_INPUT_HANDLE); ++ ++ SetNamedPipeHandleState(pipe, &pipe_mode, NULL, NULL); ++ ++ str = getenv("_FCGI_SHUTDOWN_EVENT_"); ++ if (str != NULL) { ++ HANDLE shutdown_event = (HANDLE) atoi(str); ++ if (!CreateThread(NULL, 0, fcgi_shutdown_thread, ++ shutdown_event, 0, NULL)) { ++ return -1; ++ } ++ } ++ str = getenv("_FCGI_MUTEX_"); ++ if (str != NULL) { ++ fcgi_accept_mutex = (HANDLE) atoi(str); ++ } ++ return is_fastcgi = 1; ++ } else { ++ return is_fastcgi = 0; ++ } ++#else ++ sa_t sa; ++ socklen_t len = sizeof(sa); ++ ++ is_initialized = 1; ++ errno = 0; ++ if (getpeername(0, (struct sockaddr *)&sa, &len) != 0 && errno == ENOTCONN) { ++ fcgi_setup_signals(); ++ return is_fastcgi = 1; ++ } else { ++ return is_fastcgi = 0; ++ } ++ ++ fcgi_set_allowed_clients(getenv("FCGI_WEB_SERVER_ADDRS")); ++#endif ++ } ++ return is_fastcgi; ++} ++ ++ ++int fcgi_is_fastcgi(void) ++{ ++ if (!is_initialized) { ++ return fcgi_init(); ++ } else { ++ return is_fastcgi; ++ } ++} ++ ++void fcgi_set_is_fastcgi(int new_value) ++{ ++ is_fastcgi = new_value; ++} ++ ++void fcgi_set_in_shutdown(int new_value) ++{ ++ in_shutdown = new_value; ++} ++ ++void fcgi_shutdown(void) ++{ ++ if (is_initialized) { ++ zend_hash_destroy(fcgi_mgmt_vars); ++ pefree(fcgi_mgmt_vars, 1); ++ } ++ is_fastcgi = 0; ++ ++ if (allowed_clients) { ++ free(allowed_clients); ++ allowed_clients = 0; ++ } ++} ++ ++#ifdef _WIN32 ++/* Do some black magic with the NT security API. ++ * We prepare a DACL (Discretionary Access Control List) so that ++ * we, the creator, are allowed all access, while "Everyone Else" ++ * is only allowed to read and write to the pipe. ++ * This avoids security issues on shared hosts where a luser messes ++ * with the lower-level pipe settings and screws up the FastCGI service. ++ */ ++static PACL prepare_named_pipe_acl(PSECURITY_DESCRIPTOR sd, LPSECURITY_ATTRIBUTES sa) ++{ ++ DWORD req_acl_size; ++ char everyone_buf[32], owner_buf[32]; ++ PSID sid_everyone, sid_owner; ++ SID_IDENTIFIER_AUTHORITY ++ siaWorld = SECURITY_WORLD_SID_AUTHORITY, ++ siaCreator = SECURITY_CREATOR_SID_AUTHORITY; ++ PACL acl; ++ ++ sid_everyone = (PSID)&everyone_buf; ++ sid_owner = (PSID)&owner_buf; ++ ++ req_acl_size = sizeof(ACL) + ++ (2 * ((sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) + GetSidLengthRequired(1))); ++ ++ acl = malloc(req_acl_size); ++ ++ if (acl == NULL) { ++ return NULL; ++ } ++ ++ if (!InitializeSid(sid_everyone, &siaWorld, 1)) { ++ goto out_fail; ++ } ++ *GetSidSubAuthority(sid_everyone, 0) = SECURITY_WORLD_RID; ++ ++ if (!InitializeSid(sid_owner, &siaCreator, 1)) { ++ goto out_fail; ++ } ++ *GetSidSubAuthority(sid_owner, 0) = SECURITY_CREATOR_OWNER_RID; ++ ++ if (!InitializeAcl(acl, req_acl_size, ACL_REVISION)) { ++ goto out_fail; ++ } ++ ++ if (!AddAccessAllowedAce(acl, ACL_REVISION, FILE_GENERIC_READ | FILE_GENERIC_WRITE, sid_everyone)) { ++ goto out_fail; ++ } ++ ++ if (!AddAccessAllowedAce(acl, ACL_REVISION, FILE_ALL_ACCESS, sid_owner)) { ++ goto out_fail; ++ } ++ ++ if (!InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION)) { ++ goto out_fail; ++ } ++ ++ if (!SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE)) { ++ goto out_fail; ++ } ++ ++ sa->lpSecurityDescriptor = sd; ++ ++ return acl; ++ ++out_fail: ++ free(acl); ++ return NULL; ++} ++#endif ++ ++void fcgi_set_allowed_clients(char *ip) ++{ ++ char *cur, *end; ++ int n; ++ ++ if (ip) { ++ ip = strdup(ip); ++ cur = ip; ++ n = 0; ++ while (*cur) { ++ if (*cur == ',') n++; ++ cur++; ++ } ++ if (allowed_clients) free(allowed_clients); ++ allowed_clients = malloc(sizeof(in_addr_t) * (n+2)); ++ n = 0; ++ cur = ip; ++ while (cur) { ++ end = strchr(cur, ','); ++ if (end) { ++ *end = 0; ++ end++; ++ } ++ allowed_clients[n] = inet_addr(cur); ++ if (allowed_clients[n] == INADDR_NONE) { ++ fprintf(stderr, "Wrong IP address '%s' in FCGI_WEB_SERVER_ADDRS\n", cur); ++ } ++ n++; ++ cur = end; ++ } ++ allowed_clients[n] = INADDR_NONE; ++ free(ip); ++ } ++} ++ ++static int is_port_number(const char *bindpath) ++{ ++ while (*bindpath) { ++ if (*bindpath < '0' || *bindpath > '9') { ++ return 0; ++ } ++ bindpath++; ++ } ++ return 1; ++} ++ ++int fcgi_listen(const char *path, int backlog) ++{ ++ char *s; ++ int tcp = 0; ++ char host[MAXPATHLEN]; ++ short port = 0; ++ int listen_socket; ++ sa_t sa; ++ socklen_t sock_len; ++#ifdef SO_REUSEADDR ++# ifdef _WIN32 ++ BOOL reuse = 1; ++# else ++ int reuse = 1; ++# endif ++#endif ++ ++ if ((s = strchr(path, ':'))) { ++ port = atoi(s+1); ++ if (port != 0 && (s-path) < MAXPATHLEN) { ++ strncpy(host, path, s-path); ++ host[s-path] = '\0'; ++ tcp = 1; ++ } ++ } else if (is_port_number(path)) { ++ port = atoi(path); ++ if (port != 0) { ++ host[0] = '\0'; ++ tcp = 1; ++ } ++ } ++ ++ /* Prepare socket address */ ++ if (tcp) { ++ memset(&sa.sa_inet, 0, sizeof(sa.sa_inet)); ++ sa.sa_inet.sin_family = AF_INET; ++ sa.sa_inet.sin_port = htons(port); ++ sock_len = sizeof(sa.sa_inet); ++ ++ if (!*host || !strncmp(host, "*", sizeof("*")-1)) { ++ sa.sa_inet.sin_addr.s_addr = htonl(INADDR_ANY); ++ } else { ++ sa.sa_inet.sin_addr.s_addr = inet_addr(host); ++ if (sa.sa_inet.sin_addr.s_addr == INADDR_NONE) { ++ struct hostent *hep; ++ ++ hep = gethostbyname(host); ++ if (!hep || hep->h_addrtype != AF_INET || !hep->h_addr_list[0]) { ++ fprintf(stderr, "Cannot resolve host name '%s'!\n", host); ++ return -1; ++ } else if (hep->h_addr_list[1]) { ++ fprintf(stderr, "Host '%s' has multiple addresses. You must choose one explicitly!\n", host); ++ return -1; ++ } ++ sa.sa_inet.sin_addr.s_addr = ((struct in_addr*)hep->h_addr_list[0])->s_addr; ++ } ++ } ++ } else { ++#ifdef _WIN32 ++ SECURITY_DESCRIPTOR sd; ++ SECURITY_ATTRIBUTES sa; ++ PACL acl; ++ HANDLE namedPipe; ++ ++ memset(&sa, 0, sizeof(sa)); ++ sa.nLength = sizeof(sa); ++ sa.bInheritHandle = FALSE; ++ acl = prepare_named_pipe_acl(&sd, &sa); ++ ++ namedPipe = CreateNamedPipe(path, ++ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, ++ PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_READMODE_BYTE, ++ PIPE_UNLIMITED_INSTANCES, ++ 8192, 8192, 0, &sa); ++ if (namedPipe == INVALID_HANDLE_VALUE) { ++ return -1; ++ } ++ listen_socket = _open_osfhandle((long)namedPipe, 0); ++ if (!is_initialized) { ++ fcgi_init(); ++ } ++ is_fastcgi = 1; ++ return listen_socket; ++ ++#else ++ int path_len = strlen(path); ++ ++ if (path_len >= sizeof(sa.sa_unix.sun_path)) { ++ fprintf(stderr, "Listening socket's path name is too long.\n"); ++ return -1; ++ } ++ ++ memset(&sa.sa_unix, 0, sizeof(sa.sa_unix)); ++ sa.sa_unix.sun_family = AF_UNIX; ++ memcpy(sa.sa_unix.sun_path, path, path_len + 1); ++ sock_len = (size_t)(((struct sockaddr_un *)0)->sun_path) + path_len; ++#ifdef HAVE_SOCKADDR_UN_SUN_LEN ++ sa.sa_unix.sun_len = sock_len; ++#endif ++ unlink(path); ++#endif ++ } ++ ++ /* Create, bind socket and start listen on it */ ++ if ((listen_socket = socket(sa.sa.sa_family, SOCK_STREAM, 0)) < 0 || ++#ifdef SO_REUSEADDR ++ setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)) < 0 || ++#endif ++ bind(listen_socket, (struct sockaddr *) &sa, sock_len) < 0 || ++ listen(listen_socket, backlog) < 0) { ++ ++ fprintf(stderr, "Cannot bind/listen socket - [%d] %s.\n",errno, strerror(errno)); ++ return -1; ++ } ++ ++ if (!tcp) { ++ chmod(path, 0777); ++ } ++ ++ if (!is_initialized) { ++ fcgi_init(); ++ } ++ is_fastcgi = 1; ++ ++#ifdef _WIN32 ++ if (tcp) { ++ listen_socket = _open_osfhandle((long)listen_socket, 0); ++ } ++#else ++ fcgi_setup_signals(); ++#endif ++ return listen_socket; ++} ++ ++void fcgi_init_request(fcgi_request *req, int listen_socket) ++{ ++ memset(req, 0, sizeof(fcgi_request)); ++ req->listen_socket = listen_socket; ++ req->fd = -1; ++ req->id = -1; ++ ++ req->in_len = 0; ++ req->in_pad = 0; ++ ++ req->out_hdr = NULL; ++ req->out_pos = req->out_buf; ++ ++#ifdef _WIN32 ++ req->tcp = !GetNamedPipeInfo((HANDLE)_get_osfhandle(req->listen_socket), NULL, NULL, NULL, NULL); ++#endif ++} ++ ++static inline ssize_t safe_write(fcgi_request *req, const void *buf, size_t count) ++{ ++ int ret; ++ size_t n = 0; ++ ++ do { ++ errno = 0; ++#ifdef _WIN32 ++ if (!req->tcp) { ++ ret = write(req->fd, ((char*)buf)+n, count-n); ++ } else { ++ ret = send(req->fd, ((char*)buf)+n, count-n, 0); ++ if (ret <= 0) { ++ errno = WSAGetLastError(); ++ } ++ } ++#else ++ ret = write(req->fd, ((char*)buf)+n, count-n); ++#endif ++ if (ret > 0) { ++ n += ret; ++ } else if (ret <= 0 && errno != 0 && errno != EINTR) { ++ return ret; ++ } ++ } while (n != count); ++ return n; ++} ++ ++static inline ssize_t safe_read(fcgi_request *req, const void *buf, size_t count) ++{ ++ int ret; ++ size_t n = 0; ++ ++ do { ++ errno = 0; ++#ifdef _WIN32 ++ if (!req->tcp) { ++ ret = read(req->fd, ((char*)buf)+n, count-n); ++ } else { ++ ret = recv(req->fd, ((char*)buf)+n, count-n, 0); ++ if (ret <= 0) { ++ errno = WSAGetLastError(); ++ } ++ } ++#else ++ ret = read(req->fd, ((char*)buf)+n, count-n); ++#endif ++ if (ret > 0) { ++ n += ret; ++ } else if (ret == 0 && errno == 0) { ++ return n; ++ } else if (ret <= 0 && errno != 0 && errno != EINTR) { ++ return ret; ++ } ++ } while (n != count); ++ return n; ++} ++ ++static inline int fcgi_make_header(fcgi_header *hdr, fcgi_request_type type, int req_id, int len) ++{ ++ int pad = ((len + 7) & ~7) - len; ++ ++ hdr->contentLengthB0 = (unsigned char)(len & 0xff); ++ hdr->contentLengthB1 = (unsigned char)((len >> 8) & 0xff); ++ hdr->paddingLength = (unsigned char)pad; ++ hdr->requestIdB0 = (unsigned char)(req_id & 0xff); ++ hdr->requestIdB1 = (unsigned char)((req_id >> 8) & 0xff); ++ hdr->reserved = 0; ++ hdr->type = type; ++ hdr->version = FCGI_VERSION_1; ++ if (pad) { ++ memset(((unsigned char*)hdr) + sizeof(fcgi_header) + len, 0, pad); ++ } ++ return pad; ++} ++ ++static int fcgi_get_params(fcgi_request *req, unsigned char *p, unsigned char *end) ++{ ++ char buf[128]; ++ char *tmp = buf; ++ int buf_size = sizeof(buf); ++ int name_len, val_len; ++ char *s; ++ int ret = 1; ++ ++ while (p < end) { ++ name_len = *p++; ++ if (name_len >= 128) { ++ name_len = ((name_len & 0x7f) << 24); ++ name_len |= (*p++ << 16); ++ name_len |= (*p++ << 8); ++ name_len |= *p++; ++ } ++ val_len = *p++; ++ if (val_len >= 128) { ++ val_len = ((val_len & 0x7f) << 24); ++ val_len |= (*p++ << 16); ++ val_len |= (*p++ << 8); ++ val_len |= *p++; ++ } ++ if (name_len + val_len < 0 || ++ name_len + val_len > end - p) { ++ /* Malformated request */ ++ ret = 0; ++ break; ++ } ++ if (name_len+1 >= buf_size) { ++ buf_size = name_len + 64; ++ tmp = (tmp == buf ? emalloc(buf_size): erealloc(tmp, buf_size)); ++ } ++ memcpy(tmp, p, name_len); ++ tmp[name_len] = 0; ++ s = zend_strndup((char*)p + name_len, val_len); ++ zend_hash_update(&req->env, tmp, name_len+1, &s, sizeof(char*), NULL); ++ p += name_len + val_len; ++ } ++ if (tmp != buf && tmp != NULL) { ++ efree(tmp); ++ } ++ return ret; ++} ++ ++static void fcgi_free_var(char **s) ++{ ++ free(*s); ++} ++ ++static int fcgi_read_request(fcgi_request *req) ++{ ++ fcgi_header hdr; ++ int len, padding; ++ unsigned char buf[FCGI_MAX_LENGTH+8]; ++ ++ req->keep = 0; ++ req->in_len = 0; ++ req->out_hdr = NULL; ++ req->out_pos = req->out_buf; ++ zend_hash_init(&req->env, 0, NULL, (void (*)(void *)) fcgi_free_var, 1); ++ ++ if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || ++ hdr.version < FCGI_VERSION_1) { ++ return 0; ++ } ++ ++ len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; ++ padding = hdr.paddingLength; ++ ++ while (hdr.type == FCGI_STDIN && len == 0) { ++ if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || ++ hdr.version < FCGI_VERSION_1) { ++ return 0; ++ } ++ ++ len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; ++ padding = hdr.paddingLength; ++ } ++ ++ if (len + padding > FCGI_MAX_LENGTH) { ++ return 0; ++ } ++ ++ req->id = (hdr.requestIdB1 << 8) + hdr.requestIdB0; ++ ++ if (hdr.type == FCGI_BEGIN_REQUEST && len == sizeof(fcgi_begin_request)) { ++ char *val; ++ ++ if (safe_read(req, buf, len+padding) != len+padding) { ++ return 0; ++ } ++ ++ req->keep = (((fcgi_begin_request*)buf)->flags & FCGI_KEEP_CONN); ++ switch ((((fcgi_begin_request*)buf)->roleB1 << 8) + ((fcgi_begin_request*)buf)->roleB0) { ++ case FCGI_RESPONDER: ++ val = strdup("RESPONDER"); ++ zend_hash_update(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); ++ break; ++ case FCGI_AUTHORIZER: ++ val = strdup("AUTHORIZER"); ++ zend_hash_update(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); ++ break; ++ case FCGI_FILTER: ++ val = strdup("FILTER"); ++ zend_hash_update(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); ++ break; ++ default: ++ return 0; ++ } ++ ++ if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || ++ hdr.version < FCGI_VERSION_1) { ++ return 0; ++ } ++ ++ len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; ++ padding = hdr.paddingLength; ++ ++ while (hdr.type == FCGI_PARAMS && len > 0) { ++ if (len + padding > FCGI_MAX_LENGTH) { ++ return 0; ++ } ++ ++ if (safe_read(req, buf, len+padding) != len+padding) { ++ req->keep = 0; ++ return 0; ++ } ++ ++ if (!fcgi_get_params(req, buf, buf+len)) { ++ req->keep = 0; ++ return 0; ++ } ++ ++ if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || ++ hdr.version < FCGI_VERSION_1) { ++ req->keep = 0; ++ return 0; ++ } ++ len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; ++ padding = hdr.paddingLength; ++ } ++ } else if (hdr.type == FCGI_GET_VALUES) { ++ unsigned char *p = buf + sizeof(fcgi_header); ++ HashPosition pos; ++ char * str_index; ++ uint str_length; ++ ulong num_index; ++ int key_type; ++ zval ** value; ++ ++ if (safe_read(req, buf, len+padding) != len+padding) { ++ req->keep = 0; ++ return 0; ++ } ++ ++ if (!fcgi_get_params(req, buf, buf+len)) { ++ req->keep = 0; ++ return 0; ++ } ++ ++ zend_hash_internal_pointer_reset_ex(&req->env, &pos); ++ while ((key_type = zend_hash_get_current_key_ex(&req->env, &str_index, &str_length, &num_index, 0, &pos)) != HASH_KEY_NON_EXISTANT) { ++ int zlen; ++ zend_hash_move_forward_ex(&req->env, &pos); ++ if (key_type != HASH_KEY_IS_STRING) { ++ continue; ++ } ++ if (zend_hash_find(fcgi_mgmt_vars, str_index, str_length, (void**) &value) != SUCCESS) { ++ continue; ++ } ++ --str_length; ++ zlen = Z_STRLEN_PP(value); ++ if ((p + 4 + 4 + str_length + zlen) >= (buf + sizeof(buf))) { ++ break; ++ } ++ if (str_length < 0x80) { ++ *p++ = str_length; ++ } else { ++ *p++ = ((str_length >> 24) & 0xff) | 0x80; ++ *p++ = (str_length >> 16) & 0xff; ++ *p++ = (str_length >> 8) & 0xff; ++ *p++ = str_length & 0xff; ++ } ++ if (zlen < 0x80) { ++ *p++ = zlen; ++ } else { ++ *p++ = ((zlen >> 24) & 0xff) | 0x80; ++ *p++ = (zlen >> 16) & 0xff; ++ *p++ = (zlen >> 8) & 0xff; ++ *p++ = zlen & 0xff; ++ } ++ memcpy(p, str_index, str_length); ++ p += str_length; ++ memcpy(p, Z_STRVAL_PP(value), zlen); ++ p += zlen; ++ } ++ len = p - buf - sizeof(fcgi_header); ++ len += fcgi_make_header((fcgi_header*)buf, FCGI_GET_VALUES_RESULT, 0, len); ++ if (safe_write(req, buf, sizeof(fcgi_header)+len) != (int)sizeof(fcgi_header)+len) { ++ req->keep = 0; ++ return 0; ++ } ++ return 0; ++ } else { ++ return 0; ++ } ++ ++ return 1; ++} ++ ++int fcgi_read(fcgi_request *req, char *str, int len) ++{ ++ int ret, n, rest; ++ fcgi_header hdr; ++ unsigned char buf[255]; ++ ++ n = 0; ++ rest = len; ++ while (rest > 0) { ++ if (req->in_len == 0) { ++ if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || ++ hdr.version < FCGI_VERSION_1 || ++ hdr.type != FCGI_STDIN) { ++ req->keep = 0; ++ return 0; ++ } ++ req->in_len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; ++ req->in_pad = hdr.paddingLength; ++ if (req->in_len == 0) { ++ return n; ++ } ++ } ++ ++ if (req->in_len >= rest) { ++ ret = safe_read(req, str, rest); ++ } else { ++ ret = safe_read(req, str, req->in_len); ++ } ++ if (ret < 0) { ++ req->keep = 0; ++ return ret; ++ } else if (ret > 0) { ++ req->in_len -= ret; ++ rest -= ret; ++ n += ret; ++ str += ret; ++ if (req->in_len == 0) { ++ if (req->in_pad) { ++ if (safe_read(req, buf, req->in_pad) != req->in_pad) { ++ req->keep = 0; ++ return ret; ++ } ++ } ++ } else { ++ return n; ++ } ++ } else { ++ return n; ++ } ++ } ++ return n; ++} ++ ++void fcgi_close(fcgi_request *req, int force, int destroy) ++{ ++ if (destroy) { ++ zend_hash_destroy(&req->env); ++ } ++ ++#ifdef _WIN32 ++ if (is_impersonate && !req->tcp) { ++ RevertToSelf(); ++ } ++#endif ++ ++ if ((force || !req->keep) && req->fd >= 0) { ++#ifdef _WIN32 ++ if (!req->tcp) { ++ HANDLE pipe = (HANDLE)_get_osfhandle(req->fd); ++ ++ if (!force) { ++ FlushFileBuffers(pipe); ++ } ++ DisconnectNamedPipe(pipe); ++ } else { ++ if (!force) { ++ char buf[8]; ++ ++ shutdown(req->fd, 1); ++ while (recv(req->fd, buf, sizeof(buf), 0) > 0) {} ++ } ++ closesocket(req->fd); ++ } ++#else ++ if (!force) { ++ char buf[8]; ++ ++ shutdown(req->fd, 1); ++ while (recv(req->fd, buf, sizeof(buf), 0) > 0) {} ++ } ++ close(req->fd); ++#endif ++ req->fd = -1; ++ ++ fpm_request_finished(); ++ } ++} ++ ++int fcgi_accept_request(fcgi_request *req) ++{ ++#ifdef _WIN32 ++ HANDLE pipe; ++ OVERLAPPED ov; ++#endif ++ fcgi_finish_request(req); ++ ++ while (1) { ++ if (req->fd < 0) { ++ while (1) { ++ if (in_shutdown) { ++ return -1; ++ } ++#ifdef _WIN32 ++ if (!req->tcp) { ++ pipe = (HANDLE)_get_osfhandle(req->listen_socket); ++ FCGI_LOCK(req->listen_socket); ++ ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); ++ if (!ConnectNamedPipe(pipe, &ov)) { ++ errno = GetLastError(); ++ if (errno == ERROR_IO_PENDING) { ++ while (WaitForSingleObject(ov.hEvent, 1000) == WAIT_TIMEOUT) { ++ if (in_shutdown) { ++ CloseHandle(ov.hEvent); ++ FCGI_UNLOCK(req->listen_socket); ++ return -1; ++ } ++ } ++ } else if (errno != ERROR_PIPE_CONNECTED) { ++ } ++ } ++ CloseHandle(ov.hEvent); ++ req->fd = req->listen_socket; ++ FCGI_UNLOCK(req->listen_socket); ++ } else { ++ SOCKET listen_socket = (SOCKET)_get_osfhandle(req->listen_socket); ++#else ++ { ++ int listen_socket = req->listen_socket; ++#endif ++ sa_t sa; ++ socklen_t len = sizeof(sa); ++ ++ fpm_request_accepting(); ++ ++ FCGI_LOCK(req->listen_socket); ++ req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len); ++ FCGI_UNLOCK(req->listen_socket); ++ if (req->fd >= 0 && allowed_clients) { ++ int n = 0; ++ int allowed = 0; ++ ++ while (allowed_clients[n] != INADDR_NONE) { ++ if (allowed_clients[n] == sa.sa_inet.sin_addr.s_addr) { ++ allowed = 1; ++ break; ++ } ++ n++; ++ } ++ if (!allowed) { ++ fprintf(stderr, "Connection from disallowed IP address '%s' is dropped.\n", inet_ntoa(sa.sa_inet.sin_addr)); ++ closesocket(req->fd); ++ req->fd = -1; ++ continue; ++ } ++ } ++ } ++ ++#ifdef _WIN32 ++ if (req->fd < 0 && (in_shutdown || errno != EINTR)) { ++#else ++ if (req->fd < 0 && (in_shutdown || (errno != EINTR && errno != ECONNABORTED))) { ++#endif ++ return -1; ++ } ++ ++#ifdef _WIN32 ++ break; ++#else ++ if (req->fd >= 0) { ++ ++ fpm_request_reading_headers(); ++ ++#if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL) ++ struct pollfd fds; ++ int ret; ++ ++ fds.fd = req->fd; ++ fds.events = POLLIN; ++ fds.revents = 0; ++ do { ++ errno = 0; ++ ret = poll(&fds, 1, 5000); ++ } while (ret < 0 && errno == EINTR); ++ if (ret > 0 && (fds.revents & POLLIN)) { ++ break; ++ } ++ fcgi_close(req, 1, 0); ++#else ++ if (req->fd < FD_SETSIZE) { ++ struct timeval tv = {5,0}; ++ fd_set set; ++ int ret; ++ ++ FD_ZERO(&set); ++ FD_SET(req->fd, &set); ++ do { ++ errno = 0; ++ ret = select(req->fd + 1, &set, NULL, NULL, &tv) >= 0; ++ } while (ret < 0 && errno == EINTR); ++ if (ret > 0 && FD_ISSET(req->fd, &set)) { ++ break; ++ } ++ fcgi_close(req, 1, 0); ++ } else { ++ fprintf(stderr, "Too many open file descriptors. FD_SETSIZE limit exceeded."); ++ fcgi_close(req, 1, 0); ++ } ++#endif ++ } ++#endif ++ } ++ } else if (in_shutdown) { ++ return -1; ++ } ++ if (fcgi_read_request(req)) { ++#ifdef _WIN32 ++ if (is_impersonate && !req->tcp) { ++ pipe = (HANDLE)_get_osfhandle(req->fd); ++ if (!ImpersonateNamedPipeClient(pipe)) { ++ fcgi_close(req, 1, 1); ++ continue; ++ } ++ } ++#endif ++ return req->fd; ++ } else { ++ fcgi_close(req, 1, 1); ++ } ++ } ++} ++ ++static inline fcgi_header* open_packet(fcgi_request *req, fcgi_request_type type) ++{ ++ req->out_hdr = (fcgi_header*) req->out_pos; ++ req->out_hdr->type = type; ++ req->out_pos += sizeof(fcgi_header); ++ return req->out_hdr; ++} ++ ++static inline void close_packet(fcgi_request *req) ++{ ++ if (req->out_hdr) { ++ int len = req->out_pos - ((unsigned char*)req->out_hdr + sizeof(fcgi_header)); ++ ++ req->out_pos += fcgi_make_header(req->out_hdr, (fcgi_request_type)req->out_hdr->type, req->id, len); ++ req->out_hdr = NULL; ++ } ++} ++ ++int fcgi_flush(fcgi_request *req, int close) ++{ ++ int len; ++ ++ close_packet(req); ++ ++ len = req->out_pos - req->out_buf; ++ ++ if (close) { ++ fcgi_end_request_rec *rec = (fcgi_end_request_rec*)(req->out_pos); ++ ++ fcgi_make_header(&rec->hdr, FCGI_END_REQUEST, req->id, sizeof(fcgi_end_request)); ++ rec->body.appStatusB3 = 0; ++ rec->body.appStatusB2 = 0; ++ rec->body.appStatusB1 = 0; ++ rec->body.appStatusB0 = 0; ++ rec->body.protocolStatus = FCGI_REQUEST_COMPLETE; ++ len += sizeof(fcgi_end_request_rec); ++ } ++ ++ if (safe_write(req, req->out_buf, len) != len) { ++ req->keep = 0; ++ return 0; ++ } ++ ++ req->out_pos = req->out_buf; ++ return 1; ++} ++ ++int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len) ++{ ++ int limit, rest; ++ ++ if (len <= 0) { ++ return 0; ++ } ++ ++ if (req->out_hdr && req->out_hdr->type != type) { ++ close_packet(req); ++ } ++#if 0 ++ /* Unoptimized, but clear version */ ++ rest = len; ++ while (rest > 0) { ++ limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf); ++ ++ if (!req->out_hdr) { ++ if (limit < sizeof(fcgi_header)) { ++ if (!fcgi_flush(req, 0)) { ++ return -1; ++ } ++ } ++ open_packet(req, type); ++ } ++ limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf); ++ if (rest < limit) { ++ memcpy(req->out_pos, str, rest); ++ req->out_pos += rest; ++ return len; ++ } else { ++ memcpy(req->out_pos, str, limit); ++ req->out_pos += limit; ++ rest -= limit; ++ str += limit; ++ if (!fcgi_flush(req, 0)) { ++ return -1; ++ } ++ } ++ } ++#else ++ /* Optimized version */ ++ limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf); ++ if (!req->out_hdr) { ++ limit -= sizeof(fcgi_header); ++ if (limit < 0) limit = 0; ++ } ++ ++ if (len < limit) { ++ if (!req->out_hdr) { ++ open_packet(req, type); ++ } ++ memcpy(req->out_pos, str, len); ++ req->out_pos += len; ++ } else if (len - limit < sizeof(req->out_buf) - sizeof(fcgi_header)) { ++ if (!req->out_hdr) { ++ open_packet(req, type); ++ } ++ if (limit > 0) { ++ memcpy(req->out_pos, str, limit); ++ req->out_pos += limit; ++ } ++ if (!fcgi_flush(req, 0)) { ++ return -1; ++ } ++ if (len > limit) { ++ open_packet(req, type); ++ memcpy(req->out_pos, str + limit, len - limit); ++ req->out_pos += len - limit; ++ } ++ } else { ++ int pos = 0; ++ int pad; ++ ++ close_packet(req); ++ while ((len - pos) > 0xffff) { ++ open_packet(req, type); ++ fcgi_make_header(req->out_hdr, type, req->id, 0xfff8); ++ req->out_hdr = NULL; ++ if (!fcgi_flush(req, 0)) { ++ return -1; ++ } ++ if (safe_write(req, str + pos, 0xfff8) != 0xfff8) { ++ req->keep = 0; ++ return -1; ++ } ++ pos += 0xfff8; ++ } ++ ++ pad = (((len - pos) + 7) & ~7) - (len - pos); ++ rest = pad ? 8 - pad : 0; ++ ++ open_packet(req, type); ++ fcgi_make_header(req->out_hdr, type, req->id, (len - pos) - rest); ++ req->out_hdr = NULL; ++ if (!fcgi_flush(req, 0)) { ++ return -1; ++ } ++ if (safe_write(req, str + pos, (len - pos) - rest) != (len - pos) - rest) { ++ req->keep = 0; ++ return -1; ++ } ++ if (pad) { ++ open_packet(req, type); ++ memcpy(req->out_pos, str + len - rest, rest); ++ req->out_pos += rest; ++ } ++ } ++#endif ++ return len; ++} ++ ++int fcgi_finish_request(fcgi_request *req) ++{ ++ if (req->fd >= 0) { ++ fcgi_flush(req, 1); ++ fcgi_close(req, 0, 1); ++ } ++ return 1; ++} ++ ++char* fcgi_getenv(fcgi_request *req, const char* var, int var_len) ++{ ++ char **val; ++ ++ if (!req) return NULL; ++ ++ if (zend_hash_find(&req->env, (char*)var, var_len+1, (void**)&val) == SUCCESS) { ++ return *val; ++ } ++ return NULL; ++} ++ ++char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val) ++{ ++ if (var && req) { ++ if (val == NULL) { ++ zend_hash_del(&req->env, var, var_len+1); ++ } else { ++ char **ret; ++ ++ val = strdup(val); ++ if (zend_hash_update(&req->env, var, var_len+1, &val, sizeof(char*), (void**)&ret) == SUCCESS) { ++ return *ret; ++ } ++ } ++ } ++ return NULL; ++} ++ ++#ifdef _WIN32 ++void fcgi_impersonate(void) ++{ ++ char *os_name; ++ ++ os_name = getenv("OS"); ++ if (os_name && stricmp(os_name, "Windows_NT") == 0) { ++ is_impersonate = 1; ++ } ++} ++#endif ++ ++void fcgi_set_mgmt_var(char * name, size_t name_len, const char * value, size_t value_len) ++{ ++ zval * zvalue; ++ zvalue = pemalloc(sizeof(*zvalue), 1); ++ Z_TYPE_P(zvalue) = IS_STRING; ++ Z_STRVAL_P(zvalue) = pestrndup(value, value_len, 1); ++ Z_STRLEN_P(zvalue) = value_len; ++ zend_hash_update(fcgi_mgmt_vars, name, name_len + 1, &zvalue, sizeof(zvalue), NULL); ++} ++ ++void fcgi_free_mgmt_var_cb(void * ptr) ++{ ++ zval ** var = (zval **)ptr; ++ pefree(Z_STRVAL_PP(var), 1); ++ pefree(*var, 1); ++} ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * End: ++ * vim600: sw=4 ts=4 fdm=marker ++ * vim<600: sw=4 ts=4 ++ */ +diff -Naur php-src-vanilla/sapi/fpm/cgi/fastcgi.h php-src/sapi/fpm/cgi/fastcgi.h +--- php-src-vanilla/sapi/fpm/cgi/fastcgi.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/cgi/fastcgi.h 2009-10-18 21:05:39.302497288 +0100 +@@ -0,0 +1,150 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | PHP Version 5 | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 1997-2008 The PHP Group | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 3.01 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available through the world-wide-web at the following url: | ++ | http://www.php.net/license/3_01.txt | ++ | If you did not receive a copy of the PHP license and are unable to | ++ | obtain it through the world-wide-web, please send a note to | ++ | license@php.net so we can mail you a copy immediately. | ++ +----------------------------------------------------------------------+ ++ | Authors: Dmitry Stogov | ++ +----------------------------------------------------------------------+ ++*/ ++ ++/* $Id$ */ ++ ++/* FastCGI protocol */ ++ ++#define FCGI_VERSION_1 1 ++ ++#define FCGI_MAX_LENGTH 0xffff ++ ++#define FCGI_KEEP_CONN 1 ++ ++typedef enum _fcgi_role { ++ FCGI_RESPONDER = 1, ++ FCGI_AUTHORIZER = 2, ++ FCGI_FILTER = 3 ++} fcgi_role; ++ ++typedef enum _fcgi_request_type { ++ FCGI_BEGIN_REQUEST = 1, /* [in] */ ++ FCGI_ABORT_REQUEST = 2, /* [in] (not supported) */ ++ FCGI_END_REQUEST = 3, /* [out] */ ++ FCGI_PARAMS = 4, /* [in] environment variables */ ++ FCGI_STDIN = 5, /* [in] post data */ ++ FCGI_STDOUT = 6, /* [out] response */ ++ FCGI_STDERR = 7, /* [out] errors */ ++ FCGI_DATA = 8, /* [in] filter data (not supported) */ ++ FCGI_GET_VALUES = 9, /* [in] */ ++ FCGI_GET_VALUES_RESULT = 10 /* [out] */ ++} fcgi_request_type; ++ ++typedef enum _fcgi_protocol_status { ++ FCGI_REQUEST_COMPLETE = 0, ++ FCGI_CANT_MPX_CONN = 1, ++ FCGI_OVERLOADED = 2, ++ FCGI_UNKNOWN_ROLE = 3 ++} dcgi_protocol_status; ++ ++typedef struct _fcgi_header { ++ unsigned char version; ++ unsigned char type; ++ unsigned char requestIdB1; ++ unsigned char requestIdB0; ++ unsigned char contentLengthB1; ++ unsigned char contentLengthB0; ++ unsigned char paddingLength; ++ unsigned char reserved; ++} fcgi_header; ++ ++typedef struct _fcgi_begin_request { ++ unsigned char roleB1; ++ unsigned char roleB0; ++ unsigned char flags; ++ unsigned char reserved[5]; ++} fcgi_begin_request; ++ ++typedef struct _fcgi_begin_request_rec { ++ fcgi_header hdr; ++ fcgi_begin_request body; ++} fcgi_begin_request_rec; ++ ++typedef struct _fcgi_end_request { ++ unsigned char appStatusB3; ++ unsigned char appStatusB2; ++ unsigned char appStatusB1; ++ unsigned char appStatusB0; ++ unsigned char protocolStatus; ++ unsigned char reserved[3]; ++} fcgi_end_request; ++ ++typedef struct _fcgi_end_request_rec { ++ fcgi_header hdr; ++ fcgi_end_request body; ++} fcgi_end_request_rec; ++ ++/* FastCGI client API */ ++ ++typedef struct _fcgi_request { ++ int listen_socket; ++#ifdef _WIN32 ++ int tcp; ++#endif ++ int fd; ++ int id; ++ int keep; ++ ++ int in_len; ++ int in_pad; ++ ++ fcgi_header *out_hdr; ++ unsigned char *out_pos; ++ unsigned char out_buf[1024*8]; ++ unsigned char reserved[sizeof(fcgi_end_request_rec)]; ++ ++ HashTable env; ++} fcgi_request; ++ ++int fcgi_init(void); ++void fcgi_shutdown(void); ++int fcgi_is_fastcgi(void); ++void fcgi_set_is_fastcgi(int); ++void fcgi_set_in_shutdown(int); ++void fcgi_set_allowed_clients(char *); ++int fcgi_in_shutdown(void); ++int fcgi_listen(const char *path, int backlog); ++void fcgi_init_request(fcgi_request *req, int listen_socket); ++int fcgi_accept_request(fcgi_request *req); ++int fcgi_finish_request(fcgi_request *req); ++ ++char* fcgi_getenv(fcgi_request *req, const char* var, int var_len); ++char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val); ++ ++int fcgi_read(fcgi_request *req, char *str, int len); ++ ++int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len); ++int fcgi_flush(fcgi_request *req, int close); ++ ++void fcgi_close(fcgi_request *req, int force, int destroy); ++ ++#ifdef PHP_WIN32 ++void fcgi_impersonate(void); ++#endif ++ ++void fcgi_set_mgmt_var(char * name, size_t name_len, const char * value, size_t value_len); ++void fcgi_free_mgmt_var_cb(void * ptr); ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * End: ++ * vim600: sw=4 ts=4 fdm=marker ++ * vim<600: sw=4 ts=4 ++ */ +diff -Naur php-src-vanilla/sapi/fpm/cgi/php_getopt.h php-src/sapi/fpm/cgi/php_getopt.h +--- php-src-vanilla/sapi/fpm/cgi/php_getopt.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/cgi/php_getopt.h 2009-10-18 21:05:39.302497288 +0100 +@@ -0,0 +1,39 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | PHP Version 5 | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 1997-2008 The PHP Group | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 3.01 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available through the world-wide-web at the following url: | ++ | http://www.php.net/license/3_01.txt | ++ | If you did not receive a copy of the PHP license and are unable to | ++ | obtain it through the world-wide-web, please send a note to | ++ | license@php.net so we can mail you a copy immediately. | ++ +----------------------------------------------------------------------+ ++ | Author: Marcus Boerger | ++ +----------------------------------------------------------------------+ ++*/ ++ ++/* $Id$ */ ++ ++#include ++ ++#ifdef NETWARE ++/* ++As NetWare LibC has optind and optarg macros defined in unistd.h our local variables were getting mistakenly preprocessed so undeffing optind and optarg ++*/ ++#undef optarg ++#undef optind ++#endif ++/* Define structure for one recognized option (both single char and long name). ++ * If short_open is '-' this is the last option. ++ */ ++typedef struct _opt_struct { ++ const char opt_char; ++ const int need_param; ++ const char * opt_name; ++} opt_struct; ++ ++int php_getopt(int argc, char* const *argv, const opt_struct opts[], char **optarg, int *optind, int show_err); +diff -Naur php-src-vanilla/sapi/fpm/conf/init.d.php-fpm.in php-src/sapi/fpm/conf/init.d.php-fpm.in +--- php-src-vanilla/sapi/fpm/conf/init.d.php-fpm.in 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/conf/init.d.php-fpm.in 2009-10-18 21:05:39.298456068 +0100 +@@ -0,0 +1,135 @@ ++#! /bin/sh ++ ++### BEGIN INIT INFO ++# Provides: @php_fpm_bin@ ++# Required-Start: $all ++# Required-Stop: $all ++# Default-Start: 2 3 4 5 ++# Default-Stop: 0 1 6 ++# Short-Description: starts @php_fpm_bin@ ++# Description: starts the PHP FastCGI Process Manager daemon ++### END INIT INFO ++ ++php_fpm_BIN=@php_fpm_bin_path@ ++php_fpm_CONF=@php_fpm_conf_path@ ++php_fpm_PID=@php_fpm_pid_path@ ++ ++ ++php_opts="--fpm-config $php_fpm_CONF" ++ ++ ++wait_for_pid () { ++ try=0 ++ ++ while test $try -lt 35 ; do ++ ++ case "$1" in ++ 'created') ++ if [ -f "$2" ] ; then ++ try='' ++ break ++ fi ++ ;; ++ ++ 'removed') ++ if [ ! -f "$2" ] ; then ++ try='' ++ break ++ fi ++ ;; ++ esac ++ ++ echo -n . ++ try=`expr $try + 1` ++ sleep 1 ++ ++ done ++ ++} ++ ++case "$1" in ++ start) ++ echo -n "Starting @php_fpm_bin@ " ++ ++ $php_fpm_BIN $php_opts ++ ++ if [ "$?" != 0 ] ; then ++ echo " failed" ++ exit 1 ++ fi ++ ++ wait_for_pid created $php_fpm_PID ++ ++ if [ -n "$try" ] ; then ++ echo " failed" ++ exit 1 ++ else ++ echo " done" ++ fi ++ ;; ++ ++ stop) ++ echo -n "Gracefully shutting down @php_fpm_bin@ " ++ ++ if [ ! -r $php_fpm_PID ] ; then ++ echo "warning, no pid file found - php-fpm is not running ?" ++ exit 1 ++ fi ++ ++ kill -QUIT `cat $php_fpm_PID` ++ ++ wait_for_pid removed $php_fpm_PID ++ ++ if [ -n "$try" ] ; then ++ echo " failed. Use force-exit" ++ exit 1 ++ else ++ echo " done" ++ fi ++ ;; ++ ++ force-quit) ++ echo -n "Terminating @php_fpm_bin@ " ++ ++ if [ ! -r $php_fpm_PID ] ; then ++ echo "warning, no pid file found - php-fpm is not running ?" ++ exit 1 ++ fi ++ ++ kill -TERM `cat $php_fpm_PID` ++ ++ wait_for_pid removed $php_fpm_PID ++ ++ if [ -n "$try" ] ; then ++ echo " failed" ++ exit 1 ++ else ++ echo " done" ++ fi ++ ;; ++ ++ restart) ++ $0 stop ++ $0 start ++ ;; ++ ++ reload) ++ ++ echo -n "Reload service @php_fpm_bin@ " ++ ++ if [ ! -r $php_fpm_PID ] ; then ++ echo "warning, no pid file found - @php_fpm_bin@ is not running ?" ++ exit 1 ++ fi ++ ++ kill -USR2 `cat $php_fpm_PID` ++ ++ echo " done" ++ ;; ++ ++ *) ++ echo "Usage: $0 {start|stop|force-quit|restart|reload}" ++ exit 1 ++ ;; ++ ++esac +diff -Naur php-src-vanilla/sapi/fpm/conf/nginx-site-conf.sample.in php-src/sapi/fpm/conf/nginx-site-conf.sample.in +--- php-src-vanilla/sapi/fpm/conf/nginx-site-conf.sample.in 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/conf/nginx-site-conf.sample.in 2009-10-18 21:05:39.298456068 +0100 +@@ -0,0 +1,46 @@ ++# @php_fpm_bin@ - PHP FastCGI Process Manager 'PHP-FPM' ++# ++# nginx-site-conf.sample: ++# Php Site configuration for nginx webserver ++# ++# 1. set server root /path/to/your/website; ++# 2. Rename this file. Copy it to /etc/nginx/sites-available, /etc/nginx/sites-enabled ++# or otherwise ensure that this file is included by the nginx.conf ++# 3. Restart nginx webserver, and @php_fpm_bin@ service. ++# ++ ++server { ++ ++ root /var/www/nginx-site; ++ ++ server_name localhost; ++ listen 80; ++ ++ access_log /var/log/nginx/localhost.access.log; ++ ++ location / { ++ index index.html index.htm; ++ } ++ ++ #error_page 404 /404.html; ++ ++ # redirect server error pages to the static page /50x.html ++ # ++ error_page 500 502 503 504 /50x.html; ++ location = /50x.html { ++ root /var/www/nginx-default; ++ } ++ ++ # pass the *.php scripts to @php_fpm_bin@ listening on tcp port @php_fpm_port@ ++ # ++ location ~ \.php$ { ++ ++ fastcgi_pass 127.0.0.1:@php_fpm_port@; ++ fastcgi_index index.php; ++ ++ include fastcgi_params; ++ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; ++ fastcgi_param SERVER_NAME $http_host; ++ fastcgi_ignore_client_abort on; ++ } ++} +diff -Naur php-src-vanilla/sapi/fpm/conf/php-fpm.conf.in php-src/sapi/fpm/conf/php-fpm.conf.in +--- php-src-vanilla/sapi/fpm/conf/php-fpm.conf.in 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/conf/php-fpm.conf.in 2009-10-18 21:05:39.298456068 +0100 +@@ -0,0 +1,159 @@ ++ ++ ++ ++ All relative paths in this config are relative to php's install prefix ++ ++
++ ++ Pid file ++ @php_fpm_pid_path@ ++ ++ Error log file ++ @php_fpm_log_path@ ++ ++ Log level ++ notice ++ ++ When this amount of php processes exited with SIGSEGV or SIGBUS ... ++ 10 ++ ++ ... in a less than this interval of time, a graceful restart will be initiated. ++ Useful to work around accidental curruptions in accelerator's shared memory. ++ 1m ++ ++ Time limit on waiting child's reaction on signals from master ++ 5s ++ ++ Set to 'no' to debug fpm ++ yes ++ ++
++ ++ ++ ++
++ ++ Name of pool. Used in logs and stats. ++ default ++ ++ Address to accept fastcgi requests on. ++ Valid syntax is 'ip.ad.re.ss:port' or just 'port' or '/path/to/unix/socket' ++ 127.0.0.1:@php_fpm_port@ ++ ++ ++ ++ Set listen(2) backlog ++ -1 ++ ++ Set permissions for unix socket, if one used. ++ In Linux read/write permissions must be set in order to allow connections from web server. ++ Many BSD-derrived systems allow connections regardless of permissions. ++ @php_fpm_user@ ++ @php_fpm_group@ ++ 0666 ++ ++ ++ Additional php.ini defines, specific to this pool of workers. ++ These settings overwrite the values previously defined in the php.ini. ++ ++ ++ ++ ++ ++ ++ ++ Unix user of processes ++ @php_fpm_user@ ++ ++ Unix group of processes ++ @php_fpm_group@ ++ ++ Process manager settings ++ ++ ++ Sets style of controling worker process count. ++ Valid values are 'static' and 'apache-like' ++ static ++ ++ Sets the limit on the number of simultaneous requests that will be served. ++ Equivalent to Apache MaxClients directive. ++ Equivalent to PHP_FCGI_CHILDREN environment in original php.fcgi ++ Used with any pm_style. ++ 5 ++ ++ Settings group for 'apache-like' pm style ++ ++ ++ Sets the number of server processes created on startup. ++ Used only when 'apache-like' pm_style is selected ++ 20 ++ ++ Sets the desired minimum number of idle server processes. ++ Used only when 'apache-like' pm_style is selected ++ 5 ++ ++ Sets the desired maximum number of idle server processes. ++ Used only when 'apache-like' pm_style is selected ++ 35 ++ ++ ++ ++ ++ ++ The timeout (in seconds) for serving a single request after which the worker process will be terminated ++ Should be used when 'max_execution_time' ini option does not stop script execution for some reason ++ '0s' means 'off' ++ 0s ++ ++ The timeout (in seconds) for serving of single request after which a php backtrace will be dumped to slow.log file ++ '0s' means 'off' ++ 0s ++ ++ The log file for slow requests ++ @php_fpm_log_path@.slow ++ ++ Set open file desc rlimit ++ 1024 ++ ++ Set max core size rlimit ++ 0 ++ ++ Chroot to this directory at the start, absolute path ++ ++ ++ Chdir to this directory at the start, absolute path ++ ++ ++ Redirect workers' stdout and stderr into main error log. ++ If not set, they will be redirected to /dev/null, according to FastCGI specs ++ yes ++ ++ How much requests each process should execute before respawn. ++ Useful to work around memory leaks in 3rd party libraries. ++ For endless request processing please specify 0 ++ Equivalent to PHP_FCGI_MAX_REQUESTS ++ 500 ++ ++ Comma separated list of ipv4 addresses of FastCGI clients that allowed to connect. ++ Equivalent to FCGI_WEB_SERVER_ADDRS environment in original php.fcgi (5.2.2+) ++ Makes sense only with AF_INET listening socket. ++ 127.0.0.1 ++ ++ Pass environment variables like LD_LIBRARY_PATH ++ All $VARIABLEs are taken from current environment ++ ++ $HOSTNAME ++ /usr/local/bin:/usr/bin:/bin ++ /tmp ++ /tmp ++ /tmp ++ $OSTYPE ++ $MACHTYPE ++ 2 ++ ++ ++
++ ++
++ ++
+diff -Naur php-src-vanilla/sapi/fpm/config.m4 php-src/sapi/fpm/config.m4 +--- php-src-vanilla/sapi/fpm/config.m4 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/config.m4 2009-10-18 21:05:39.302497288 +0100 +@@ -0,0 +1,26 @@ ++dnl ++dnl $Id$ ++dnl ++ ++PHP_ARG_WITH(fpm,, ++[ --with-fpm Build PHP FastCGI - FPM executable], no) ++ ++if test "$PHP_FPM" != "no"; then ++ ++ PHP_CONFIGURE_PART(Configuring fpm) ++ ++ sinclude(sapi/fpm/ac/fpm_libevent.m4) ++ AC_LIB_EVENT([1.4.3],[1.4.11]) ++ ++ sinclude(sapi/fpm/ac/fpm_checks.m4) ++ AC_FPM_CHECKS ++ ++ sinclude(sapi/fpm/ac/fpm_conf.m4) ++ fpm_version="0.6" ++ AC_FPM_CONF ++ ++ sinclude(sapi/fpm/ac/fpm_build.m4) ++ AC_FPM_BUILD_SAPI ++ ++ AC_MSG_RESULT() ++fi +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_arrays.h php-src/sapi/fpm/fpm/fpm_arrays.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_arrays.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_arrays.h 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,110 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_ARRAYS_H ++#define FPM_ARRAYS_H 1 ++ ++#include ++#include ++ ++struct fpm_array_s { ++ void *data; ++ size_t sz; ++ size_t used; ++ size_t allocated; ++}; ++ ++static inline struct fpm_array_s *fpm_array_init(struct fpm_array_s *a, unsigned int sz, unsigned int initial_num) ++{ ++ void *allocated = 0; ++ ++ if (!a) { ++ a = malloc(sizeof(struct fpm_array_s)); ++ ++ if (!a) { ++ return 0; ++ } ++ ++ allocated = a; ++ } ++ ++ a->sz = sz; ++ ++ a->data = calloc(sz, initial_num); ++ ++ if (!a->data) { ++ free(allocated); ++ return 0; ++ } ++ ++ a->allocated = initial_num; ++ a->used = 0; ++ ++ return a; ++} ++ ++static inline void *fpm_array_item(struct fpm_array_s *a, unsigned int n) ++{ ++ char *ret; ++ ++ ret = (char *) a->data + a->sz * n; ++ ++ return ret; ++} ++ ++static inline void *fpm_array_item_last(struct fpm_array_s *a) ++{ ++ return fpm_array_item(a, a->used - 1); ++} ++ ++static inline int fpm_array_item_remove(struct fpm_array_s *a, unsigned int n) ++{ ++ int ret = -1; ++ ++ if (n < a->used - 1) { ++ void *last = fpm_array_item(a, a->used - 1); ++ void *to_remove = fpm_array_item(a, n); ++ ++ memcpy(to_remove, last, a->sz); ++ ++ ret = n; ++ } ++ ++ --a->used; ++ ++ return ret; ++} ++ ++static inline void *fpm_array_push(struct fpm_array_s *a) ++{ ++ void *ret; ++ ++ if (a->used == a->allocated) { ++ size_t new_allocated = a->allocated ? a->allocated * 2 : 20; ++ void *new_ptr = realloc(a->data, a->sz * new_allocated); ++ ++ if (!new_ptr) { ++ return 0; ++ } ++ ++ a->data = new_ptr; ++ a->allocated = new_allocated; ++ } ++ ++ ret = fpm_array_item(a, a->used); ++ ++ ++a->used; ++ ++ return ret; ++} ++ ++static inline void fpm_array_free(struct fpm_array_s *a) ++{ ++ free(a->data); ++ a->data = 0; ++ a->sz = 0; ++ a->used = a->allocated = 0; ++} ++ ++#endif +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_atomic.h php-src/sapi/fpm/fpm/fpm_atomic.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_atomic.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_atomic.h 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,139 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_ATOMIC_H ++#define FPM_ATOMIC_H 1 ++ ++#if HAVE_INTTYPES_H ++#include ++#else ++#include ++#endif ++#include ++ ++#if ( __i386__ || __i386 ) ++ ++typedef int32_t atomic_int_t; ++typedef uint32_t atomic_uint_t; ++typedef volatile atomic_uint_t atomic_t; ++ ++ ++static inline atomic_int_t atomic_fetch_add(atomic_t *value, atomic_int_t add) ++{ ++ __asm__ volatile ( "lock;" "xaddl %0, %1;" : ++ "+r" (add) : "m" (*value) : "memory"); ++ ++ return add; ++} ++ ++static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, atomic_uint_t set) ++{ ++ unsigned char res; ++ ++ __asm__ volatile ( "lock;" "cmpxchgl %3, %1;" "sete %0;" : ++ "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "memory"); ++ ++ return res; ++} ++ ++#elif ( __amd64__ || __amd64 ) ++ ++typedef int64_t atomic_int_t; ++typedef uint64_t atomic_uint_t; ++typedef volatile atomic_uint_t atomic_t; ++ ++static inline atomic_int_t atomic_fetch_add(atomic_t *value, atomic_int_t add) ++{ ++ __asm__ volatile ( "lock;" "xaddq %0, %1;" : ++ "+r" (add) : "m" (*value) : "memory"); ++ ++ return add; ++} ++ ++static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, atomic_uint_t set) ++{ ++ unsigned char res; ++ ++ __asm__ volatile ( "lock;" "cmpxchgq %3, %1;" "sete %0;" : ++ "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "memory"); ++ ++ return res; ++} ++ ++#if (__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)) ++ ++#elif ( __arm__ || __arm ) /* W-Mark Kubacki */ ++ ++#if (__arch64__ || __arch64) ++typedef int64_t atomic_int_t; ++typedef uint64_t atomic_uint_t; ++#else ++typedef int32_t atomic_int_t; ++typedef uint32_t atomic_uint_t; ++#endif ++ ++#define atomic_cmp_set(a,b,c) __sync_bool_compare_and_swap(a,b,c) ++ ++#endif /* defined (__GNUC__) &&... */ ++ ++#elif ( __sparc__ || __sparc ) /* Marcin Ochab */ ++ ++#if (__arch64__ || __arch64) ++typedef uint64_t atomic_uint_t; ++typedef volatile atomic_uint_t atomic_t; ++ ++static inline int atomic_cas_64(atomic_t *lock, atomic_uint_t old, atomic_uint_t new) ++{ ++ __asm__ __volatile__("casx [%2], %3, %0 " : "=&r"(new) : "0"(new), "r"(lock), "r"(old): "memory"); ++ ++ return new; ++} ++ ++static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, atomic_uint_t set) ++{ ++ return (atomic_cas_64(lock, old, set)==old); ++} ++#else ++typedef uint32_t atomic_uint_t; ++typedef volatile atomic_uint_t atomic_t; ++ ++static inline int atomic_cas_32(atomic_t *lock, atomic_uint_t old, atomic_uint_t new) ++{ ++ __asm__ __volatile__("cas [%2], %3, %0 " : "=&r"(new) : "0"(new), "r"(lock), "r"(old): "memory"); ++ ++ return new; ++} ++ ++static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, atomic_uint_t set) ++{ ++ return (atomic_cas_32(lock, old, set)==old); ++} ++#endif ++ ++#else ++ ++#error unsupported architecture. please write a patch and send it in ++ ++#endif ++ ++static inline int fpm_spinlock(atomic_t *lock, int try_once) ++{ ++ if (try_once) { ++ return atomic_cmp_set(lock, 0, 1) ? 0 : -1; ++ } ++ ++ for (;;) { ++ ++ if (atomic_cmp_set(lock, 0, 1)) { ++ break; ++ } ++ ++ sched_yield(); ++ } ++ ++ return 0; ++} ++ ++#endif ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm.c php-src/sapi/fpm/fpm/fpm.c +--- php-src-vanilla/sapi/fpm/fpm/fpm.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm.c 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,82 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#include /* for exit */ ++ ++#include "fpm.h" ++#include "fpm_children.h" ++#include "fpm_signals.h" ++#include "fpm_env.h" ++#include "fpm_events.h" ++#include "fpm_cleanup.h" ++#include "fpm_php.h" ++#include "fpm_sockets.h" ++#include "fpm_unix.h" ++#include "fpm_process_ctl.h" ++#include "fpm_conf.h" ++#include "fpm_worker_pool.h" ++#include "fpm_stdio.h" ++#include "zlog.h" ++ ++struct fpm_globals_s fpm_globals; ++ ++int fpm_init(int argc, char **argv, char *config) ++{ ++ fpm_globals.argc = argc; ++ fpm_globals.argv = argv; ++ fpm_globals.config = config; ++ ++ if (0 > fpm_php_init_main() || ++ 0 > fpm_stdio_init_main() || ++ 0 > fpm_conf_init_main() || ++ 0 > fpm_unix_init_main() || ++ 0 > fpm_env_init_main() || ++ 0 > fpm_signals_init_main() || ++ 0 > fpm_pctl_init_main() || ++ 0 > fpm_children_init_main() || ++ 0 > fpm_sockets_init_main() || ++ 0 > fpm_worker_pool_init_main() || ++ 0 > fpm_event_init_main()) { ++ return -1; ++ } ++ ++ if (0 > fpm_conf_write_pid()) { ++ return -1; ++ } ++ ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "fpm is running, pid %d", (int) fpm_globals.parent_pid); ++ ++ return 0; ++} ++ ++/* children: return listening socket ++ parent: never return */ ++int fpm_run(int *max_requests) ++{ ++ struct fpm_worker_pool_s *wp; ++ ++ /* create initial children in all pools */ ++ for (wp = fpm_worker_all_pools; wp; wp = wp->next) { ++ int is_parent; ++ ++ is_parent = fpm_children_create_initial(wp); ++ ++ if (!is_parent) { ++ goto run_child; ++ } ++ } ++ ++ /* run event loop forever */ ++ fpm_event_loop(); ++ ++run_child: /* only workers reach this point */ ++ ++ fpm_cleanups_run(FPM_CLEANUP_CHILD); ++ ++ *max_requests = fpm_globals.max_requests; ++ return fpm_globals.listening_socket; ++} ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_children.c php-src/sapi/fpm/fpm/fpm_children.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_children.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_children.c 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,387 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "fpm.h" ++#include "fpm_children.h" ++#include "fpm_signals.h" ++#include "fpm_worker_pool.h" ++#include "fpm_sockets.h" ++#include "fpm_process_ctl.h" ++#include "fpm_php.h" ++#include "fpm_conf.h" ++#include "fpm_cleanup.h" ++#include "fpm_events.h" ++#include "fpm_clock.h" ++#include "fpm_stdio.h" ++#include "fpm_unix.h" ++#include "fpm_env.h" ++#include "fpm_shm_slots.h" ++ ++#include "zlog.h" ++ ++static time_t *last_faults; ++static int fault; ++ ++static int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop); ++ ++static void fpm_children_cleanup(int which, void *arg) ++{ ++ free(last_faults); ++} ++ ++static struct fpm_child_s *fpm_child_alloc() ++{ ++ struct fpm_child_s *ret; ++ ++ ret = malloc(sizeof(struct fpm_child_s)); ++ ++ if (!ret) { return 0; } ++ ++ memset(ret, 0, sizeof(*ret)); ++ ++ return ret; ++} ++ ++static void fpm_child_free(struct fpm_child_s *child) ++{ ++ free(child); ++} ++ ++static void fpm_child_close(struct fpm_child_s *child, int in_event_loop) ++{ ++ if (child->fd_stdout != -1) { ++ if (in_event_loop) { ++ fpm_event_fire(&child->ev_stdout); ++ } ++ if (child->fd_stdout != -1) { ++ close(child->fd_stdout); ++ } ++ } ++ ++ if (child->fd_stderr != -1) { ++ if (in_event_loop) { ++ fpm_event_fire(&child->ev_stderr); ++ } ++ if (child->fd_stderr != -1) { ++ close(child->fd_stderr); ++ } ++ } ++ ++ fpm_child_free(child); ++} ++ ++static void fpm_child_link(struct fpm_child_s *child) ++{ ++ struct fpm_worker_pool_s *wp = child->wp; ++ ++ ++wp->running_children; ++ ++fpm_globals.running_children; ++ ++ child->next = wp->children; ++ if (child->next) { child->next->prev = child; } ++ child->prev = 0; ++ wp->children = child; ++} ++ ++static void fpm_child_unlink(struct fpm_child_s *child) ++{ ++ --child->wp->running_children; ++ --fpm_globals.running_children; ++ ++ if (child->prev) { child->prev->next = child->next; } ++ else { child->wp->children = child->next; } ++ if (child->next) { child->next->prev = child->prev; } ++ ++} ++ ++static struct fpm_child_s *fpm_child_find(pid_t pid) ++{ ++ struct fpm_worker_pool_s *wp; ++ struct fpm_child_s *child = 0; ++ ++ for (wp = fpm_worker_all_pools; wp; wp = wp->next) { ++ ++ for (child = wp->children; child; child = child->next) { ++ if (child->pid == pid) { ++ break; ++ } ++ } ++ ++ if (child) { ++ break; ++ } ++ } ++ ++ if (!child) { ++ return 0; ++ } ++ ++ return child; ++} ++ ++static void fpm_child_init(struct fpm_worker_pool_s *wp) ++{ ++ fpm_globals.max_requests = wp->config->max_requests; ++ ++ if (0 > fpm_stdio_init_child(wp) || ++ 0 > fpm_unix_init_child(wp) || ++ 0 > fpm_signals_init_child() || ++ 0 > fpm_env_init_child(wp) || ++ 0 > fpm_php_init_child(wp)) { ++ ++ zlog(ZLOG_STUFF, ZLOG_ERROR, "child failed to initialize (pool %s)", wp->config->name); ++ exit(255); ++ } ++} ++ ++int fpm_children_free(struct fpm_child_s *child) ++{ ++ struct fpm_child_s *next; ++ ++ for (; child; child = next) { ++ next = child->next; ++ fpm_child_close(child, 0 /* in_event_loop */); ++ } ++ ++ return 0; ++} ++ ++void fpm_children_bury() ++{ ++ int status; ++ pid_t pid; ++ struct fpm_child_s *child; ++ ++ while ( (pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) { ++ char buf[128]; ++ int severity = ZLOG_NOTICE; ++ ++ child = fpm_child_find(pid); ++ ++ if (WIFEXITED(status)) { ++ ++ snprintf(buf, sizeof(buf), "with code %d", WEXITSTATUS(status)); ++ ++ if (WEXITSTATUS(status) != 0) { ++ severity = ZLOG_WARNING; ++ } ++ ++ } ++ else if (WIFSIGNALED(status)) { ++ const char *signame = fpm_signal_names[WTERMSIG(status)]; ++ const char *have_core = WCOREDUMP(status) ? " (core dumped)" : ""; ++ ++ if (signame == NULL) { ++ signame = ""; ++ } ++ ++ snprintf(buf, sizeof(buf), "on signal %d %s%s", WTERMSIG(status), signame, have_core); ++ ++ if (WTERMSIG(status) != SIGQUIT) { /* possible request loss */ ++ severity = ZLOG_WARNING; ++ } ++ } ++ else if (WIFSTOPPED(status)) { ++ ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "child %d stopped for tracing", (int) pid); ++ ++ if (child && child->tracer) { ++ child->tracer(child); ++ } ++ ++ continue; ++ } ++ ++ if (child) { ++ struct fpm_worker_pool_s *wp = child->wp; ++ struct timeval tv1, tv2; ++ ++ fpm_child_unlink(child); ++ ++ fpm_shm_slots_discard_slot(child); ++ ++ fpm_clock_get(&tv1); ++ ++ timersub(&tv1, &child->started, &tv2); ++ ++ zlog(ZLOG_STUFF, severity, "child %d (pool %s) exited %s after %ld.%06d seconds from start", (int) pid, ++ child->wp->config->name, buf, tv2.tv_sec, (int) tv2.tv_usec); ++ ++ fpm_child_close(child, 1 /* in event_loop */); ++ ++ fpm_pctl_child_exited(); ++ ++ if (last_faults && (WTERMSIG(status) == SIGSEGV || WTERMSIG(status) == SIGBUS)) { ++ time_t now = tv1.tv_sec; ++ int restart_condition = 1; ++ int i; ++ ++ last_faults[fault++] = now; ++ ++ if (fault == fpm_global_config.emergency_restart_threshold) { ++ fault = 0; ++ } ++ ++ for (i = 0; i < fpm_global_config.emergency_restart_threshold; i++) { ++ if (now - last_faults[i] > fpm_global_config.emergency_restart_interval) { ++ restart_condition = 0; ++ break; ++ } ++ } ++ ++ if (restart_condition) { ++ ++ zlog(ZLOG_STUFF, ZLOG_WARNING, "failed processes threshold (%d in %d sec) is reached, initiating reload", ++ fpm_global_config.emergency_restart_threshold, fpm_global_config.emergency_restart_interval); ++ ++ fpm_pctl(FPM_PCTL_STATE_RELOADING, FPM_PCTL_ACTION_SET); ++ } ++ } ++ ++ fpm_children_make(wp, 1 /* in event loop */); ++ ++ if (fpm_globals.is_child) { ++ break; ++ } ++ } ++ else { ++ zlog(ZLOG_STUFF, ZLOG_ALERT, "oops, unknown child exited %s", buf); ++ } ++ } ++ ++} ++ ++static struct fpm_child_s *fpm_resources_prepare(struct fpm_worker_pool_s *wp) ++{ ++ struct fpm_child_s *c; ++ ++ c = fpm_child_alloc(); ++ ++ if (!c) { ++ zlog(ZLOG_STUFF, ZLOG_ERROR, "malloc failed (pool %s)", wp->config->name); ++ return 0; ++ } ++ ++ c->wp = wp; ++ c->fd_stdout = -1; c->fd_stderr = -1; ++ ++ if (0 > fpm_stdio_prepare_pipes(c)) { ++ fpm_child_free(c); ++ return 0; ++ } ++ ++ if (0 > fpm_shm_slots_prepare_slot(c)) { ++ fpm_stdio_discard_pipes(c); ++ fpm_child_free(c); ++ return 0; ++ } ++ ++ return c; ++} ++ ++static void fpm_resources_discard(struct fpm_child_s *child) ++{ ++ fpm_shm_slots_discard_slot(child); ++ fpm_stdio_discard_pipes(child); ++ fpm_child_free(child); ++} ++ ++static void fpm_child_resources_use(struct fpm_child_s *child) ++{ ++ fpm_shm_slots_child_use_slot(child); ++ fpm_stdio_child_use_pipes(child); ++ fpm_child_free(child); ++} ++ ++static void fpm_parent_resources_use(struct fpm_child_s *child) ++{ ++ fpm_shm_slots_parent_use_slot(child); ++ fpm_stdio_parent_use_pipes(child); ++ fpm_child_link(child); ++} ++ ++static int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop) ++{ ++ int enough = 0; ++ pid_t pid; ++ struct fpm_child_s *child; ++ ++ while (!enough && fpm_pctl_can_spawn_children() && wp->running_children < wp->config->pm->max_children) { ++ ++ child = fpm_resources_prepare(wp); ++ ++ if (!child) { ++ enough = 1; ++ break; ++ } ++ ++ pid = fork(); ++ ++ switch (pid) { ++ ++ case 0 : ++ fpm_child_resources_use(child); ++ fpm_globals.is_child = 1; ++ if (in_event_loop) { ++ fpm_event_exit_loop(); ++ } ++ fpm_child_init(wp); ++ return 0; ++ ++ case -1 : ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fork() failed"); ++ enough = 1; ++ ++ fpm_resources_discard(child); ++ ++ break; /* dont try any more on error */ ++ ++ default : ++ child->pid = pid; ++ fpm_clock_get(&child->started); ++ fpm_parent_resources_use(child); ++ ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "child %d (pool %s) started", (int) pid, wp->config->name); ++ } ++ ++ } ++ ++ return 1; /* we are done */ ++} ++ ++int fpm_children_create_initial(struct fpm_worker_pool_s *wp) ++{ ++ return fpm_children_make(wp, 0 /* not in event loop yet */); ++} ++ ++int fpm_children_init_main() ++{ ++ if (fpm_global_config.emergency_restart_threshold && ++ fpm_global_config.emergency_restart_interval) { ++ ++ last_faults = malloc(sizeof(time_t) * fpm_global_config.emergency_restart_threshold); ++ ++ if (!last_faults) { ++ return -1; ++ } ++ ++ memset(last_faults, 0, sizeof(time_t) * fpm_global_config.emergency_restart_threshold); ++ } ++ ++ if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_children_cleanup, 0)) { ++ return -1; ++ } ++ ++ return 0; ++} ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_children.h php-src/sapi/fpm/fpm/fpm_children.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_children.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_children.h 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,33 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_CHILDREN_H ++#define FPM_CHILDREN_H 1 ++ ++#include ++#include ++#include ++ ++#include "fpm_worker_pool.h" ++ ++int fpm_children_create_initial(struct fpm_worker_pool_s *wp); ++int fpm_children_free(struct fpm_child_s *child); ++void fpm_children_bury(); ++int fpm_children_init_main(); ++ ++struct fpm_child_s; ++ ++struct fpm_child_s { ++ struct fpm_child_s *prev, *next; ++ struct timeval started; ++ struct fpm_worker_pool_s *wp; ++ struct event ev_stdout, ev_stderr; ++ int shm_slot_i; ++ int fd_stdout, fd_stderr; ++ void (*tracer)(struct fpm_child_s *); ++ struct timeval slow_logged; ++ pid_t pid; ++}; ++ ++#endif +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_cleanup.c php-src/sapi/fpm/fpm/fpm_cleanup.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_cleanup.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_cleanup.c 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,51 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#include ++ ++#include "fpm_arrays.h" ++#include "fpm_cleanup.h" ++#include "zlog.h" ++ ++struct cleanup_s { ++ int type; ++ void (*cleanup)(int, void *); ++ void *arg; ++}; ++ ++static struct fpm_array_s cleanups = { .sz = sizeof(struct cleanup_s) }; ++ ++int fpm_cleanup_add(int type, void (*cleanup)(int, void *), void *arg) ++{ ++ struct cleanup_s *c; ++ ++ c = fpm_array_push(&cleanups); ++ ++ if (!c) { ++ return -1; ++ } ++ ++ c->type = type; ++ c->cleanup = cleanup; ++ c->arg = arg; ++ ++ return 0; ++} ++ ++void fpm_cleanups_run(int type) ++{ ++ struct cleanup_s *c = fpm_array_item_last(&cleanups); ++ int cl = cleanups.used; ++ ++ for ( ; cl--; c--) { ++ if (c->type & type) { ++ c->cleanup(type, c->arg); ++ } ++ } ++ ++ fpm_array_free(&cleanups); ++} ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_cleanup.h php-src/sapi/fpm/fpm/fpm_cleanup.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_cleanup.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_cleanup.h 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,21 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_CLEANUP_H ++#define FPM_CLEANUP_H 1 ++ ++int fpm_cleanup_add(int type, void (*cleanup)(int, void *), void *); ++void fpm_cleanups_run(int type); ++ ++enum { ++ FPM_CLEANUP_CHILD = (1 << 0), ++ FPM_CLEANUP_PARENT_EXIT = (1 << 1), ++ FPM_CLEANUP_PARENT_EXIT_MAIN = (1 << 2), ++ FPM_CLEANUP_PARENT_EXEC = (1 << 3), ++ FPM_CLEANUP_PARENT = (1 << 1) | (1 << 2) | (1 << 3), ++ FPM_CLEANUP_ALL = ~0, ++}; ++ ++#endif ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_clock.c php-src/sapi/fpm/fpm/fpm_clock.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_clock.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_clock.c 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,115 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#if defined(HAVE_CLOCK_GETTIME) ++#include /* for CLOCK_MONOTONIC */ ++#endif ++ ++#include "fpm_clock.h" ++#include "zlog.h" ++ ++ ++/* posix monotonic clock - preferred source of time */ ++#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) ++ ++static int monotonic_works; ++ ++int fpm_clock_init() ++{ ++ struct timespec ts; ++ ++ monotonic_works = 0; ++ ++ if (0 == clock_gettime(CLOCK_MONOTONIC, &ts)) { ++ monotonic_works = 1; ++ } ++ ++ return 0; ++} ++ ++int fpm_clock_get(struct timeval *tv) ++{ ++ if (monotonic_works) { ++ struct timespec ts; ++ ++ if (0 > clock_gettime(CLOCK_MONOTONIC, &ts)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "clock_gettime() failed"); ++ return -1; ++ } ++ ++ tv->tv_sec = ts.tv_sec; ++ tv->tv_usec = ts.tv_nsec / 1000; ++ return 0; ++ } ++ ++ return gettimeofday(tv, 0); ++} ++ ++/* macosx clock */ ++#elif defined(HAVE_CLOCK_GET_TIME) ++ ++#include ++#include ++#include ++ ++static clock_serv_t mach_clock; ++ ++/* this code borrowed from here: http://lists.apple.com/archives/Darwin-development/2002/Mar/msg00746.html */ ++/* mach_clock also should be re-initialized in child process after fork */ ++int fpm_clock_init() ++{ ++ kern_return_t ret; ++ mach_timespec_t aTime; ++ ++ ret = host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &mach_clock); ++ ++ if (ret != KERN_SUCCESS) { ++ zlog(ZLOG_STUFF, ZLOG_ERROR, "host_get_clock_service() failed: %s", mach_error_string(ret)); ++ return -1; ++ } ++ ++ /* test if it works */ ++ ret = clock_get_time(mach_clock, &aTime); ++ ++ if (ret != KERN_SUCCESS) { ++ zlog(ZLOG_STUFF, ZLOG_ERROR, "clock_get_time() failed: %s", mach_error_string(ret)); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int fpm_clock_get(struct timeval *tv) ++{ ++ kern_return_t ret; ++ mach_timespec_t aTime; ++ ++ ret = clock_get_time(mach_clock, &aTime); ++ ++ if (ret != KERN_SUCCESS) { ++ zlog(ZLOG_STUFF, ZLOG_ERROR, "clock_get_time() failed: %s", mach_error_string(ret)); ++ return -1; ++ } ++ ++ tv->tv_sec = aTime.tv_sec; ++ tv->tv_usec = aTime.tv_nsec / 1000; ++ ++ return 0; ++} ++ ++#else /* no clock */ ++ ++int fpm_clock_init() ++{ ++ return 0; ++} ++ ++int fpm_clock_get(struct timeval *tv) ++{ ++ return gettimeofday(tv, 0); ++} ++ ++#endif +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_clock.h php-src/sapi/fpm/fpm/fpm_clock.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_clock.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_clock.h 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,13 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_CLOCK_H ++#define FPM_CLOCK_H 1 ++ ++#include ++ ++int fpm_clock_init(); ++int fpm_clock_get(struct timeval *tv); ++ ++#endif +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_conf.c php-src/sapi/fpm/fpm/fpm_conf.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_conf.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_conf.c 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,537 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#if HAVE_INTTYPES_H ++#include ++#else ++#include ++#endif ++ ++#include ++#include ++ ++#include "fpm.h" ++#include "fpm_conf.h" ++#include "fpm_stdio.h" ++#include "fpm_worker_pool.h" ++#include "fpm_cleanup.h" ++#include "fpm_php.h" ++#include "fpm_sockets.h" ++#include "xml_config.h" ++#include "zlog.h" ++ ++ ++struct fpm_global_config_s fpm_global_config; ++ ++static void *fpm_global_config_ptr() ++{ ++ return &fpm_global_config; ++} ++ ++static char *fpm_conf_set_log_level(void **conf, char *name, void *vv, intptr_t offset) ++{ ++ char *value = vv; ++ ++ if (!strcmp(value, "debug")) { ++ fpm_globals.log_level = ZLOG_DEBUG; ++ } ++ else if (!strcmp(value, "notice")) { ++ fpm_globals.log_level = ZLOG_NOTICE; ++ } ++ else if (!strcmp(value, "warn")) { ++ fpm_globals.log_level = ZLOG_WARNING; ++ } ++ else if (!strcmp(value, "error")) { ++ fpm_globals.log_level = ZLOG_ERROR; ++ } ++ else if (!strcmp(value, "alert")) { ++ fpm_globals.log_level = ZLOG_ALERT; ++ } ++ else { ++ return "invalid value for 'log_level'"; ++ } ++ ++ return NULL; ++} ++ ++static struct xml_conf_section xml_section_fpm_global_options = { ++ .conf = &fpm_global_config_ptr, ++ .path = "/configuration/global_options", ++ .parsers = (struct xml_value_parser []) { ++ { XML_CONF_SCALAR, "emergency_restart_threshold", &xml_conf_set_slot_integer, offsetof(struct fpm_global_config_s, emergency_restart_threshold) }, ++ { XML_CONF_SCALAR, "emergency_restart_interval", &xml_conf_set_slot_time, offsetof(struct fpm_global_config_s, emergency_restart_interval) }, ++ { XML_CONF_SCALAR, "process_control_timeout", &xml_conf_set_slot_time, offsetof(struct fpm_global_config_s, process_control_timeout) }, ++ { XML_CONF_SCALAR, "daemonize", &xml_conf_set_slot_boolean, offsetof(struct fpm_global_config_s, daemonize) }, ++ { XML_CONF_SCALAR, "pid_file", &xml_conf_set_slot_string, offsetof(struct fpm_global_config_s, pid_file) }, ++ { XML_CONF_SCALAR, "error_log", &xml_conf_set_slot_string, offsetof(struct fpm_global_config_s, error_log) }, ++ { XML_CONF_SCALAR, "log_level", &fpm_conf_set_log_level, 0 }, ++ { 0, 0, 0, 0 } ++ } ++}; ++ ++static char *fpm_conf_set_pm_style(void **conf, char *name, void *vv, intptr_t offset) ++{ ++ char *value = vv; ++ struct fpm_pm_s *c = *conf; ++ ++ if (!strcmp(value, "static")) { ++ c->style = PM_STYLE_STATIC; ++ } ++ else if (!strcmp(value, "apache-like")) { ++ c->style = PM_STYLE_APACHE_LIKE; ++ } ++ else { ++ return "invalid value for 'style'"; ++ } ++ ++ return NULL; ++} ++ ++static char *fpm_conf_set_rlimit_core(void **conf, char *name, void *vv, intptr_t offset) ++{ ++ char *value = vv; ++ struct fpm_worker_pool_config_s *c = *conf; ++ ++ if (!strcmp(value, "unlimited")) { ++ c->rlimit_core = -1; ++ } ++ else { ++ int int_value; ++ void *subconf = &int_value; ++ char *error; ++ ++ error = xml_conf_set_slot_integer(&subconf, name, vv, 0); ++ ++ if (error) { return error; } ++ ++ if (int_value < 0) { return "invalid value for 'rlimit_core'"; } ++ ++ c->rlimit_core = int_value; ++ } ++ ++ return NULL; ++} ++ ++static char *fpm_conf_set_catch_workers_output(void **conf, char *name, void *vv, intptr_t offset) ++{ ++ struct fpm_worker_pool_config_s *c = *conf; ++ int int_value; ++ void *subconf = &int_value; ++ char *error; ++ ++ error = xml_conf_set_slot_boolean(&subconf, name, vv, 0); ++ ++ if (error) { return error; } ++ ++ c->catch_workers_output = int_value; ++ ++ return NULL; ++} ++ ++static struct xml_conf_section fpm_conf_set_apache_like_subsection_conf = { ++ .path = "apache_like somewhere", /* fixme */ ++ .parsers = (struct xml_value_parser []) { ++ { XML_CONF_SCALAR, "StartServers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, options_apache_like.StartServers) }, ++ { XML_CONF_SCALAR, "MinSpareServers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, options_apache_like.MinSpareServers) }, ++ { XML_CONF_SCALAR, "MaxSpareServers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, options_apache_like.MaxSpareServers) }, ++ { 0, 0, 0, 0 } ++ } ++}; ++ ++static char *fpm_conf_set_apache_like_subsection(void **conf, char *name, void *xml_node, intptr_t offset) ++{ ++ return xml_conf_parse_section(conf, &fpm_conf_set_apache_like_subsection_conf, xml_node); ++} ++ ++static struct xml_conf_section fpm_conf_set_listen_options_subsection_conf = { ++ .path = "listen options somewhere", /* fixme */ ++ .parsers = (struct xml_value_parser []) { ++ { XML_CONF_SCALAR, "backlog", &xml_conf_set_slot_integer, offsetof(struct fpm_listen_options_s, backlog) }, ++ { XML_CONF_SCALAR, "owner", &xml_conf_set_slot_string, offsetof(struct fpm_listen_options_s, owner) }, ++ { XML_CONF_SCALAR, "group", &xml_conf_set_slot_string, offsetof(struct fpm_listen_options_s, group) }, ++ { XML_CONF_SCALAR, "mode", &xml_conf_set_slot_string, offsetof(struct fpm_listen_options_s, mode) }, ++ { 0, 0, 0, 0 } ++ } ++}; ++ ++static char *fpm_conf_set_listen_options_subsection(void **conf, char *name, void *xml_node, intptr_t offset) ++{ ++ void *subconf = (char *) *conf + offset; ++ struct fpm_listen_options_s *lo; ++ ++ lo = malloc(sizeof(*lo)); ++ ++ if (!lo) { ++ return "malloc() failed"; ++ } ++ ++ memset(lo, 0, sizeof(*lo)); ++ ++ lo->backlog = -1; ++ ++ * (struct fpm_listen_options_s **) subconf = lo; ++ ++ subconf = lo; ++ ++ return xml_conf_parse_section(&subconf, &fpm_conf_set_listen_options_subsection_conf, xml_node); ++} ++ ++static struct xml_conf_section fpm_conf_set_pm_subsection_conf = { ++ .path = "pm settings somewhere", /* fixme */ ++ .parsers = (struct xml_value_parser []) { ++ { XML_CONF_SCALAR, "style", &fpm_conf_set_pm_style, 0 }, ++ { XML_CONF_SCALAR, "max_children", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, max_children) }, ++ { XML_CONF_SUBSECTION, "apache_like", &fpm_conf_set_apache_like_subsection, offsetof(struct fpm_pm_s, options_apache_like) }, ++ { 0, 0, 0, 0 } ++ } ++}; ++ ++static char *fpm_conf_set_pm_subsection(void **conf, char *name, void *xml_node, intptr_t offset) ++{ ++ void *subconf = (char *) *conf + offset; ++ struct fpm_pm_s *pm; ++ ++ pm = malloc(sizeof(*pm)); ++ ++ if (!pm) { ++ return "fpm_conf_set_pm_subsection(): malloc failed"; ++ } ++ ++ memset(pm, 0, sizeof(*pm)); ++ ++ * (struct fpm_pm_s **) subconf = pm; ++ ++ subconf = pm; ++ ++ return xml_conf_parse_section(&subconf, &fpm_conf_set_pm_subsection_conf, xml_node); ++} ++ ++static char *xml_conf_set_slot_key_value_pair(void **conf, char *name, void *vv, intptr_t offset) ++{ ++ char *value = vv; ++ struct key_value_s *kv; ++ struct key_value_s ***parent = (struct key_value_s ***) conf; ++ ++ kv = malloc(sizeof(*kv)); ++ ++ if (!kv) { ++ return "malloc() failed"; ++ } ++ ++ memset(kv, 0, sizeof(*kv)); ++ ++ kv->key = strdup(name); ++ kv->value = strdup(value); ++ ++ if (!kv->key || !kv->value) { ++ return "xml_conf_set_slot_key_value_pair(): strdup() failed"; ++ } ++ ++ **parent = kv; ++ ++ *parent = &kv->next; ++ ++ return NULL; ++} ++ ++static struct xml_conf_section fpm_conf_set_key_value_pairs_subsection_conf = { ++ .path = "key_value_pairs somewhere", /* fixme */ ++ .parsers = (struct xml_value_parser []) { ++ { XML_CONF_SCALAR, 0, &xml_conf_set_slot_key_value_pair, 0 }, ++ { 0, 0, 0, 0 } ++ } ++}; ++ ++static char *fpm_conf_set_key_value_pairs_subsection(void **conf, char *name, void *xml_node, intptr_t offset) ++{ ++ void *next_kv = (char *) *conf + offset; ++ ++ return xml_conf_parse_section(&next_kv, &fpm_conf_set_key_value_pairs_subsection_conf, xml_node); ++} ++ ++static void *fpm_worker_pool_config_alloc() ++{ ++ static struct fpm_worker_pool_s *current_wp = 0; ++ struct fpm_worker_pool_s *wp; ++ ++ wp = fpm_worker_pool_alloc(); ++ ++ if (!wp) { return 0; } ++ ++ wp->config = malloc(sizeof(struct fpm_worker_pool_config_s)); ++ ++ if (!wp->config) { return 0; } ++ ++ memset(wp->config, 0, sizeof(struct fpm_worker_pool_config_s)); ++ ++ if (current_wp) { current_wp->next = wp; } ++ ++ current_wp = wp; ++ ++ return wp->config; ++} ++ ++int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc) ++{ ++ struct key_value_s *kv, *kv_next; ++ ++ free(wpc->name); ++ free(wpc->listen_address); ++ if (wpc->listen_options) { ++ free(wpc->listen_options->owner); ++ free(wpc->listen_options->group); ++ free(wpc->listen_options->mode); ++ free(wpc->listen_options); ++ } ++ for (kv = wpc->php_defines; kv; kv = kv_next) { ++ kv_next = kv->next; ++ free(kv->key); ++ free(kv->value); ++ free(kv); ++ } ++ for (kv = wpc->environment; kv; kv = kv_next) { ++ kv_next = kv->next; ++ free(kv->key); ++ free(kv->value); ++ free(kv); ++ } ++ free(wpc->pm); ++ free(wpc->user); ++ free(wpc->group); ++ free(wpc->chroot); ++ free(wpc->chdir); ++ free(wpc->allowed_clients); ++ free(wpc->slowlog); ++ ++ return 0; ++} ++ ++static struct xml_conf_section xml_section_fpm_worker_pool_config = { ++ .conf = &fpm_worker_pool_config_alloc, ++ .path = "/configuration/workers/pool", ++ .parsers = (struct xml_value_parser []) { ++ { XML_CONF_SCALAR, "name", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, name) }, ++ { XML_CONF_SCALAR, "listen_address", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, listen_address) }, ++ { XML_CONF_SUBSECTION, "listen_options", &fpm_conf_set_listen_options_subsection, offsetof(struct fpm_worker_pool_config_s, listen_options) }, ++ { XML_CONF_SUBSECTION, "php_defines", &fpm_conf_set_key_value_pairs_subsection, offsetof(struct fpm_worker_pool_config_s, php_defines) }, ++ { XML_CONF_SCALAR, "user", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, user) }, ++ { XML_CONF_SCALAR, "group", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, group) }, ++ { XML_CONF_SCALAR, "chroot", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, chroot) }, ++ { XML_CONF_SCALAR, "chdir", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, chdir) }, ++ { XML_CONF_SCALAR, "allowed_clients", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, allowed_clients) }, ++ { XML_CONF_SUBSECTION, "environment", &fpm_conf_set_key_value_pairs_subsection, offsetof(struct fpm_worker_pool_config_s, environment) }, ++ { XML_CONF_SCALAR, "request_terminate_timeout", &xml_conf_set_slot_time, offsetof(struct fpm_worker_pool_config_s, request_terminate_timeout) }, ++ { XML_CONF_SCALAR, "request_slowlog_timeout", &xml_conf_set_slot_time, offsetof(struct fpm_worker_pool_config_s, request_slowlog_timeout) }, ++ { XML_CONF_SCALAR, "slowlog", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, slowlog) }, ++ { XML_CONF_SCALAR, "rlimit_files", &xml_conf_set_slot_integer, offsetof(struct fpm_worker_pool_config_s, rlimit_files) }, ++ { XML_CONF_SCALAR, "rlimit_core", &fpm_conf_set_rlimit_core, 0 }, ++ { XML_CONF_SCALAR, "max_requests", &xml_conf_set_slot_integer, offsetof(struct fpm_worker_pool_config_s, max_requests) }, ++ { XML_CONF_SCALAR, "catch_workers_output", &fpm_conf_set_catch_workers_output, 0 }, ++ { XML_CONF_SUBSECTION, "pm", &fpm_conf_set_pm_subsection, offsetof(struct fpm_worker_pool_config_s, pm) }, ++ { 0, 0, 0, 0 } ++ } ++}; ++ ++static struct xml_conf_section *fpm_conf_all_sections[] = { ++ &xml_section_fpm_global_options, ++ &xml_section_fpm_worker_pool_config, ++ 0 ++}; ++ ++static int fpm_evaluate_full_path(char **path) ++{ ++ if (**path != '/') { ++ char *full_path; ++ ++ full_path = malloc(sizeof(PHP_PREFIX) + strlen(*path) + 1); ++ ++ if (!full_path) { return -1; } ++ ++ sprintf(full_path, "%s/%s", PHP_PREFIX, *path); ++ ++ free(*path); ++ ++ *path = full_path; ++ } ++ ++ return 0; ++} ++ ++static int fpm_conf_process_all_pools() ++{ ++ struct fpm_worker_pool_s *wp; ++ ++ if (!fpm_worker_all_pools) { ++ zlog(ZLOG_STUFF, ZLOG_ERROR, "at least one pool section must be specified in config file"); ++ return -1; ++ } ++ ++ for (wp = fpm_worker_all_pools; wp; wp = wp->next) { ++ ++ if (wp->config->listen_address && *wp->config->listen_address) { ++ ++ wp->listen_address_domain = fpm_sockets_domain_from_address(wp->config->listen_address); ++ ++ if (wp->listen_address_domain == FPM_AF_UNIX && *wp->config->listen_address != '/') { ++ fpm_evaluate_full_path(&wp->config->listen_address); ++ } ++ ++ } ++ else { ++ ++ wp->is_template = 1; ++ ++ } ++ ++ if (wp->config->request_slowlog_timeout) { ++#if HAVE_FPM_TRACE ++ if (! (wp->config->slowlog && *wp->config->slowlog)) { ++ zlog(ZLOG_STUFF, ZLOG_ERROR, "pool %s: 'slowlog' must be specified for use with 'request_slowlog_timeout'", ++ wp->config->name); ++ return -1; ++ } ++#else ++ static int warned = 0; ++ ++ if (!warned) { ++ zlog(ZLOG_STUFF, ZLOG_WARNING, "pool %s: 'request_slowlog_timeout' is not supported on your system", ++ wp->config->name); ++ warned = 1; ++ } ++ ++ wp->config->request_slowlog_timeout = 0; ++#endif ++ } ++ ++ if (wp->config->request_slowlog_timeout && wp->config->slowlog && *wp->config->slowlog) { ++ int fd; ++ ++ fpm_evaluate_full_path(&wp->config->slowlog); ++ ++ if (wp->config->request_slowlog_timeout) { ++ fd = open(wp->config->slowlog, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR); ++ ++ if (0 > fd) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "open(%s) failed", wp->config->slowlog); ++ return -1; ++ } ++ close(fd); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++int fpm_conf_unlink_pid() ++{ ++ if (fpm_global_config.pid_file) { ++ ++ if (0 > unlink(fpm_global_config.pid_file)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "unlink(\"%s\") failed", fpm_global_config.pid_file); ++ return -1; ++ } ++ ++ } ++ ++ return 0; ++} ++ ++int fpm_conf_write_pid() ++{ ++ int fd; ++ ++ if (fpm_global_config.pid_file) { ++ char buf[64]; ++ int len; ++ ++ unlink(fpm_global_config.pid_file); ++ ++ fd = creat(fpm_global_config.pid_file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); ++ ++ if (fd < 0) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "creat(\"%s\") failed", fpm_global_config.pid_file); ++ return -1; ++ } ++ ++ len = sprintf(buf, "%d", (int) fpm_globals.parent_pid); ++ ++ if (len != write(fd, buf, len)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "write() failed"); ++ return -1; ++ } ++ ++ close(fd); ++ } ++ ++ return 0; ++} ++ ++static int fpm_conf_post_process() ++{ ++ if (fpm_global_config.pid_file) { ++ fpm_evaluate_full_path(&fpm_global_config.pid_file); ++ } ++ ++ if (!fpm_global_config.error_log) { ++ fpm_global_config.error_log = strdup(PHP_FPM_LOG_PATH); ++ } ++ ++ fpm_evaluate_full_path(&fpm_global_config.error_log); ++ ++ if (0 > fpm_stdio_open_error_log(0)) { ++ return -1; ++ } ++ ++ return fpm_conf_process_all_pools(); ++} ++ ++static void fpm_conf_cleanup(int which, void *arg) ++{ ++ free(fpm_global_config.pid_file); ++ free(fpm_global_config.error_log); ++ fpm_global_config.pid_file = 0; ++ fpm_global_config.error_log = 0; ++} ++ ++int fpm_conf_init_main() ++{ ++ char *filename = fpm_globals.config; ++ char *err; ++ ++ if (0 > xml_conf_sections_register(fpm_conf_all_sections)) { ++ return -1; ++ } ++ ++ if (filename == NULL) { ++ filename = PHP_FPM_CONF_PATH; ++ } ++ ++ err = xml_conf_load_file(filename); ++ ++ if (err) { ++ zlog(ZLOG_STUFF, ZLOG_ERROR, "failed to load configuration file: %s", err); ++ return -1; ++ } ++ ++ if (0 > fpm_conf_post_process()) { ++ return -1; ++ } ++ ++ xml_conf_clean(); ++ ++ if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_conf_cleanup, 0)) { ++ return -1; ++ } ++ ++ return 0; ++} +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_conf.h php-src/sapi/fpm/fpm/fpm_conf.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_conf.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_conf.h 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,73 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_CONF_H ++#define FPM_CONF_H 1 ++ ++struct key_value_s; ++ ++struct key_value_s { ++ struct key_value_s *next; ++ char *key; ++ char *value; ++}; ++ ++struct fpm_global_config_s { ++ int emergency_restart_threshold; ++ int emergency_restart_interval; ++ int process_control_timeout; ++ int daemonize; ++ char *pid_file; ++ char *error_log; ++}; ++ ++extern struct fpm_global_config_s fpm_global_config; ++ ++struct fpm_pm_s { ++ int style; ++ int max_children; ++ struct { ++ int StartServers; ++ int MinSpareServers; ++ int MaxSpareServers; ++ } options_apache_like; ++}; ++ ++struct fpm_listen_options_s { ++ int backlog; ++ char *owner; ++ char *group; ++ char *mode; ++}; ++ ++struct fpm_worker_pool_config_s { ++ char *name; ++ char *listen_address; ++ struct fpm_listen_options_s *listen_options; ++ struct key_value_s *php_defines; ++ char *user; ++ char *group; ++ char *chroot; ++ char *chdir; ++ char *allowed_clients; ++ struct key_value_s *environment; ++ struct fpm_pm_s *pm; ++ int request_terminate_timeout; ++ int request_slowlog_timeout; ++ char *slowlog; ++ int max_requests; ++ int rlimit_files; ++ int rlimit_core; ++ unsigned catch_workers_output:1; ++}; ++ ++enum { PM_STYLE_STATIC = 1, PM_STYLE_APACHE_LIKE = 2 }; ++ ++int fpm_conf_init_main(); ++int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc); ++int fpm_conf_write_pid(); ++int fpm_conf_unlink_pid(); ++ ++#endif ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_config.h php-src/sapi/fpm/fpm/fpm_config.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_config.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_config.h 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,40 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include ++#ifdef FPM_AUTOCONFIG_H ++#include ++#endif ++ ++/* Solaris does not have it */ ++#ifndef INADDR_NONE ++#define INADDR_NONE (-1) ++#endif ++ ++ ++/* If we're not using GNU C, elide __attribute__ */ ++#ifndef __GNUC__ ++# define __attribute__(x) /*NOTHING*/ ++#endif ++ ++ ++/* Solaris does not have it */ ++#ifndef timersub ++#define timersub(tvp, uvp, vvp) \ ++ do { \ ++ (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ ++ (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ ++ if ((vvp)->tv_usec < 0) { \ ++ (vvp)->tv_sec--; \ ++ (vvp)->tv_usec += 1000000; \ ++ } \ ++ } while (0) ++#endif ++ ++#if defined(HAVE_PTRACE) || defined(PROC_MEM_FILE) || defined(HAVE_MACH_VM_READ) ++#define HAVE_FPM_TRACE 1 ++#else ++#define HAVE_FPM_TRACE 0 ++#endif ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_env.c php-src/sapi/fpm/fpm/fpm_env.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_env.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_env.c 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,175 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#ifdef HAVE_ALLOCA_H ++#include ++#endif ++#include ++#include ++#include ++ ++#include "fpm_env.h" ++#include "zlog.h" ++ ++#ifndef HAVE_SETENV ++#ifdef (__sparc__ || __sparc) ++int setenv(name, value, clobber) ++char *name; ++char *value; ++int clobber; ++{ ++ char *malloc(); ++ char *getenv(); ++ char *cp; ++ ++ if (clobber == 0 && getenv(name) != 0) ++ { return (0); } ++ if ((cp = malloc(strlen(name) + strlen(value) + 2)) == 0) ++ { return (1); } ++ sprintf(cp, "%s=%s", name, value); ++ return (putenv(cp)); ++} ++#else ++int setenv(char *name, char *value, int overwrite) ++{ ++ int name_len = strlen(name); ++ int value_len = strlen(value); ++ char *var = alloca(name_len + 1 + value_len + 1); ++ ++ memcpy(var, name, name_len); ++ ++ var[name_len] = '='; ++ ++ memcpy(var + name_len + 1, value, value_len); ++ ++ var[name_len + 1 + value_len] = '\0'; ++ ++ return putenv(var); ++} ++#endif ++#endif ++ ++#ifndef HAVE_CLEARENV ++void clearenv() ++{ ++ char **envp; ++ char *s; ++ ++ /* this algo is the only one known to me ++ that works well on all systems */ ++ while (*(envp = environ)) { ++ char *eq = strchr(*envp, '='); ++ ++ s = strdup(*envp); ++ ++ if (eq) { s[eq - *envp] = '\0'; } ++ ++ unsetenv(s); ++ free(s); ++ } ++ ++} ++#endif ++ ++#ifndef HAVE_UNSETENV ++void unsetenv(const char *name) ++{ ++ if(getenv(name)!=NULL) ++ { ++ int ct=0; ++ int del=0; ++ ++ while(environ[ct] != NULL) ++ { ++ if (nvmatch(name, environ[ct]) != 0) del=ct; ++ { ct++; } ++ } ++ /* isn't needed free here?? */ ++ environ[del]=environ[ct-1]; ++ environ[ct-1]=NULL; ++ } ++} ++static char * nvmatch(s1, s2) ++register char *s1, *s2; ++{ ++ while(*s1 == *s2++) ++ { ++ if(*s1++ == '=') ++ { return(s2); } ++ } ++ if(*s1 == '\0' && *(s2-1) == '=') ++ { return(s2); } ++ return(NULL); ++} ++#endif ++ ++int fpm_env_init_child(struct fpm_worker_pool_s *wp) ++{ ++ struct key_value_s *kv; ++ ++ clearenv(); ++ ++ for (kv = wp->config->environment; kv; kv = kv->next) { ++ setenv(kv->key, kv->value, 1); ++ } ++ ++ if (wp->user) { ++ setenv("USER", wp->user, 1); ++ } ++ ++ if (wp->home) { ++ setenv("HOME", wp->home, 1); ++ } ++ ++ return 0; ++} ++ ++static int fpm_env_conf_wp(struct fpm_worker_pool_s *wp) ++{ ++ struct key_value_s *kv; ++ ++ kv = wp->config->environment; ++ ++ for (kv = wp->config->environment; kv; kv = kv->next) { ++ if (*kv->value == '$') { ++ char *value = getenv(kv->value + 1); ++ ++ if (!value) { value = ""; } ++ ++ free(kv->value); ++ kv->value = strdup(value); ++ } ++ ++ /* autodetected values should be removed ++ if these vars specified in config */ ++ if (!strcmp(kv->key, "USER")) { ++ free(wp->user); ++ wp->user = 0; ++ } ++ ++ if (!strcmp(kv->key, "HOME")) { ++ free(wp->home); ++ wp->home = 0; ++ } ++ } ++ ++ return 0; ++} ++ ++int fpm_env_init_main() ++{ ++ struct fpm_worker_pool_s *wp; ++ ++ for (wp = fpm_worker_all_pools; wp; wp = wp->next) { ++ ++ if (0 > fpm_env_conf_wp(wp)) { ++ return -1; ++ } ++ ++ } ++ ++ return 0; ++} +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_env.h php-src/sapi/fpm/fpm/fpm_env.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_env.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_env.h 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,24 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_ENV_H ++#define FPM_ENV_H 1 ++ ++#include "fpm_worker_pool.h" ++ ++int fpm_env_init_child(struct fpm_worker_pool_s *wp); ++int fpm_env_init_main(); ++ ++extern char **environ; ++ ++#ifndef HAVE_SETENV ++int setenv(char *name, char *value, int overwrite); ++#endif ++ ++#ifndef HAVE_CLEARENV ++void clearenv(); ++#endif ++ ++#endif ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_events.c php-src/sapi/fpm/fpm/fpm_events.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_events.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_events.c 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,135 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#include ++#include ++#include /* for putenv */ ++#include ++#include /* for event.h below */ ++#include ++ ++#include "fpm.h" ++#include "fpm_process_ctl.h" ++#include "fpm_events.h" ++#include "fpm_cleanup.h" ++#include "fpm_stdio.h" ++#include "fpm_signals.h" ++#include "fpm_children.h" ++#include "zlog.h" ++ ++static void fpm_event_cleanup(int which, void *arg) ++{ ++ event_base_free(0); ++} ++ ++static void fpm_got_signal(int fd, short ev, void *arg) ++{ ++ char c; ++ int res; ++ ++ do { ++ ++ do { ++ res = read(fd, &c, 1); ++ } while (res == -1 && errno == EINTR); ++ ++ if (res <= 0) { ++ if (res < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "read() failed"); ++ } ++ return; ++ } ++ ++ switch (c) { ++ case 'C' : /* SIGCHLD */ ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGCHLD"); ++ fpm_children_bury(); ++ break; ++ case 'I' : /* SIGINT */ ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGINT"); ++ fpm_pctl(FPM_PCTL_STATE_TERMINATING, FPM_PCTL_ACTION_SET); ++ break; ++ case 'T' : /* SIGTERM */ ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGTERM"); ++ fpm_pctl(FPM_PCTL_STATE_TERMINATING, FPM_PCTL_ACTION_SET); ++ break; ++ case 'Q' : /* SIGQUIT */ ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGQUIT"); ++ fpm_pctl(FPM_PCTL_STATE_FINISHING, FPM_PCTL_ACTION_SET); ++ break; ++ case '1' : /* SIGUSR1 */ ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGUSR1"); ++ if (0 == fpm_stdio_open_error_log(1)) { ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "log file re-opened"); ++ } ++ break; ++ case '2' : /* SIGUSR2 */ ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGUSR2"); ++ fpm_pctl(FPM_PCTL_STATE_RELOADING, FPM_PCTL_ACTION_SET); ++ break; ++ } ++ ++ if (fpm_globals.is_child) { ++ break; ++ } ++ ++ } while (1); ++ ++ return; ++} ++ ++int fpm_event_init_main() ++{ ++ event_init(); ++ ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "libevent: using %s", event_get_method()); ++ ++ if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_event_cleanup, 0)) { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int fpm_event_loop() ++{ ++ static struct event signal_fd_event; ++ ++ event_set(&signal_fd_event, fpm_signals_get_fd(), EV_PERSIST | EV_READ, &fpm_got_signal, 0); ++ ++ event_add(&signal_fd_event, 0); ++ ++ fpm_pctl_heartbeat(-1, 0, 0); ++ ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "libevent: entering main loop"); ++ ++ event_loop(0); ++ ++ return 0; ++} ++ ++int fpm_event_add(int fd, struct event *ev, void (*callback)(int, short, void *), void *arg) ++{ ++ event_set(ev, fd, EV_PERSIST | EV_READ, callback, arg); ++ ++ return event_add(ev, 0); ++} ++ ++int fpm_event_del(struct event *ev) ++{ ++ return event_del(ev); ++} ++ ++void fpm_event_exit_loop() ++{ ++ event_loopbreak(); ++} ++ ++void fpm_event_fire(struct event *ev) ++{ ++ (*ev->ev_callback)( (int) ev->ev_fd, (short) ev->ev_res, ev->ev_arg); ++} ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_events.h php-src/sapi/fpm/fpm/fpm_events.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_events.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_events.h 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,16 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_EVENTS_H ++#define FPM_EVENTS_H 1 ++ ++void fpm_event_exit_loop(); ++int fpm_event_loop(); ++int fpm_event_add(int fd, struct event *ev, void (*callback)(int, short, void *), void *arg); ++int fpm_event_del(struct event *ev); ++void fpm_event_fire(struct event *ev); ++int fpm_event_init_main(); ++ ++ ++#endif +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm.h php-src/sapi/fpm/fpm/fpm.h +--- php-src-vanilla/sapi/fpm/fpm/fpm.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm.h 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,28 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_H ++#define FPM_H 1 ++ ++#include ++ ++int fpm_run(int *max_requests); ++int fpm_init(int argc, char **argv, char *config); ++ ++struct fpm_globals_s { ++ pid_t parent_pid; ++ int argc; ++ char **argv; ++ char *config; ++ int running_children; ++ int error_log_fd; ++ int log_level; ++ int listening_socket; /* for this child */ ++ int max_requests; /* for this child */ ++ int is_child; ++}; ++ ++extern struct fpm_globals_s fpm_globals; ++ ++#endif +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_php.c php-src/sapi/fpm/fpm/fpm_php.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_php.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_php.c 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,189 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#include ++#include ++#include ++ ++#include "php.h" ++#include "php_main.h" ++#include "php_ini.h" ++#include "ext/standard/dl.h" ++ ++#include "cgi/fastcgi.h" ++ ++#include "fpm.h" ++#include "fpm_php.h" ++#include "fpm_cleanup.h" ++#include "fpm_worker_pool.h" ++ ++static int zend_ini_alter_master(char *name, int name_length, char *new_value, int new_value_length, int stage TSRMLS_DC) ++{ ++ zend_ini_entry *ini_entry; ++ char *duplicate; ++ ++ if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry) == FAILURE) { ++ return FAILURE; ++ } ++ ++ duplicate = strdup(new_value); ++ ++ if (!ini_entry->on_modify ++ || ini_entry->on_modify(ini_entry, duplicate, new_value_length, ++ ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage TSRMLS_CC) == SUCCESS) { ++ ini_entry->value = duplicate; ++ ini_entry->value_length = new_value_length; ++ } else { ++ free(duplicate); ++ } ++ ++ return SUCCESS; ++} ++ ++static void fpm_php_disable(char *value, int (*zend_disable)(char *, uint TSRMLS_DC) TSRMLS_DC) ++{ ++ char *s = 0, *e = value; ++ ++ while (*e) { ++ switch (*e) { ++ case ' ': ++ case ',': ++ if (s) { ++ *e = '\0'; ++ zend_disable(s, e - s TSRMLS_CC); ++ s = 0; ++ } ++ break; ++ default: ++ if (!s) { ++ s = e; ++ } ++ break; ++ } ++ e++; ++ } ++ ++ if (s) { ++ zend_disable(s, e - s TSRMLS_CC); ++ } ++} ++ ++static int fpm_php_apply_defines(struct fpm_worker_pool_s *wp) ++{ ++ TSRMLS_FETCH(); ++ struct key_value_s *kv; ++ ++ for (kv = wp->config->php_defines; kv; kv = kv->next) { ++ char *name = kv->key; ++ char *value = kv->value; ++ int name_len = strlen(name); ++ int value_len = strlen(value); ++ ++ if (!strcmp(name, "extension") && *value) { ++ zval zv; ++ ++#if defined(PHP_VERSION_ID) && (PHP_VERSION_ID >= 50300) ++ php_dl(value, MODULE_PERSISTENT, &zv, 1 TSRMLS_CC); ++#else ++ zval filename; ++ ZVAL_STRINGL(&filename, value, value_len, 0); ++#if (PHP_MAJOR_VERSION >= 5) ++ php_dl(&filename, MODULE_PERSISTENT, &zv, 1 TSRMLS_CC); ++#else ++ php_dl(&filename, MODULE_PERSISTENT, &zv TSRMLS_CC); ++#endif ++#endif ++ continue; ++ } ++ ++ zend_ini_alter_master(name, name_len + 1, value, value_len, PHP_INI_STAGE_ACTIVATE TSRMLS_CC); ++ ++ if (!strcmp(name, "disable_functions") && *value) { ++ char *v = strdup(value); ++#if (PHP_MAJOR_VERSION >= 5) ++ PG(disable_functions) = v; ++#endif ++ fpm_php_disable(v, zend_disable_function TSRMLS_CC); ++ } ++ else if (!strcmp(name, "disable_classes") && *value) { ++ char *v = strdup(value); ++#if (PHP_MAJOR_VERSION >= 5) ++ PG(disable_classes) = v; ++#endif ++ fpm_php_disable(v, zend_disable_class TSRMLS_CC); ++ } ++ } ++ ++ return 0; ++} ++ ++static int fpm_php_set_allowed_clients(struct fpm_worker_pool_s *wp) ++{ ++ if (wp->listen_address_domain == FPM_AF_INET) { ++ fcgi_set_allowed_clients(wp->config->allowed_clients); ++ } ++ ++ return 0; ++} ++ ++static int fpm_php_set_fcgi_mgmt_vars(struct fpm_worker_pool_s *wp) ++{ ++ char max_workers[10 + 1]; /* 4294967295 */ ++ int len; ++ ++ len = sprintf(max_workers, "%u", (unsigned int) wp->config->pm->max_children); ++ ++ fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, max_workers, len); ++ fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, max_workers, len); ++ ++ return 0; ++} ++ ++char *fpm_php_script_filename(TSRMLS_D) ++{ ++ return SG(request_info).path_translated; ++} ++ ++char *fpm_php_request_method(TSRMLS_D) ++{ ++ return (char *) SG(request_info).request_method; ++} ++ ++size_t fpm_php_content_length(TSRMLS_D) ++{ ++ return SG(request_info).content_length; ++} ++ ++static void fpm_php_cleanup(int which, void *arg) ++{ ++ TSRMLS_FETCH(); ++ php_module_shutdown(TSRMLS_C); ++ sapi_shutdown(); ++} ++ ++void fpm_php_soft_quit() ++{ ++ fcgi_set_in_shutdown(1); ++} ++ ++int fpm_php_init_main() ++{ ++ if (0 > fpm_cleanup_add(FPM_CLEANUP_PARENT, fpm_php_cleanup, 0)) { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int fpm_php_init_child(struct fpm_worker_pool_s *wp) ++{ ++ if (0 > fpm_php_apply_defines(wp) || ++ 0 > fpm_php_set_allowed_clients(wp)) { ++ return -1; ++ } ++ ++ return 0; ++} +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_php.h php-src/sapi/fpm/fpm/fpm_php.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_php.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_php.h 2009-10-18 21:05:39.302497288 +0100 +@@ -0,0 +1,22 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_PHP_H ++#define FPM_PHP_H 1 ++ ++#include ++ ++#include "build-defs.h" /* for PHP_ defines */ ++ ++struct fpm_worker_pool_s; ++ ++int fpm_php_init_child(struct fpm_worker_pool_s *wp); ++char *fpm_php_script_filename(TSRMLS_D); ++char *fpm_php_request_method(TSRMLS_D); ++size_t fpm_php_content_length(TSRMLS_D); ++void fpm_php_soft_quit(); ++int fpm_php_init_main(); ++ ++#endif ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_php_trace.c php-src/sapi/fpm/fpm/fpm_php_trace.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_php_trace.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_php_trace.c 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,176 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#if HAVE_FPM_TRACE ++ ++#include "php.h" ++#include "php_main.h" ++ ++#include ++#include ++#if HAVE_INTTYPES_H ++#include ++#else ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++ ++#include "fpm_trace.h" ++#include "fpm_php_trace.h" ++#include "fpm_children.h" ++#include "fpm_worker_pool.h" ++#include "fpm_process_ctl.h" ++ ++#include "zlog.h" ++ ++ ++#define valid_ptr(p) ((p) && 0 == ((p) & (sizeof(long) - 1))) ++ ++#if SIZEOF_LONG == 4 ++#define PTR_FMT "08" ++#elif SIZEOF_LONG == 8 ++#define PTR_FMT "016" ++#endif ++ ++ ++static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog TSRMLS_DC) ++{ ++ int callers_limit = 20; ++ pid_t pid = child->pid; ++ struct timeval tv; ++ static const int buf_size = 1024; ++ char buf[buf_size]; ++ long execute_data; ++ long l; ++ ++ gettimeofday(&tv, 0); ++ ++ zlog_print_time(&tv, buf, buf_size); ++ ++ fprintf(slowlog, "\n%s pid %d (pool %s)\n", buf, (int) pid, child->wp->config->name); ++ ++ if (0 > fpm_trace_get_strz(buf, buf_size, (long) &SG(request_info).path_translated)) { ++ return -1; ++ } ++ ++ fprintf(slowlog, "script_filename = %s\n", buf); ++ ++ if (0 > fpm_trace_get_long((long) &EG(current_execute_data), &l)) { ++ return -1; ++ } ++ ++ execute_data = l; ++ ++ while (execute_data) { ++ long function; ++ uint lineno = 0; ++ ++ fprintf(slowlog, "[0x%" PTR_FMT "lx] ", execute_data); ++ ++ if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, function_state.function), &l)) { ++ return -1; ++ } ++ ++ function = l; ++ ++ if (valid_ptr(function)) { ++ if (0 > fpm_trace_get_strz(buf, buf_size, function + offsetof(zend_function, common.function_name))) { ++ return -1; ++ } ++ ++ fprintf(slowlog, "%s()", buf); ++ } ++ else { ++ fprintf(slowlog, "???"); ++ } ++ ++ if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, op_array), &l)) { ++ return -1; ++ } ++ ++ *buf = '\0'; ++ ++ if (valid_ptr(l)) { ++ long op_array = l; ++ ++ if (0 > fpm_trace_get_strz(buf, buf_size, op_array + offsetof(zend_op_array, filename))) { ++ return -1; ++ } ++ } ++ ++ if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, opline), &l)) { ++ return -1; ++ } ++ ++ if (valid_ptr(l)) { ++ long opline = l; ++ uint *lu = (uint *) &l; ++ ++ if (0 > fpm_trace_get_long(opline + offsetof(struct _zend_op, lineno), &l)) { ++ return -1; ++ } ++ ++ lineno = *lu; ++ } ++ ++ fprintf(slowlog, " %s:%u\n", *buf ? buf : "unknown", lineno); ++ ++ if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, prev_execute_data), &l)) { ++ return -1; ++ } ++ ++ execute_data = l; ++ ++ if (0 == --callers_limit) { ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++void fpm_php_trace(struct fpm_child_s *child) ++{ ++ TSRMLS_FETCH(); ++ FILE *slowlog; ++ ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "about to trace %d", (int) child->pid); ++ ++ slowlog = fopen(child->wp->config->slowlog, "a+"); ++ ++ if (!slowlog) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fopen(%s) failed", child->wp->config->slowlog); ++ goto done0; ++ } ++ ++ if (0 > fpm_trace_ready(child->pid)) { ++ goto done1; ++ } ++ ++ if (0 > fpm_php_trace_dump(child, slowlog TSRMLS_CC)) { ++ fprintf(slowlog, "+++ dump failed\n"); ++ } ++ ++ if (0 > fpm_trace_close(child->pid)) { ++ goto done1; ++ } ++ ++done1: ++ fclose(slowlog); ++ ++done0: ++ fpm_pctl_kill(child->pid, FPM_PCTL_CONT); ++ child->tracer = 0; ++ ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "finished trace of %d", (int) child->pid); ++} ++ ++#endif ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_php_trace.h php-src/sapi/fpm/fpm/fpm_php_trace.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_php_trace.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_php_trace.h 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,13 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_PHP_TRACE_H ++#define FPM_PHP_TRACE_H 1 ++ ++struct fpm_child_s; ++ ++void fpm_php_trace(struct fpm_child_s *); ++ ++#endif ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_process_ctl.c php-src/sapi/fpm/fpm/fpm_process_ctl.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_process_ctl.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_process_ctl.c 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,354 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#include ++#include ++#include ++#include ++ ++#include "fpm.h" ++#include "fpm_clock.h" ++#include "fpm_children.h" ++#include "fpm_signals.h" ++#include "fpm_events.h" ++#include "fpm_process_ctl.h" ++#include "fpm_cleanup.h" ++#include "fpm_request.h" ++#include "fpm_worker_pool.h" ++#include "zlog.h" ++ ++ ++static int fpm_state = FPM_PCTL_STATE_NORMAL; ++static int fpm_signal_sent = 0; ++ ++ ++static const char *fpm_state_names[] = { ++ [FPM_PCTL_STATE_NORMAL] = "normal", ++ [FPM_PCTL_STATE_RELOADING] = "reloading", ++ [FPM_PCTL_STATE_TERMINATING] = "terminating", ++ [FPM_PCTL_STATE_FINISHING] = "finishing" ++}; ++ ++static int saved_argc; ++static char **saved_argv; ++ ++static void fpm_pctl_cleanup(int which, void *arg) ++{ ++ int i; ++ ++ if (which != FPM_CLEANUP_PARENT_EXEC) { ++ ++ for (i = 0; i < saved_argc; i++) { ++ free(saved_argv[i]); ++ } ++ ++ free(saved_argv); ++ ++ } ++} ++ ++static struct event pctl_event; ++ ++static void fpm_pctl_action(int fd, short which, void *arg) ++{ ++ evtimer_del(&pctl_event); ++ ++ memset(&pctl_event, 0, sizeof(pctl_event)); ++ ++ fpm_pctl(FPM_PCTL_STATE_UNSPECIFIED, FPM_PCTL_ACTION_TIMEOUT); ++} ++ ++static int fpm_pctl_timeout_set(int sec) ++{ ++ struct timeval tv = { .tv_sec = sec, .tv_usec = 0 }; ++ ++ if (evtimer_initialized(&pctl_event)) { ++ evtimer_del(&pctl_event); ++ } ++ ++ evtimer_set(&pctl_event, &fpm_pctl_action, 0); ++ ++ evtimer_add(&pctl_event, &tv); ++ ++ return 0; ++} ++ ++static void fpm_pctl_exit() ++{ ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "exiting, bye-bye!"); ++ ++ fpm_conf_unlink_pid(); ++ ++ fpm_cleanups_run(FPM_CLEANUP_PARENT_EXIT_MAIN); ++ ++ exit(0); ++} ++ ++#define optional_arg(c) (saved_argc > c ? ", \"" : ""), (saved_argc > c ? saved_argv[c] : ""), (saved_argc > c ? "\"" : "") ++ ++static void fpm_pctl_exec() ++{ ++ ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "reloading: execvp(\"%s\", {\"%s\"" ++ "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s" ++ "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s" ++ "})", ++ saved_argv[0], saved_argv[0], ++ optional_arg(1), ++ optional_arg(2), ++ optional_arg(3), ++ optional_arg(4), ++ optional_arg(5), ++ optional_arg(6), ++ optional_arg(7), ++ optional_arg(8), ++ optional_arg(9), ++ optional_arg(10) ++ ); ++ ++ fpm_cleanups_run(FPM_CLEANUP_PARENT_EXEC); ++ ++ execvp(saved_argv[0], saved_argv); ++ ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "execvp() failed"); ++ ++ exit(1); ++} ++ ++static void fpm_pctl_action_last() ++{ ++ switch (fpm_state) { ++ ++ case FPM_PCTL_STATE_RELOADING : ++ ++ fpm_pctl_exec(); ++ break; ++ ++ case FPM_PCTL_STATE_FINISHING : ++ ++ case FPM_PCTL_STATE_TERMINATING : ++ ++ fpm_pctl_exit(); ++ break; ++ } ++} ++ ++int fpm_pctl_kill(pid_t pid, int how) ++{ ++ int s = 0; ++ ++ switch (how) { ++ case FPM_PCTL_TERM : ++ s = SIGTERM; ++ break; ++ case FPM_PCTL_STOP : ++ s = SIGSTOP; ++ break; ++ case FPM_PCTL_CONT : ++ s = SIGCONT; ++ break; ++ default : ++ break; ++ } ++ ++ return kill(pid, s); ++} ++ ++static void fpm_pctl_kill_all(int signo) ++{ ++ struct fpm_worker_pool_s *wp; ++ int alive_children = 0; ++ ++ for (wp = fpm_worker_all_pools; wp; wp = wp->next) { ++ struct fpm_child_s *child; ++ ++ for (child = wp->children; child; child = child->next) { ++ ++ int res = kill(child->pid, signo); ++ ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "sending signal %d %s to child %d (pool %s)", signo, ++ fpm_signal_names[signo] ? fpm_signal_names[signo] : "", ++ (int) child->pid, child->wp->config->name); ++ ++ if (res == 0) { ++alive_children; } ++ } ++ } ++ ++ if (alive_children) { ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "%d %s still alive", alive_children, alive_children == 1 ? "child is" : "children are"); ++ } ++} ++ ++static void fpm_pctl_action_next() ++{ ++ int sig, timeout; ++ ++ if (!fpm_globals.running_children) { fpm_pctl_action_last(); } ++ ++ if (fpm_signal_sent == 0) { ++ if (fpm_state == FPM_PCTL_STATE_TERMINATING) { ++ sig = SIGTERM; ++ } ++ else { ++ sig = SIGQUIT; ++ } ++ timeout = fpm_global_config.process_control_timeout; ++ } ++ else { ++ if (fpm_signal_sent == SIGQUIT) { ++ sig = SIGTERM; ++ } ++ else { ++ sig = SIGKILL; ++ } ++ timeout = 1; ++ } ++ ++ fpm_pctl_kill_all(sig); ++ ++ fpm_signal_sent = sig; ++ ++ fpm_pctl_timeout_set(timeout); ++} ++ ++void fpm_pctl(int new_state, int action) ++{ ++ switch (action) { ++ ++ case FPM_PCTL_ACTION_SET : ++ ++ if (fpm_state == new_state) { /* already in progress - just ignore duplicate signal */ ++ return; ++ } ++ ++ switch (fpm_state) { /* check which states can be overridden */ ++ ++ case FPM_PCTL_STATE_NORMAL : ++ ++ /* 'normal' can be overridden by any other state */ ++ break; ++ ++ case FPM_PCTL_STATE_RELOADING : ++ ++ /* 'reloading' can be overridden by 'finishing' */ ++ if (new_state == FPM_PCTL_STATE_FINISHING) { break; } ++ ++ case FPM_PCTL_STATE_FINISHING : ++ ++ /* 'reloading' and 'finishing' can be overridden by 'terminating' */ ++ if (new_state == FPM_PCTL_STATE_TERMINATING) { break; } ++ ++ case FPM_PCTL_STATE_TERMINATING : ++ ++ /* nothing can override 'terminating' state */ ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "not switching to '%s' state, because already in '%s' state", ++ fpm_state_names[new_state], fpm_state_names[fpm_state]); ++ ++ return; ++ } ++ ++ fpm_signal_sent = 0; ++ fpm_state = new_state; ++ ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "switching to '%s' state", fpm_state_names[fpm_state]); ++ ++ /* fall down */ ++ ++ case FPM_PCTL_ACTION_TIMEOUT : ++ ++ fpm_pctl_action_next(); ++ ++ break; ++ ++ case FPM_PCTL_ACTION_LAST_CHILD_EXITED : ++ ++ fpm_pctl_action_last(); ++ ++ break; ++ ++ } ++} ++ ++int fpm_pctl_can_spawn_children() ++{ ++ return fpm_state == FPM_PCTL_STATE_NORMAL; ++} ++ ++int fpm_pctl_child_exited() ++{ ++ if (fpm_state == FPM_PCTL_STATE_NORMAL) { return 0; } ++ ++ if (!fpm_globals.running_children) { ++ fpm_pctl(FPM_PCTL_STATE_UNSPECIFIED, FPM_PCTL_ACTION_LAST_CHILD_EXITED); ++ } ++ ++ return 0; ++} ++ ++int fpm_pctl_init_main() ++{ ++ int i; ++ ++ saved_argc = fpm_globals.argc; ++ ++ saved_argv = malloc(sizeof(char *) * (saved_argc + 1)); ++ ++ if (!saved_argv) { ++ return -1; ++ } ++ ++ for (i = 0; i < saved_argc; i++) { ++ saved_argv[i] = strdup(fpm_globals.argv[i]); ++ ++ if (!saved_argv[i]) { ++ return -1; ++ } ++ } ++ ++ saved_argv[i] = 0; ++ ++ if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_pctl_cleanup, 0)) { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static void fpm_pctl_check_request_timeout(struct timeval *now) ++{ ++ struct fpm_worker_pool_s *wp; ++ ++ for (wp = fpm_worker_all_pools; wp; wp = wp->next) { ++ int terminate_timeout = wp->config->request_terminate_timeout; ++ int slowlog_timeout = wp->config->request_slowlog_timeout; ++ struct fpm_child_s *child; ++ ++ if (terminate_timeout || slowlog_timeout) { ++ for (child = wp->children; child; child = child->next) { ++ fpm_request_check_timed_out(child, now, terminate_timeout, slowlog_timeout); ++ } ++ } ++ } ++ ++} ++ ++void fpm_pctl_heartbeat(int fd, short which, void *arg) ++{ ++ static struct event heartbeat; ++ struct timeval tv = { .tv_sec = 0, .tv_usec = 130000 }; ++ struct timeval now; ++ ++ if (which == EV_TIMEOUT) { ++ evtimer_del(&heartbeat); ++ fpm_clock_get(&now); ++ fpm_pctl_check_request_timeout(&now); ++ } ++ ++ evtimer_set(&heartbeat, &fpm_pctl_heartbeat, 0); ++ ++ evtimer_add(&heartbeat, &tv); ++} ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_process_ctl.h php-src/sapi/fpm/fpm/fpm_process_ctl.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_process_ctl.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_process_ctl.h 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,39 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_PROCESS_CTL_H ++#define FPM_PROCESS_CTL_H 1 ++ ++struct fpm_child_s; ++ ++void fpm_pctl(int new_state, int action); ++int fpm_pctl_can_spawn_children(); ++int fpm_pctl_kill(pid_t pid, int how); ++void fpm_pctl_heartbeat(int fd, short which, void *arg); ++int fpm_pctl_child_exited(); ++int fpm_pctl_init_main(); ++ ++ ++enum { ++ FPM_PCTL_STATE_UNSPECIFIED, ++ FPM_PCTL_STATE_NORMAL, ++ FPM_PCTL_STATE_RELOADING, ++ FPM_PCTL_STATE_TERMINATING, ++ FPM_PCTL_STATE_FINISHING ++}; ++ ++enum { ++ FPM_PCTL_ACTION_SET, ++ FPM_PCTL_ACTION_TIMEOUT, ++ FPM_PCTL_ACTION_LAST_CHILD_EXITED ++}; ++ ++enum { ++ FPM_PCTL_TERM, ++ FPM_PCTL_STOP, ++ FPM_PCTL_CONT ++}; ++ ++#endif ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_request.c php-src/sapi/fpm/fpm/fpm_request.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_request.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_request.c 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,164 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#include "fpm_php.h" ++#include "fpm_str.h" ++#include "fpm_clock.h" ++#include "fpm_conf.h" ++#include "fpm_trace.h" ++#include "fpm_php_trace.h" ++#include "fpm_process_ctl.h" ++#include "fpm_children.h" ++#include "fpm_shm_slots.h" ++#include "fpm_request.h" ++ ++#include "zlog.h" ++ ++void fpm_request_accepting() ++{ ++ struct fpm_shm_slot_s *slot; ++ ++ slot = fpm_shm_slots_acquire(0, 0); ++ ++ slot->request_stage = FPM_REQUEST_ACCEPTING; ++ ++ fpm_clock_get(&slot->tv); ++ memset(slot->request_method, 0, sizeof(slot->request_method)); ++ slot->content_length = 0; ++ memset(slot->script_filename, 0, sizeof(slot->script_filename)); ++ ++ fpm_shm_slots_release(slot); ++} ++ ++void fpm_request_reading_headers() ++{ ++ struct fpm_shm_slot_s *slot; ++ ++ slot = fpm_shm_slots_acquire(0, 0); ++ ++ slot->request_stage = FPM_REQUEST_READING_HEADERS; ++ ++ fpm_clock_get(&slot->tv); ++ slot->accepted = slot->tv; ++ ++ fpm_shm_slots_release(slot); ++} ++ ++void fpm_request_info() ++{ ++ TSRMLS_FETCH(); ++ struct fpm_shm_slot_s *slot; ++ char *request_method = fpm_php_request_method(TSRMLS_C); ++ char *script_filename = fpm_php_script_filename(TSRMLS_C); ++ ++ slot = fpm_shm_slots_acquire(0, 0); ++ ++ slot->request_stage = FPM_REQUEST_INFO; ++ ++ fpm_clock_get(&slot->tv); ++ ++ if (request_method) { ++ cpystrn(slot->request_method, request_method, sizeof(slot->request_method)); ++ } ++ ++ slot->content_length = fpm_php_content_length(TSRMLS_C); ++ ++ /* if cgi.fix_pathinfo is set to "1" and script cannot be found (404) ++ the sapi_globals.request_info.path_translated is set to NULL */ ++ if (script_filename) { ++ cpystrn(slot->script_filename, script_filename, sizeof(slot->script_filename)); ++ } ++ ++ fpm_shm_slots_release(slot); ++} ++ ++void fpm_request_executing() ++{ ++ struct fpm_shm_slot_s *slot; ++ ++ slot = fpm_shm_slots_acquire(0, 0); ++ ++ slot->request_stage = FPM_REQUEST_EXECUTING; ++ ++ fpm_clock_get(&slot->tv); ++ ++ fpm_shm_slots_release(slot); ++} ++ ++void fpm_request_finished() ++{ ++ struct fpm_shm_slot_s *slot; ++ ++ slot = fpm_shm_slots_acquire(0, 0); ++ ++ slot->request_stage = FPM_REQUEST_FINISHED; ++ ++ fpm_clock_get(&slot->tv); ++ memset(&slot->accepted, 0, sizeof(slot->accepted)); ++ ++ fpm_shm_slots_release(slot); ++} ++ ++void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *now, int terminate_timeout, int slowlog_timeout) ++{ ++ struct fpm_shm_slot_s *slot; ++ struct fpm_shm_slot_s slot_c; ++ ++ slot = fpm_shm_slot(child); ++ ++ if (!fpm_shm_slots_acquire(slot, 1)) { ++ return; ++ } ++ ++ slot_c = *slot; ++ ++ fpm_shm_slots_release(slot); ++ ++#if HAVE_FPM_TRACE ++ if (child->slow_logged.tv_sec) { ++ if (child->slow_logged.tv_sec != slot_c.accepted.tv_sec || child->slow_logged.tv_usec != slot_c.accepted.tv_usec) { ++ child->slow_logged.tv_sec = 0; ++ child->slow_logged.tv_usec = 0; ++ } ++ } ++#endif ++ ++ if (slot_c.request_stage > FPM_REQUEST_ACCEPTING && slot_c.request_stage < FPM_REQUEST_FINISHED) { ++ char purified_script_filename[sizeof(slot_c.script_filename)]; ++ struct timeval tv; ++ ++ timersub(now, &slot_c.accepted, &tv); ++ ++#if HAVE_FPM_TRACE ++ if (child->slow_logged.tv_sec == 0 && slowlog_timeout && ++ slot_c.request_stage == FPM_REQUEST_EXECUTING && tv.tv_sec >= slowlog_timeout) { ++ ++ str_purify_filename(purified_script_filename, slot_c.script_filename, sizeof(slot_c.script_filename)); ++ ++ child->slow_logged = slot_c.accepted; ++ child->tracer = fpm_php_trace; ++ ++ fpm_trace_signal(child->pid); ++ ++ zlog(ZLOG_STUFF, ZLOG_WARNING, "child %d, script '%s' (pool %s) executing too slow (%d.%06d sec), logging", ++ (int) child->pid, purified_script_filename, child->wp->config->name, (int) tv.tv_sec, (int) tv.tv_usec); ++ } ++ ++ else ++#endif ++ if (terminate_timeout && tv.tv_sec >= terminate_timeout) { ++ ++ str_purify_filename(purified_script_filename, slot_c.script_filename, sizeof(slot_c.script_filename)); ++ ++ fpm_pctl_kill(child->pid, FPM_PCTL_TERM); ++ ++ zlog(ZLOG_STUFF, ZLOG_WARNING, "child %d, script '%s' (pool %s) execution timed out (%d.%06d sec), terminating", ++ (int) child->pid, purified_script_filename, child->wp->config->name, (int) tv.tv_sec, (int) tv.tv_usec); ++ } ++ } ++ ++} ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_request.h php-src/sapi/fpm/fpm/fpm_request.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_request.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_request.h 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,27 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_REQUEST_H ++#define FPM_REQUEST_H 1 ++ ++void fpm_request_accepting(); /* hanging in accept() */ ++void fpm_request_reading_headers(); /* start reading fastcgi request from very first byte */ ++void fpm_request_info(); /* not a stage really but a point in the php code, where all request params have become known to sapi */ ++void fpm_request_executing(); /* the script is executing */ ++void fpm_request_finished(); /* request processed: script response have been sent to web server */ ++ ++struct fpm_child_s; ++struct timeval; ++ ++void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *tv, int terminate_timeout, int slowlog_timeout); ++ ++enum fpm_request_stage_e { ++ FPM_REQUEST_ACCEPTING = 1, ++ FPM_REQUEST_READING_HEADERS, ++ FPM_REQUEST_INFO, ++ FPM_REQUEST_EXECUTING, ++ FPM_REQUEST_FINISHED ++}; ++ ++#endif +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_shm.c php-src/sapi/fpm/fpm/fpm_shm.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_shm.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_shm.c 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,100 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#include ++#include ++#include ++ ++#include "fpm_shm.h" ++#include "zlog.h" ++ ++ ++/* MAP_ANON is depricated, but not in macosx */ ++#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) ++#define MAP_ANONYMOUS MAP_ANON ++#endif ++ ++ ++struct fpm_shm_s *fpm_shm_alloc(size_t sz) ++{ ++ struct fpm_shm_s *shm; ++ ++ shm = malloc(sizeof(*shm)); ++ ++ if (!shm) { ++ return 0; ++ } ++ ++ shm->mem = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0); ++ ++ if (!shm->mem) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "mmap(MAP_ANONYMOUS | MAP_SHARED) failed"); ++ free(shm); ++ return 0; ++ } ++ ++ shm->used = 0; ++ shm->sz = sz; ++ ++ return shm; ++} ++ ++static void fpm_shm_free(struct fpm_shm_s *shm, int do_unmap) ++{ ++ if (do_unmap) { ++ munmap(shm->mem, shm->sz); ++ } ++ ++ free(shm); ++} ++ ++void fpm_shm_free_list(struct fpm_shm_s *shm, void *mem) ++{ ++ struct fpm_shm_s *next; ++ ++ for (; shm; shm = next) { ++ next = shm->next; ++ ++ fpm_shm_free(shm, mem != shm->mem); ++ } ++} ++ ++void *fpm_shm_alloc_chunk(struct fpm_shm_s **head, size_t sz, void **mem) ++{ ++ size_t pagesize = getpagesize(); ++ static const size_t cache_line_size = 16; ++ size_t aligned_sz; ++ struct fpm_shm_s *shm; ++ void *ret; ++ ++ sz = (sz + cache_line_size - 1) & -cache_line_size; ++ ++ shm = *head; ++ ++ if (0 == shm || shm->sz - shm->used < sz) { ++ /* allocate one more shm segment */ ++ ++ aligned_sz = (sz + pagesize - 1) & -pagesize; ++ ++ shm = fpm_shm_alloc(aligned_sz); ++ ++ if (!shm) { ++ return 0; ++ } ++ ++ shm->next = *head; ++ if (shm->next) { shm->next->prev = shm; } ++ shm->prev = 0; ++ *head = shm; ++ } ++ ++ *mem = shm->mem; ++ ret = (char *) shm->mem + shm->used; ++ shm->used += sz; ++ ++ return ret; ++} ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_shm.h php-src/sapi/fpm/fpm/fpm_shm.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_shm.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_shm.h 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,22 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_SHM_H ++#define FPM_SHM_H 1 ++ ++struct fpm_shm_s; ++ ++struct fpm_shm_s { ++ struct fpm_shm_s *prev, *next; ++ void *mem; ++ size_t sz; ++ size_t used; ++}; ++ ++struct fpm_shm_s *fpm_shm_alloc(size_t sz); ++void fpm_shm_free_list(struct fpm_shm_s *, void *); ++void *fpm_shm_alloc_chunk(struct fpm_shm_s **head, size_t sz, void **mem); ++ ++#endif ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_shm_slots.c php-src/sapi/fpm/fpm/fpm_shm_slots.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_shm_slots.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_shm_slots.c 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,127 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#include "fpm_atomic.h" ++#include "fpm_worker_pool.h" ++#include "fpm_children.h" ++#include "fpm_shm.h" ++#include "fpm_shm_slots.h" ++#include "zlog.h" ++ ++static void *shm_mem; ++static struct fpm_shm_slot_s *shm_slot; ++ ++int fpm_shm_slots_prepare_slot(struct fpm_child_s *child) ++{ ++ struct fpm_worker_pool_s *wp = child->wp; ++ struct fpm_shm_slot_ptr_s *shm_slot_ptr; ++ ++ child->shm_slot_i = wp->slots_used.used; ++ ++ shm_slot_ptr = fpm_array_push(&wp->slots_used); ++ ++ if (0 == shm_slot_ptr) { ++ return -1; ++ } ++ ++ if (0 == wp->slots_free.used) { ++ shm_slot_ptr->shm_slot = fpm_shm_alloc_chunk(&wp->shm_list, sizeof(struct fpm_shm_slot_s), &shm_slot_ptr->mem); ++ ++ if (!shm_slot_ptr->shm_slot) { ++ return -1; ++ } ++ } ++ else { ++ *shm_slot_ptr = *(struct fpm_shm_slot_ptr_s *) fpm_array_item_last(&wp->slots_free); ++ ++ --wp->slots_free.used; ++ } ++ ++ memset(shm_slot_ptr->shm_slot, 0, sizeof(struct fpm_shm_slot_s)); ++ ++ shm_slot_ptr->child = child; ++ ++ return 0; ++} ++ ++void fpm_shm_slots_discard_slot(struct fpm_child_s *child) ++{ ++ struct fpm_shm_slot_ptr_s *shm_slot_ptr; ++ struct fpm_worker_pool_s *wp = child->wp; ++ int n; ++ ++ shm_slot_ptr = fpm_array_push(&wp->slots_free); ++ ++ if (shm_slot_ptr) { ++ ++ struct fpm_shm_slot_ptr_s *shm_slot_ptr_used; ++ ++ shm_slot_ptr_used = fpm_array_item(&wp->slots_used, child->shm_slot_i); ++ ++ *shm_slot_ptr = *shm_slot_ptr_used; ++ ++ shm_slot_ptr->child = 0; ++ ++ } ++ ++ n = fpm_array_item_remove(&wp->slots_used, child->shm_slot_i); ++ ++ if (n > -1) { ++ shm_slot_ptr = fpm_array_item(&wp->slots_used, n); ++ ++ shm_slot_ptr->child->shm_slot_i = n; ++ } ++} ++ ++void fpm_shm_slots_child_use_slot(struct fpm_child_s *child) ++{ ++ struct fpm_shm_slot_ptr_s *shm_slot_ptr; ++ struct fpm_worker_pool_s *wp = child->wp; ++ ++ shm_slot_ptr = fpm_array_item(&wp->slots_used, child->shm_slot_i); ++ ++ shm_slot = shm_slot_ptr->shm_slot; ++ shm_mem = shm_slot_ptr->mem; ++} ++ ++void fpm_shm_slots_parent_use_slot(struct fpm_child_s *child) ++{ ++ /* nothing to do */ ++} ++ ++void *fpm_shm_slots_mem() ++{ ++ return shm_mem; ++} ++ ++struct fpm_shm_slot_s *fpm_shm_slot(struct fpm_child_s *child) ++{ ++ struct fpm_shm_slot_ptr_s *shm_slot_ptr; ++ struct fpm_worker_pool_s *wp = child->wp; ++ ++ shm_slot_ptr = fpm_array_item(&wp->slots_used, child->shm_slot_i); ++ ++ return shm_slot_ptr->shm_slot; ++} ++ ++struct fpm_shm_slot_s *fpm_shm_slots_acquire(struct fpm_shm_slot_s *s, int nohang) ++{ ++ if (s == 0) { ++ s = shm_slot; ++ } ++ ++ if (0 > fpm_spinlock(&s->lock, nohang)) { ++ return 0; ++ } ++ ++ return s; ++} ++ ++void fpm_shm_slots_release(struct fpm_shm_slot_s *s) ++{ ++ s->lock = 0; ++} ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_shm_slots.h php-src/sapi/fpm/fpm/fpm_shm_slots.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_shm_slots.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_shm_slots.h 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,43 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_SHM_SLOTS_H ++#define FPM_SHM_SLOTS_H 1 ++ ++#include "fpm_atomic.h" ++#include "fpm_worker_pool.h" ++#include "fpm_request.h" ++ ++struct fpm_child_s; ++ ++struct fpm_shm_slot_s { ++ union { ++ atomic_t lock; ++ char dummy[16]; ++ }; ++ enum fpm_request_stage_e request_stage; ++ struct timeval accepted; ++ struct timeval tv; ++ char request_method[16]; ++ size_t content_length; /* used with POST only */ ++ char script_filename[256]; ++}; ++ ++struct fpm_shm_slot_ptr_s { ++ void *mem; ++ struct fpm_shm_slot_s *shm_slot; ++ struct fpm_child_s *child; ++}; ++ ++int fpm_shm_slots_prepare_slot(struct fpm_child_s *child); ++void fpm_shm_slots_discard_slot(struct fpm_child_s *child); ++void fpm_shm_slots_child_use_slot(struct fpm_child_s *child); ++void fpm_shm_slots_parent_use_slot(struct fpm_child_s *child); ++void *fpm_shm_slots_mem(); ++struct fpm_shm_slot_s *fpm_shm_slot(struct fpm_child_s *child); ++struct fpm_shm_slot_s *fpm_shm_slots_acquire(struct fpm_shm_slot_s *, int nohang); ++void fpm_shm_slots_release(struct fpm_shm_slot_s *); ++ ++#endif ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_signals.c php-src/sapi/fpm/fpm/fpm_signals.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_signals.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_signals.c 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,252 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "fpm.h" ++#include "fpm_signals.h" ++#include "fpm_sockets.h" ++#include "fpm_php.h" ++#include "zlog.h" ++ ++static int sp[2]; ++ ++const char *fpm_signal_names[NSIG + 1] = { ++#ifdef SIGHUP ++ [SIGHUP] = "SIGHUP", ++#endif ++#ifdef SIGINT ++ [SIGINT] = "SIGINT", ++#endif ++#ifdef SIGQUIT ++ [SIGQUIT] = "SIGQUIT", ++#endif ++#ifdef SIGILL ++ [SIGILL] = "SIGILL", ++#endif ++#ifdef SIGTRAP ++ [SIGTRAP] = "SIGTRAP", ++#endif ++#ifdef SIGABRT ++ [SIGABRT] = "SIGABRT", ++#endif ++#ifdef SIGEMT ++ [SIGEMT] = "SIGEMT", ++#endif ++#ifdef SIGBUS ++ [SIGBUS] = "SIGBUS", ++#endif ++#ifdef SIGFPE ++ [SIGFPE] = "SIGFPE", ++#endif ++#ifdef SIGKILL ++ [SIGKILL] = "SIGKILL", ++#endif ++#ifdef SIGUSR1 ++ [SIGUSR1] = "SIGUSR1", ++#endif ++#ifdef SIGSEGV ++ [SIGSEGV] = "SIGSEGV", ++#endif ++#ifdef SIGUSR2 ++ [SIGUSR2] = "SIGUSR2", ++#endif ++#ifdef SIGPIPE ++ [SIGPIPE] = "SIGPIPE", ++#endif ++#ifdef SIGALRM ++ [SIGALRM] = "SIGALRM", ++#endif ++#ifdef SIGTERM ++ [SIGTERM] = "SIGTERM", ++#endif ++#ifdef SIGCHLD ++ [SIGCHLD] = "SIGCHLD", ++#endif ++#ifdef SIGCONT ++ [SIGCONT] = "SIGCONT", ++#endif ++#ifdef SIGSTOP ++ [SIGSTOP] = "SIGSTOP", ++#endif ++#ifdef SIGTSTP ++ [SIGTSTP] = "SIGTSTP", ++#endif ++#ifdef SIGTTIN ++ [SIGTTIN] = "SIGTTIN", ++#endif ++#ifdef SIGTTOU ++ [SIGTTOU] = "SIGTTOU", ++#endif ++#ifdef SIGURG ++ [SIGURG] = "SIGURG", ++#endif ++#ifdef SIGXCPU ++ [SIGXCPU] = "SIGXCPU", ++#endif ++#ifdef SIGXFSZ ++ [SIGXFSZ] = "SIGXFSZ", ++#endif ++#ifdef SIGVTALRM ++ [SIGVTALRM] = "SIGVTALRM", ++#endif ++#ifdef SIGPROF ++ [SIGPROF] = "SIGPROF", ++#endif ++#ifdef SIGWINCH ++ [SIGWINCH] = "SIGWINCH", ++#endif ++#ifdef SIGINFO ++ [SIGINFO] = "SIGINFO", ++#endif ++#ifdef SIGIO ++ [SIGIO] = "SIGIO", ++#endif ++#ifdef SIGPWR ++ [SIGPWR] = "SIGPWR", ++#endif ++#ifdef SIGSYS ++ [SIGSYS] = "SIGSYS", ++#endif ++#ifdef SIGWAITING ++ [SIGWAITING] = "SIGWAITING", ++#endif ++#ifdef SIGLWP ++ [SIGLWP] = "SIGLWP", ++#endif ++#ifdef SIGFREEZE ++ [SIGFREEZE] = "SIGFREEZE", ++#endif ++#ifdef SIGTHAW ++ [SIGTHAW] = "SIGTHAW", ++#endif ++#ifdef SIGCANCEL ++ [SIGCANCEL] = "SIGCANCEL", ++#endif ++#ifdef SIGLOST ++ [SIGLOST] = "SIGLOST", ++#endif ++}; ++ ++static void sig_soft_quit(int signo) ++{ ++ int saved_errno = errno; ++ ++ /* closing fastcgi listening socket will force fcgi_accept() exit immediately */ ++ close(0); ++ socket(AF_UNIX, SOCK_STREAM, 0); ++ ++ fpm_php_soft_quit(); ++ ++ errno = saved_errno; ++} ++ ++static void sig_handler(int signo) ++{ ++ static const char sig_chars[NSIG + 1] = { ++ [SIGTERM] = 'T', ++ [SIGINT] = 'I', ++ [SIGUSR1] = '1', ++ [SIGUSR2] = '2', ++ [SIGQUIT] = 'Q', ++ [SIGCHLD] = 'C' ++ }; ++ char s; ++ int saved_errno; ++ ++ if (fpm_globals.parent_pid != getpid()) { ++ /* prevent a signal race condition when child process ++ have not set up it's own signal handler yet */ ++ return; ++ } ++ ++ saved_errno = errno; ++ ++ s = sig_chars[signo]; ++ ++ write(sp[1], &s, sizeof(s)); ++ ++ errno = saved_errno; ++} ++ ++int fpm_signals_init_main() ++{ ++ struct sigaction act; ++ ++ if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "socketpair() failed"); ++ return -1; ++ } ++ ++ if (0 > fd_set_blocked(sp[0], 0) || 0 > fd_set_blocked(sp[1], 0)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fd_set_blocked() failed"); ++ return -1; ++ } ++ ++ if (0 > fcntl(sp[0], F_SETFD, FD_CLOEXEC) || 0 > fcntl(sp[1], F_SETFD, FD_CLOEXEC)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fcntl(F_SETFD, FD_CLOEXEC) failed"); ++ return -1; ++ } ++ ++ memset(&act, 0, sizeof(act)); ++ act.sa_handler = sig_handler; ++ sigfillset(&act.sa_mask); ++ ++ if (0 > sigaction(SIGTERM, &act, 0) || ++ 0 > sigaction(SIGINT, &act, 0) || ++ 0 > sigaction(SIGUSR1, &act, 0) || ++ 0 > sigaction(SIGUSR2, &act, 0) || ++ 0 > sigaction(SIGCHLD, &act, 0) || ++ 0 > sigaction(SIGQUIT, &act, 0)) { ++ ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "sigaction() failed"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int fpm_signals_init_child() ++{ ++ struct sigaction act, act_dfl; ++ ++ memset(&act, 0, sizeof(act)); ++ memset(&act_dfl, 0, sizeof(act_dfl)); ++ ++ act.sa_handler = &sig_soft_quit; ++ act.sa_flags |= SA_RESTART; ++ ++ act_dfl.sa_handler = SIG_DFL; ++ ++ close(sp[0]); ++ close(sp[1]); ++ ++ if (0 > sigaction(SIGTERM, &act_dfl, 0) || ++ 0 > sigaction(SIGINT, &act_dfl, 0) || ++ 0 > sigaction(SIGUSR1, &act_dfl, 0) || ++ 0 > sigaction(SIGUSR2, &act_dfl, 0) || ++ 0 > sigaction(SIGCHLD, &act_dfl, 0) || ++ 0 > sigaction(SIGQUIT, &act, 0)) { ++ ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "sigaction() failed"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int fpm_signals_get_fd() ++{ ++ return sp[0]; ++} +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_signals.h php-src/sapi/fpm/fpm/fpm_signals.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_signals.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_signals.h 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,16 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_SIGNALS_H ++#define FPM_SIGNALS_H 1 ++ ++#include ++ ++int fpm_signals_init_main(); ++int fpm_signals_init_child(); ++int fpm_signals_get_fd(); ++ ++extern const char *fpm_signal_names[NSIG + 1]; ++ ++#endif +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_sockets.c php-src/sapi/fpm/fpm/fpm_sockets.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_sockets.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_sockets.c 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,427 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#ifdef HAVE_ALLOCA_H ++#include ++#endif ++#include ++#include /* for chmod(2) */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "zlog.h" ++#include "fpm_arrays.h" ++#include "fpm_sockets.h" ++#include "fpm_worker_pool.h" ++#include "fpm_unix.h" ++#include "fpm_str.h" ++#include "fpm_env.h" ++#include "fpm_cleanup.h" ++ ++struct listening_socket_s { ++ int refcount; ++ int sock; ++ int type; ++ char *key; ++}; ++ ++static struct fpm_array_s sockets_list; ++ ++static int fpm_sockets_resolve_af_inet(char *node, char *service, struct sockaddr_in *addr) ++{ ++ struct addrinfo *res; ++ struct addrinfo hints; ++ int ret; ++ ++ memset(&hints, 0, sizeof(hints)); ++ ++ hints.ai_family = AF_INET; ++ ++ ret = getaddrinfo(node, service, &hints, &res); ++ ++ if (ret != 0) { ++ zlog(ZLOG_STUFF, ZLOG_ERROR, "can't resolve hostname '%s%s%s': getaddrinfo said: %s%s%s\n", ++ node, service ? ":" : "", service ? service : "", ++ gai_strerror(ret), ret == EAI_SYSTEM ? ", system error: " : "", ret == EAI_SYSTEM ? strerror(errno) : ""); ++ return -1; ++ } ++ ++ *addr = *(struct sockaddr_in *) res->ai_addr; ++ ++ freeaddrinfo(res); ++ ++ return 0; ++} ++ ++enum { FPM_GET_USE_SOCKET = 1, FPM_STORE_SOCKET = 2, FPM_STORE_USE_SOCKET = 3 }; ++ ++static void fpm_sockets_cleanup(int which, void *arg) ++{ ++ int i; ++ char *env_value = 0; ++ int p = 0; ++ struct listening_socket_s *ls = sockets_list.data; ++ ++ for (i = 0; i < sockets_list.used; i++, ls++) { ++ ++ if (which != FPM_CLEANUP_PARENT_EXEC) { ++ ++ close(ls->sock); ++ ++ } ++ else { /* on PARENT EXEC we want socket fds to be inherited through environment variable */ ++ char fd[32]; ++ sprintf(fd, "%d", ls->sock); ++ env_value = realloc(env_value, p + (p ? 1 : 0) + strlen(ls->key) + 1 + strlen(fd) + 1); ++ p += sprintf(env_value + p, "%s%s=%s", p ? "," : "", ls->key, fd); ++ } ++ ++ if (which == FPM_CLEANUP_PARENT_EXIT_MAIN) { ++ ++ if (ls->type == FPM_AF_UNIX) { ++ unlink(ls->key); ++ } ++ ++ } ++ ++ free(ls->key); ++ } ++ ++ if (env_value) { ++ setenv("FPM_SOCKETS", env_value, 1); ++ free(env_value); ++ } ++ ++ fpm_array_free(&sockets_list); ++} ++ ++static int fpm_sockets_hash_op(int sock, struct sockaddr *sa, char *key, int type, int op) ++{ ++ ++ if (key == NULL) { ++ ++ switch (type) { ++ ++ case FPM_AF_INET : { ++ struct sockaddr_in *sa_in = (struct sockaddr_in *) sa; ++ ++ key = alloca(sizeof("xxx.xxx.xxx.xxx:ppppp")); ++ ++ sprintf(key, "%u.%u.%u.%u:%u", IPQUAD(&sa_in->sin_addr), (unsigned int) ntohs(sa_in->sin_port)); ++ ++ break; ++ } ++ ++ case FPM_AF_UNIX : { ++ struct sockaddr_un *sa_un = (struct sockaddr_un *) sa; ++ ++ key = alloca(strlen(sa_un->sun_path) + 1); ++ ++ strcpy(key, sa_un->sun_path); ++ ++ break; ++ } ++ ++ default : ++ ++ return -1; ++ } ++ ++ } ++ ++ switch (op) { ++ ++ case FPM_GET_USE_SOCKET : ++ { ++ ++ int i; ++ struct listening_socket_s *ls = sockets_list.data; ++ ++ for (i = 0; i < sockets_list.used; i++, ls++) { ++ ++ if (!strcmp(ls->key, key)) { ++ ++ls->refcount; ++ return ls->sock; ++ } ++ } ++ ++ break; ++ } ++ ++ case FPM_STORE_SOCKET : /* inherited socket */ ++ case FPM_STORE_USE_SOCKET : /* just created */ ++ { ++ ++ struct listening_socket_s *ls; ++ ++ ls = fpm_array_push(&sockets_list); ++ ++ if (!ls) { ++ break; ++ } ++ ++ if (op == FPM_STORE_SOCKET) { ++ ls->refcount = 0; ++ } ++ else { ++ ls->refcount = 1; ++ } ++ ls->type = type; ++ ls->sock = sock; ++ ls->key = strdup(key); ++ ++ return 0; ++ ++ } ++ } ++ ++ return -1; ++ ++} ++ ++static int fpm_sockets_new_listening_socket(struct fpm_worker_pool_s *wp, struct sockaddr *sa, int socklen) ++{ ++ int backlog = -1; ++ int flags = 1; ++ int sock; ++ mode_t saved_umask; ++ ++ /* we have custom backlog value */ ++ if (wp->config->listen_options) { ++ backlog = wp->config->listen_options->backlog; ++ } ++ ++ sock = socket(sa->sa_family, SOCK_STREAM, 0); ++ ++ if (0 > sock) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "socket() failed"); ++ return -1; ++ } ++ ++ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags)); ++ ++ if (wp->listen_address_domain == FPM_AF_UNIX) { ++ unlink( ((struct sockaddr_un *) sa)->sun_path); ++ } ++ ++ saved_umask = umask(0777 ^ wp->socket_mode); ++ ++ if (0 > bind(sock, sa, socklen)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "bind() for address '%s' failed", wp->config->listen_address); ++ return -1; ++ } ++ ++ if (wp->listen_address_domain == FPM_AF_UNIX) { ++ ++ char *path = ((struct sockaddr_un *) sa)->sun_path; ++ ++ if (wp->socket_uid != -1 || wp->socket_gid != -1) { ++ ++ if (0 > chown(path, wp->socket_uid, wp->socket_gid)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "chown() for address '%s' failed", wp->config->listen_address); ++ return -1; ++ } ++ ++ } ++ ++ } ++ ++ umask(saved_umask); ++ ++ if (0 > listen(sock, backlog)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "listen() for address '%s' failed", wp->config->listen_address); ++ return -1; ++ } ++ ++ return sock; ++} ++ ++static int fpm_sockets_get_listening_socket(struct fpm_worker_pool_s *wp, struct sockaddr *sa, int socklen) ++{ ++ int sock; ++ ++ sock = fpm_sockets_hash_op(0, sa, 0, wp->listen_address_domain, FPM_GET_USE_SOCKET); ++ ++ if (sock >= 0) { return sock; } ++ ++ sock = fpm_sockets_new_listening_socket(wp, sa, socklen); ++ ++ fpm_sockets_hash_op(sock, sa, 0, wp->listen_address_domain, FPM_STORE_USE_SOCKET); ++ ++ return sock; ++} ++ ++enum fpm_address_domain fpm_sockets_domain_from_address(char *address) ++{ ++ if (strchr(address, ':')) { return FPM_AF_INET; } ++ ++ if (strlen(address) == strspn(address, "0123456789")) { return FPM_AF_INET; } ++ ++ return FPM_AF_UNIX; ++} ++ ++static int fpm_socket_af_inet_listening_socket(struct fpm_worker_pool_s *wp) ++{ ++ struct sockaddr_in sa_in; ++ char *dup_address = strdup(wp->config->listen_address); ++ char *port_str = strchr(dup_address, ':'); ++ char *addr = NULL; ++ int port = 0; ++ ++ if (port_str) { /* this is host:port pair */ ++ *port_str++ = '\0'; ++ port = atoi(port_str); ++ addr = dup_address; ++ } ++ else if (strlen(dup_address) == strspn(dup_address, "0123456789")) { /* this is port */ ++ port = atoi(dup_address); ++ port_str = dup_address; ++ } ++ ++ if (port == 0) { ++ zlog(ZLOG_STUFF, ZLOG_ERROR, "invalid port value '%s'", port_str); ++ return -1; ++ } ++ ++ memset(&sa_in, 0, sizeof(sa_in)); ++ ++ if (addr) { ++ ++ sa_in.sin_addr.s_addr = inet_addr(addr); ++ ++ if (sa_in.sin_addr.s_addr == INADDR_NONE) { /* do resolve */ ++ if (0 > fpm_sockets_resolve_af_inet(addr, NULL, &sa_in)) { ++ return -1; ++ } ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "address '%s' resolved as %u.%u.%u.%u", addr, IPQUAD(&sa_in.sin_addr)); ++ } ++ } ++ else { ++ ++ sa_in.sin_addr.s_addr = htonl(INADDR_ANY); ++ ++ } ++ ++ sa_in.sin_family = AF_INET; ++ sa_in.sin_port = htons(port); ++ ++ free(dup_address); ++ ++ return fpm_sockets_get_listening_socket(wp, (struct sockaddr *) &sa_in, sizeof(struct sockaddr_in)); ++} ++ ++static int fpm_socket_af_unix_listening_socket(struct fpm_worker_pool_s *wp) ++{ ++ struct sockaddr_un sa_un; ++ ++ memset(&sa_un, 0, sizeof(sa_un)); ++ ++ cpystrn(sa_un.sun_path, wp->config->listen_address, sizeof(sa_un.sun_path)); ++ sa_un.sun_family = AF_UNIX; ++ ++ return fpm_sockets_get_listening_socket(wp, (struct sockaddr *) &sa_un, sizeof(struct sockaddr_un)); ++} ++ ++int fpm_sockets_init_main() ++{ ++ int i; ++ struct fpm_worker_pool_s *wp; ++ char *inherited = getenv("FPM_SOCKETS"); ++ struct listening_socket_s *ls; ++ ++ if (0 == fpm_array_init(&sockets_list, sizeof(struct listening_socket_s), 10)) { ++ return -1; ++ } ++ ++ /* import inherited sockets */ ++ while (inherited && *inherited) { ++ char *comma = strchr(inherited, ','); ++ int type, fd_no; ++ char *eq; ++ ++ if (comma) { *comma = '\0'; } ++ ++ eq = strchr(inherited, '='); ++ ++ if (eq) { ++ *eq = '\0'; ++ ++ fd_no = atoi(eq + 1); ++ ++ type = fpm_sockets_domain_from_address(inherited); ++ ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "using inherited socket fd=%d, \"%s\"", fd_no, inherited); ++ ++ fpm_sockets_hash_op(fd_no, 0, inherited, type, FPM_STORE_SOCKET); ++ } ++ ++ if (comma) { inherited = comma + 1; } ++ else { inherited = 0; } ++ } ++ ++ /* create all required sockets */ ++ for (wp = fpm_worker_all_pools; wp; wp = wp->next) { ++ ++ if (!wp->is_template) { ++ ++ switch (wp->listen_address_domain) { ++ ++ case FPM_AF_INET : ++ ++ wp->listening_socket = fpm_socket_af_inet_listening_socket(wp); ++ break; ++ ++ case FPM_AF_UNIX : ++ ++ if (0 > fpm_unix_resolve_socket_premissions(wp)) { ++ return -1; ++ } ++ ++ wp->listening_socket = fpm_socket_af_unix_listening_socket(wp); ++ break; ++ ++ } ++ ++ if (wp->listening_socket == -1) { ++ return -1; ++ } ++ } ++ ++ } ++ ++ /* close unused sockets that was inherited */ ++ ls = sockets_list.data; ++ ++ for (i = 0; i < sockets_list.used; ) { ++ ++ if (ls->refcount == 0) { ++ close(ls->sock); ++ if (ls->type == FPM_AF_UNIX) { ++ unlink(ls->key); ++ } ++ free(ls->key); ++ fpm_array_item_remove(&sockets_list, i); ++ } ++ else { ++ ++i; ++ ++ls; ++ } ++ } ++ ++ if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_sockets_cleanup, 0)) { ++ return -1; ++ } ++ ++ return 0; ++} +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_sockets.h php-src/sapi/fpm/fpm/fpm_sockets.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_sockets.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_sockets.h 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,37 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_MISC_H ++#define FPM_MISC_H 1 ++ ++#include ++#include ++ ++#include "fpm_worker_pool.h" ++ ++enum fpm_address_domain fpm_sockets_domain_from_address(char *addr); ++int fpm_sockets_init_main(); ++ ++ ++static inline int fd_set_blocked(int fd, int blocked) ++{ ++ int flags = fcntl(fd, F_GETFL); ++ ++ if (flags < 0) { return -1; } ++ ++ if (blocked) ++ { flags &= ~O_NONBLOCK; } ++ else ++ { flags |= O_NONBLOCK; } ++ ++ return fcntl(fd, F_SETFL, flags); ++} ++ ++#define IPQUAD(sin_addr) \ ++ (unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[0], \ ++ (unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[1], \ ++ (unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[2], \ ++ (unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[3] ++ ++#endif +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_stdio.c php-src/sapi/fpm/fpm/fpm_stdio.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_stdio.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_stdio.c 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,286 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "fpm.h" ++#include "fpm_children.h" ++#include "fpm_events.h" ++#include "fpm_sockets.h" ++#include "fpm_stdio.h" ++#include "zlog.h" ++ ++static int fd_stdout[2]; ++static int fd_stderr[2]; ++ ++int fpm_stdio_init_main() ++{ ++ int fd = open("/dev/null", O_RDWR); ++ ++ if (0 > fd) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "open(\"/dev/null\") failed"); ++ return -1; ++ } ++ ++ if (0 > dup2(fd, STDIN_FILENO) || 0 > dup2(fd, STDOUT_FILENO)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "dup2() failed"); ++ return -1; ++ } ++ ++ close(fd); ++ ++ return 0; ++} ++ ++int fpm_stdio_init_final() ++{ ++ if (fpm_global_config.daemonize) { ++ ++ if (fpm_globals.error_log_fd != STDERR_FILENO) { ++ /* there might be messages to stderr from libevent, we need to log them all */ ++ if (0 > dup2(fpm_globals.error_log_fd, STDERR_FILENO)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "dup2() failed"); ++ return -1; ++ } ++ } ++ ++ zlog_set_level(fpm_globals.log_level); ++ ++ zlog_set_fd(fpm_globals.error_log_fd); ++ } ++ ++ return 0; ++} ++ ++int fpm_stdio_init_child(struct fpm_worker_pool_s *wp) ++{ ++ close(fpm_globals.error_log_fd); ++ fpm_globals.error_log_fd = -1; ++ zlog_set_fd(-1); ++ ++ if (wp->listening_socket != STDIN_FILENO) { ++ if (0 > dup2(wp->listening_socket, STDIN_FILENO)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "dup2() failed"); ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ ++static void fpm_stdio_child_said(int fd, short which, void *arg) ++{ ++ static const int max_buf_size = 1024; ++ char buf[max_buf_size]; ++ struct fpm_child_s *child = arg; ++ int is_stdout = fd == child->fd_stdout; ++ struct event *ev = is_stdout ? &child->ev_stdout : &child->ev_stderr; ++ int fifo_in = 1, fifo_out = 1; ++ int is_last_message = 0; ++ int in_buf = 0; ++ int res; ++ ++#if 0 ++ zlog(ZLOG_STUFF, ZLOG_DEBUG, "child %d said %s", (int) child->pid, is_stdout ? "stdout" : "stderr"); ++#endif ++ ++ while (fifo_in || fifo_out) { ++ ++ if (fifo_in) { ++ ++ res = read(fd, buf + in_buf, max_buf_size - 1 - in_buf); ++ ++ if (res <= 0) { /* no data */ ++ fifo_in = 0; ++ ++ if (res < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) { ++ /* just no more data ready */ ++ } ++ else { /* error or pipe is closed */ ++ ++ if (res < 0) { /* error */ ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "read() failed"); ++ } ++ ++ fpm_event_del(ev); ++ is_last_message = 1; ++ ++ if (is_stdout) { ++ close(child->fd_stdout); ++ child->fd_stdout = -1; ++ } ++ else { ++ close(child->fd_stderr); ++ child->fd_stderr = -1; ++ } ++ ++#if 0 ++ if (in_buf == 0 && !fpm_globals.is_child) { ++ zlog(ZLOG_STUFF, ZLOG_DEBUG, "child %d (pool %s) %s pipe is closed", (int) child->pid, ++ child->wp->config->name, is_stdout ? "stdout" : "stderr"); ++ } ++#endif ++ } ++ } ++ else { ++ in_buf += res; ++ } ++ } ++ ++ if (fifo_out) { ++ if (in_buf == 0) { ++ fifo_out = 0; ++ } ++ else { ++ char *nl; ++ int should_print = 0; ++ buf[in_buf] = '\0'; ++ ++ /* FIXME: there might be binary data */ ++ ++ /* we should print if no more space in the buffer */ ++ if (in_buf == max_buf_size - 1) { ++ should_print = 1; ++ } ++ ++ /* we should print if no more data to come */ ++ if (!fifo_in) { ++ should_print = 1; ++ } ++ ++ nl = strchr(buf, '\n'); ++ ++ if (nl || should_print) { ++ ++ if (nl) { ++ *nl = '\0'; ++ } ++ ++ zlog(ZLOG_STUFF, ZLOG_WARNING, "child %d (pool %s) said into %s: \"%s\"%s", (int) child->pid, ++ child->wp->config->name, is_stdout ? "stdout" : "stderr", buf, is_last_message ? ", pipe is closed" : ""); ++ ++ if (nl) { ++ int out_buf = 1 + nl - buf; ++ memmove(buf, buf + out_buf, in_buf - out_buf); ++ in_buf -= out_buf; ++ } ++ else { ++ in_buf = 0; ++ } ++ } ++ } ++ } ++ } ++ ++} ++ ++int fpm_stdio_prepare_pipes(struct fpm_child_s *child) ++{ ++ if (0 == child->wp->config->catch_workers_output) { /* not required */ ++ return 0; ++ } ++ ++ if (0 > pipe(fd_stdout)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "pipe() failed"); ++ return -1; ++ } ++ ++ if (0 > pipe(fd_stderr)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "pipe() failed"); ++ close(fd_stdout[0]); close(fd_stdout[1]); ++ return -1; ++ } ++ ++ if (0 > fd_set_blocked(fd_stdout[0], 0) || 0 > fd_set_blocked(fd_stderr[0], 0)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fd_set_blocked() failed"); ++ close(fd_stdout[0]); close(fd_stdout[1]); ++ close(fd_stderr[0]); close(fd_stderr[1]); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int fpm_stdio_parent_use_pipes(struct fpm_child_s *child) ++{ ++ if (0 == child->wp->config->catch_workers_output) { /* not required */ ++ return 0; ++ } ++ ++ close(fd_stdout[1]); ++ close(fd_stderr[1]); ++ ++ child->fd_stdout = fd_stdout[0]; ++ child->fd_stderr = fd_stderr[0]; ++ ++ fpm_event_add(child->fd_stdout, &child->ev_stdout, fpm_stdio_child_said, child); ++ fpm_event_add(child->fd_stderr, &child->ev_stderr, fpm_stdio_child_said, child); ++ ++ return 0; ++} ++ ++int fpm_stdio_discard_pipes(struct fpm_child_s *child) ++{ ++ if (0 == child->wp->config->catch_workers_output) { /* not required */ ++ return 0; ++ } ++ ++ close(fd_stdout[1]); ++ close(fd_stderr[1]); ++ ++ close(fd_stdout[0]); ++ close(fd_stderr[0]); ++ ++ return 0; ++} ++ ++void fpm_stdio_child_use_pipes(struct fpm_child_s *child) ++{ ++ if (child->wp->config->catch_workers_output) { ++ dup2(fd_stdout[1], STDOUT_FILENO); ++ dup2(fd_stderr[1], STDERR_FILENO); ++ close(fd_stdout[0]); close(fd_stdout[1]); ++ close(fd_stderr[0]); close(fd_stderr[1]); ++ } ++ else { ++ /* stdout of parent is always /dev/null */ ++ dup2(STDOUT_FILENO, STDERR_FILENO); ++ } ++} ++ ++int fpm_stdio_open_error_log(int reopen) ++{ ++ int fd; ++ ++ fd = open(fpm_global_config.error_log, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR); ++ ++ if (0 > fd) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "open(\"%s\") failed", fpm_global_config.error_log); ++ return -1; ++ } ++ ++ if (reopen) { ++ if (fpm_global_config.daemonize) { ++ dup2(fd, STDERR_FILENO); ++ } ++ ++ dup2(fd, fpm_globals.error_log_fd); ++ close(fd); ++ fd = fpm_globals.error_log_fd; /* for FD_CLOSEXEC to work */ ++ } ++ else { ++ fpm_globals.error_log_fd = fd; ++ } ++ ++ fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); ++ ++ return 0; ++} +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_stdio.h php-src/sapi/fpm/fpm/fpm_stdio.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_stdio.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_stdio.h 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,20 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_STDIO_H ++#define FPM_STDIO_H 1 ++ ++#include "fpm_worker_pool.h" ++ ++int fpm_stdio_init_main(); ++int fpm_stdio_init_final(); ++int fpm_stdio_init_child(struct fpm_worker_pool_s *wp); ++int fpm_stdio_prepare_pipes(struct fpm_child_s *child); ++void fpm_stdio_child_use_pipes(struct fpm_child_s *child); ++int fpm_stdio_parent_use_pipes(struct fpm_child_s *child); ++int fpm_stdio_discard_pipes(struct fpm_child_s *child); ++int fpm_stdio_open_error_log(int reopen); ++ ++#endif ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_str.h php-src/sapi/fpm/fpm/fpm_str.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_str.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_str.h 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,49 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_STR_H ++#define FPM_STR_H 1 ++ ++static inline char *cpystrn(char *dst, const char *src, size_t dst_size) ++{ ++ char *d, *end; ++ ++ if (!dst_size) { return dst; } ++ ++ d = dst; ++ end = dst + dst_size - 1; ++ ++ for (; d < end; ++d, ++src) { ++ if (!(*d = *src)) { ++ return d; ++ } ++ } ++ ++ *d = '\0'; ++ ++ return d; ++} ++ ++static inline char *str_purify_filename(char *dst, char *src, size_t size) ++{ ++ char *d, *end; ++ ++ d = dst; ++ end = dst + size - 1; ++ ++ for (; d < end && *src; ++d, ++src) { ++ if (* (unsigned char *) src < ' ' || * (unsigned char *) src > '\x7f') { ++ *d = '.'; ++ } ++ else { ++ *d = *src; ++ } ++ } ++ ++ *d = '\0'; ++ ++ return d; ++} ++ ++#endif +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_trace.c php-src/sapi/fpm/fpm/fpm_trace.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_trace.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_trace.c 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,46 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#include ++ ++#include "fpm_trace.h" ++ ++int fpm_trace_get_strz(char *buf, size_t sz, long addr) ++{ ++ int i; ++ long l; ++ char *lc = (char *) &l; ++ ++ if (0 > fpm_trace_get_long(addr, &l)) { ++ return -1; ++ } ++ ++ i = l % SIZEOF_LONG; ++ ++ l -= i; ++ ++ for (addr = l; ; addr += SIZEOF_LONG) { ++ ++ if (0 > fpm_trace_get_long(addr, &l)) { ++ return -1; ++ } ++ ++ for ( ; i < SIZEOF_LONG; i++) { ++ --sz; ++ ++ if (sz && lc[i]) { ++ *buf++ = lc[i]; ++ continue; ++ } ++ ++ *buf = '\0'; ++ return 0; ++ } ++ ++ i = 0; ++ } ++} ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_trace.h php-src/sapi/fpm/fpm/fpm_trace.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_trace.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_trace.h 2009-10-18 21:05:39.302497288 +0100 +@@ -0,0 +1,17 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_TRACE_H ++#define FPM_TRACE_H 1 ++ ++#include ++ ++int fpm_trace_signal(pid_t pid); ++int fpm_trace_ready(pid_t pid); ++int fpm_trace_close(pid_t pid); ++int fpm_trace_get_long(long addr, long *data); ++int fpm_trace_get_strz(char *buf, size_t sz, long addr); ++ ++#endif ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_trace_mach.c php-src/sapi/fpm/fpm/fpm_trace_mach.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_trace_mach.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_trace_mach.c 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,102 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#include ++#include ++ ++#include ++ ++#include "fpm_trace.h" ++#include "fpm_process_ctl.h" ++#include "fpm_unix.h" ++#include "zlog.h" ++ ++ ++static mach_port_name_t target; ++static vm_offset_t target_page_base; ++static vm_offset_t local_page; ++static mach_msg_type_number_t local_size; ++ ++static void fpm_mach_vm_deallocate() ++{ ++ if (local_page) { ++ mach_vm_deallocate(mach_task_self(), local_page, local_size); ++ target_page_base = 0; ++ local_page = 0; ++ local_size = 0; ++ } ++} ++ ++static int fpm_mach_vm_read_page(vm_offset_t page) ++{ ++ kern_return_t kr; ++ ++ kr = mach_vm_read(target, page, fpm_pagesize, &local_page, &local_size); ++ ++ if (kr != KERN_SUCCESS) { ++ zlog(ZLOG_STUFF, ZLOG_ERROR, "mach_vm_read() failed: %s (%d)", mach_error_string(kr), kr); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int fpm_trace_signal(pid_t pid) ++{ ++ if (0 > fpm_pctl_kill(pid, FPM_PCTL_STOP)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "kill(SIGSTOP) failed"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int fpm_trace_ready(pid_t pid) ++{ ++ kern_return_t kr; ++ ++ kr = task_for_pid(mach_task_self(), pid, &target); ++ ++ if (kr != KERN_SUCCESS) { ++ char *msg = ""; ++ ++ if (kr == KERN_FAILURE) { ++ msg = " It seems that master process does not have enough privileges to trace processes."; ++ } ++ ++ zlog(ZLOG_STUFF, ZLOG_ERROR, "task_for_pid() failed: %s (%d)%s", mach_error_string(kr), kr, msg); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int fpm_trace_close(pid_t pid) ++{ ++ fpm_mach_vm_deallocate(); ++ ++ target = 0; ++ ++ return 0; ++} ++ ++int fpm_trace_get_long(long addr, long *data) ++{ ++ size_t offset = ((uintptr_t) (addr) % fpm_pagesize); ++ vm_offset_t base = (uintptr_t) (addr) - offset; ++ ++ if (base != target_page_base) { ++ fpm_mach_vm_deallocate(); ++ if (0 > fpm_mach_vm_read_page(base)) { ++ return -1; ++ } ++ } ++ ++ *data = * (long *) (local_page + offset); ++ ++ return 0; ++} ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_trace_pread.c php-src/sapi/fpm/fpm/fpm_trace_pread.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_trace_pread.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_trace_pread.c 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,72 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#define _GNU_SOURCE ++#define _FILE_OFFSET_BITS 64 ++ ++#include "fpm_config.h" ++ ++#include ++ ++#include ++#include ++#if HAVE_INTTYPES_H ++#include ++#else ++#include ++#endif ++ ++ ++#include "fpm_trace.h" ++#include "fpm_process_ctl.h" ++#include "zlog.h" ++ ++ ++static int mem_file = -1; ++ ++int fpm_trace_signal(pid_t pid) ++{ ++ if (0 > fpm_pctl_kill(pid, FPM_PCTL_STOP)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "kill(SIGSTOP) failed"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int fpm_trace_ready(pid_t pid) ++{ ++ char buf[128]; ++ ++ sprintf(buf, "/proc/%d/" PROC_MEM_FILE, (int) pid); ++ ++ mem_file = open(buf, O_RDONLY); ++ ++ if (0 > mem_file) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "open(%s) failed", buf); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int fpm_trace_close(pid_t pid) ++{ ++ close(mem_file); ++ ++ mem_file = -1; ++ ++ return 0; ++} ++ ++int fpm_trace_get_long(long addr, long *data) ++{ ++ if (sizeof(*data) != pread(mem_file, (void *) data, sizeof(*data), (uintptr_t) addr)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "pread() failed"); ++ return -1; ++ } ++ ++ return 0; ++} ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_trace_ptrace.c php-src/sapi/fpm/fpm/fpm_trace_ptrace.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_trace_ptrace.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_trace_ptrace.c 2009-10-18 21:05:39.302497288 +0100 +@@ -0,0 +1,85 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#include ++#include ++#include ++#include ++ ++#if defined(PT_ATTACH) && !defined(PTRACE_ATTACH) ++#define PTRACE_ATTACH PT_ATTACH ++#endif ++ ++#if defined(PT_DETACH) && !defined(PTRACE_DETACH) ++#define PTRACE_DETACH PT_DETACH ++#endif ++ ++#if defined(PT_READ_D) && !defined(PTRACE_PEEKDATA) ++#define PTRACE_PEEKDATA PT_READ_D ++#endif ++ ++#include "fpm_trace.h" ++#include "zlog.h" ++ ++static pid_t traced_pid; ++ ++int fpm_trace_signal(pid_t pid) ++{ ++ if (0 > ptrace(PTRACE_ATTACH, pid, 0, 0)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "ptrace(ATTACH) failed"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int fpm_trace_ready(pid_t pid) ++{ ++ traced_pid = pid; ++ ++ return 0; ++} ++ ++int fpm_trace_close(pid_t pid) ++{ ++ if (0 > ptrace(PTRACE_DETACH, pid, (void *) 1, 0)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "ptrace(DETACH) failed"); ++ return -1; ++ } ++ ++ traced_pid = 0; ++ ++ return 0; ++} ++ ++int fpm_trace_get_long(long addr, long *data) ++{ ++#ifdef PT_IO ++ struct ptrace_io_desc ptio = { ++ .piod_op = PIOD_READ_D, ++ .piod_offs = (void *) addr, ++ .piod_addr = (void *) data, ++ .piod_len = sizeof(long) ++ }; ++ ++ if (0 > ptrace(PT_IO, traced_pid, (void *) &ptio, 0)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "ptrace(PT_IO) failed"); ++ return -1; ++ } ++#else ++ errno = 0; ++ ++ *data = ptrace(PTRACE_PEEKDATA, traced_pid, (void *) addr, 0); ++ ++ if (errno) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "ptrace(PEEKDATA) failed"); ++ return -1; ++ } ++#endif ++ ++ return 0; ++} ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_unix.c php-src/sapi/fpm/fpm/fpm_unix.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_unix.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_unix.c 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,289 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef HAVE_PRCTL ++#include ++#endif ++ ++#include "fpm.h" ++#include "fpm_conf.h" ++#include "fpm_cleanup.h" ++#include "fpm_clock.h" ++#include "fpm_stdio.h" ++#include "fpm_unix.h" ++#include "zlog.h" ++ ++size_t fpm_pagesize; ++ ++int fpm_unix_resolve_socket_premissions(struct fpm_worker_pool_s *wp) ++{ ++ struct fpm_listen_options_s *lo = wp->config->listen_options; ++ ++ /* uninitialized */ ++ wp->socket_uid = -1; ++ wp->socket_gid = -1; ++ wp->socket_mode = 0666; ++ ++ if (!lo) { return 0; } ++ ++ if (lo->owner && *lo->owner) { ++ struct passwd *pwd; ++ ++ pwd = getpwnam(lo->owner); ++ ++ if (!pwd) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "cannot get uid for user '%s', pool '%s'", lo->owner, wp->config->name); ++ return -1; ++ } ++ ++ wp->socket_uid = pwd->pw_uid; ++ wp->socket_gid = pwd->pw_gid; ++ } ++ ++ if (lo->group && *lo->group) { ++ struct group *grp; ++ ++ grp = getgrnam(lo->group); ++ ++ if (!grp) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "cannot get gid for group '%s', pool '%s'", lo->group, wp->config->name); ++ return -1; ++ } ++ ++ wp->socket_gid = grp->gr_gid; ++ } ++ ++ if (lo->mode && *lo->mode) { ++ wp->socket_mode = strtoul(lo->mode, 0, 8); ++ } ++ ++ return 0; ++} ++ ++static int fpm_unix_conf_wp(struct fpm_worker_pool_s *wp) ++{ ++ int is_root = !geteuid(); ++ ++ if (is_root) { ++ if (wp->config->user && *wp->config->user) { ++ ++ if (strlen(wp->config->user) == strspn(wp->config->user, "0123456789")) { ++ wp->set_uid = strtoul(wp->config->user, 0, 10); ++ } ++ else { ++ struct passwd *pwd; ++ ++ pwd = getpwnam(wp->config->user); ++ ++ if (!pwd) { ++ zlog(ZLOG_STUFF, ZLOG_ERROR, "cannot get uid for user '%s', pool '%s'", wp->config->user, wp->config->name); ++ return -1; ++ } ++ ++ wp->set_uid = pwd->pw_uid; ++ wp->set_gid = pwd->pw_gid; ++ ++ wp->user = strdup(pwd->pw_name); ++ wp->home = strdup(pwd->pw_dir); ++ } ++ } ++ ++ if (wp->config->group && *wp->config->group) { ++ ++ if (strlen(wp->config->group) == strspn(wp->config->group, "0123456789")) { ++ wp->set_gid = strtoul(wp->config->group, 0, 10); ++ } ++ else { ++ struct group *grp; ++ ++ grp = getgrnam(wp->config->group); ++ ++ if (!grp) { ++ zlog(ZLOG_STUFF, ZLOG_ERROR, "cannot get gid for group '%s', pool '%s'", wp->config->group, wp->config->name); ++ return -1; ++ } ++ ++ wp->set_gid = grp->gr_gid; ++ } ++ } ++ ++#ifndef I_REALLY_WANT_ROOT_PHP ++ if (wp->set_uid == 0 || wp->set_gid == 0) { ++ zlog(ZLOG_STUFF, ZLOG_ERROR, "please specify user and group other than root, pool '%s'", wp->config->name); ++ return -1; ++ } ++#endif ++ } ++ else { /* not root */ ++ if (wp->config->user && *wp->config->user) { ++ zlog(ZLOG_STUFF, ZLOG_WARNING, "'user' directive is ignored, pool '%s'", wp->config->name); ++ } ++ if (wp->config->group && *wp->config->group) { ++ zlog(ZLOG_STUFF, ZLOG_WARNING, "'group' directive is ignored, pool '%s'", wp->config->name); ++ } ++ if (wp->config->chroot && *wp->config->chroot) { ++ zlog(ZLOG_STUFF, ZLOG_WARNING, "'chroot' directive is ignored, pool '%s'", wp->config->name); ++ } ++ ++ { /* set up HOME and USER anyway */ ++ struct passwd *pwd; ++ ++ pwd = getpwuid(getuid()); ++ ++ if (pwd) { ++ wp->user = strdup(pwd->pw_name); ++ wp->home = strdup(pwd->pw_dir); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++int fpm_unix_init_child(struct fpm_worker_pool_s *wp) ++{ ++ int is_root = !geteuid(); ++ int made_chroot = 0; ++ ++ if (wp->config->rlimit_files) { ++ struct rlimit r; ++ ++ getrlimit(RLIMIT_NOFILE, &r); ++ ++ r.rlim_cur = (rlim_t) wp->config->rlimit_files; ++ ++ if (0 > setrlimit(RLIMIT_NOFILE, &r)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "setrlimit(RLIMIT_NOFILE) failed"); ++ } ++ } ++ ++ if (wp->config->rlimit_core) { ++ struct rlimit r; ++ ++ getrlimit(RLIMIT_CORE, &r); ++ ++ r.rlim_cur = wp->config->rlimit_core == -1 ? (rlim_t) RLIM_INFINITY : (rlim_t) wp->config->rlimit_core; ++ ++ if (0 > setrlimit(RLIMIT_CORE, &r)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "setrlimit(RLIMIT_CORE) failed"); ++ } ++ } ++ ++ if (is_root && wp->config->chroot && *wp->config->chroot) { ++ if (0 > chroot(wp->config->chroot)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "chroot(%s) failed", wp->config->chroot); ++ return -1; ++ } ++ made_chroot = 1; ++ } ++ ++ if (wp->config->chdir && *wp->config->chdir) { ++ if (0 > chdir(wp->config->chdir)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "chdir(%s) failed", wp->config->chdir); ++ return -1; ++ } ++ } ++ else if (made_chroot) { ++ chdir("/"); ++ } ++ ++ if (is_root) { ++ if (wp->set_gid) { ++ if (0 > setgid(wp->set_gid)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "setgid(%d) failed", wp->set_gid); ++ return -1; ++ } ++ } ++ if (wp->set_uid) { ++ if (0 > initgroups(wp->config->user, wp->set_gid)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "initgroups(%s, %d) failed", wp->config->user, wp->set_gid); ++ return -1; ++ } ++ if (0 > setuid(wp->set_uid)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "setuid(%d) failed", wp->set_uid); ++ return -1; ++ } ++ } ++ } ++ ++#ifdef HAVE_PRCTL ++ if (0 > prctl(PR_SET_DUMPABLE, 1, 0, 0, 0)) { ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "prctl(PR_SET_DUMPABLE) failed"); ++ } ++#endif ++ ++ if (0 > fpm_clock_init()) { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int fpm_unix_init_main() ++{ ++ struct fpm_worker_pool_s *wp; ++ ++ fpm_pagesize = getpagesize(); ++ ++ if (fpm_global_config.daemonize) { ++ ++ switch (fork()) { ++ ++ case -1 : ++ ++ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fork() failed"); ++ return -1; ++ ++ case 0 : ++ ++ break; ++ ++ default : ++ ++ fpm_cleanups_run(FPM_CLEANUP_PARENT_EXIT); ++ exit(0); ++ ++ } ++ ++ } ++ ++ setsid(); ++ ++ if (0 > fpm_clock_init()) { ++ return -1; ++ } ++ ++ fpm_globals.parent_pid = getpid(); ++ ++ for (wp = fpm_worker_all_pools; wp; wp = wp->next) { ++ ++ if (0 > fpm_unix_conf_wp(wp)) { ++ return -1; ++ } ++ ++ } ++ ++ fpm_stdio_init_final(); ++ ++ { ++ struct rlimit r; ++ getrlimit(RLIMIT_NOFILE, &r); ++ ++ zlog(ZLOG_STUFF, ZLOG_NOTICE, "getrlimit(nofile): max:%lld, cur:%lld", ++ (long long) r.rlim_max, (long long) r.rlim_cur); ++ } ++ ++ return 0; ++} +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_unix.h php-src/sapi/fpm/fpm/fpm_unix.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_unix.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_unix.h 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,17 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_UNIX_H ++#define FPM_UNIX_H 1 ++ ++#include "fpm_worker_pool.h" ++ ++int fpm_unix_resolve_socket_premissions(struct fpm_worker_pool_s *wp); ++int fpm_unix_init_child(struct fpm_worker_pool_s *wp); ++int fpm_unix_init_main(); ++ ++extern size_t fpm_pagesize; ++ ++#endif ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_worker_pool.c php-src/sapi/fpm/fpm/fpm_worker_pool.c +--- php-src-vanilla/sapi/fpm/fpm/fpm_worker_pool.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_worker_pool.c 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,69 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#include ++#include ++#include ++ ++#include "fpm_worker_pool.h" ++#include "fpm_cleanup.h" ++#include "fpm_children.h" ++#include "fpm_shm.h" ++#include "fpm_shm_slots.h" ++#include "fpm_conf.h" ++ ++struct fpm_worker_pool_s *fpm_worker_all_pools; ++ ++static void fpm_worker_pool_cleanup(int which, void *arg) ++{ ++ struct fpm_worker_pool_s *wp, *wp_next; ++ ++ for (wp = fpm_worker_all_pools; wp; wp = wp_next) { ++ wp_next = wp->next; ++ fpm_worker_pool_config_free(wp->config); ++ fpm_children_free(wp->children); ++ fpm_array_free(&wp->slots_used); ++ fpm_array_free(&wp->slots_free); ++ fpm_shm_free_list(wp->shm_list, which == FPM_CLEANUP_CHILD ? fpm_shm_slots_mem() : 0); ++ free(wp->config); ++ free(wp->user); ++ free(wp->home); ++ free(wp); ++ } ++ ++ fpm_worker_all_pools = 0; ++} ++ ++struct fpm_worker_pool_s *fpm_worker_pool_alloc() ++{ ++ struct fpm_worker_pool_s *ret; ++ ++ ret = malloc(sizeof(struct fpm_worker_pool_s)); ++ ++ if (!ret) { ++ return 0; ++ } ++ ++ memset(ret, 0, sizeof(struct fpm_worker_pool_s)); ++ ++ if (!fpm_worker_all_pools) { ++ fpm_worker_all_pools = ret; ++ } ++ ++ fpm_array_init(&ret->slots_used, sizeof(struct fpm_shm_slot_ptr_s), 50); ++ fpm_array_init(&ret->slots_free, sizeof(struct fpm_shm_slot_ptr_s), 50); ++ ++ return ret; ++} ++ ++int fpm_worker_pool_init_main() ++{ ++ if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_worker_pool_cleanup, 0)) { ++ return -1; ++ } ++ ++ return 0; ++} +diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_worker_pool.h php-src/sapi/fpm/fpm/fpm_worker_pool.h +--- php-src-vanilla/sapi/fpm/fpm/fpm_worker_pool.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/fpm_worker_pool.h 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,46 @@ ++ ++ /* $Id$ */ ++ /* (c) 2007,2008 Andrei Nigmatulin */ ++ ++#ifndef FPM_WORKER_POOL_H ++#define FPM_WORKER_POOL_H 1 ++ ++#include "fpm_conf.h" ++#include "fpm_arrays.h" ++ ++struct fpm_worker_pool_s; ++struct fpm_child_s; ++struct fpm_child_stat_s; ++struct fpm_shm_s; ++ ++enum fpm_address_domain { ++ FPM_AF_UNIX = 1, ++ FPM_AF_INET = 2 ++}; ++ ++struct fpm_worker_pool_s { ++ struct fpm_worker_pool_s *next; ++ struct fpm_worker_pool_config_s *config; ++ char *user, *home; /* for setting env USER and HOME */ ++ enum fpm_address_domain listen_address_domain; ++ int listening_socket; ++ int set_uid, set_gid; /* config uid and gid */ ++ unsigned is_template:1; /* just config template, no processes will be created */ ++ int socket_uid, socket_gid, socket_mode; ++ ++ struct fpm_shm_s *shm_list; ++ struct fpm_array_s slots_used; ++ struct fpm_array_s slots_free; ++ ++ /* runtime */ ++ struct fpm_child_s *children; ++ int running_children; ++}; ++ ++struct fpm_worker_pool_s *fpm_worker_pool_alloc(); ++int fpm_worker_pool_init_main(); ++ ++extern struct fpm_worker_pool_s *fpm_worker_all_pools; ++ ++#endif ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/xml_config.c php-src/sapi/fpm/fpm/xml_config.c +--- php-src-vanilla/sapi/fpm/fpm/xml_config.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/xml_config.c 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,278 @@ ++ ++ /* $Id$ */ ++ /* (c) 2004-2007 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#ifdef HAVE_ALLOCA_H ++#include ++#endif ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "xml_config.h" ++ ++static struct xml_conf_section **xml_conf_sections = 0; ++static int xml_conf_sections_allocated = 0; ++static int xml_conf_sections_used = 0; ++ ++char *xml_conf_set_slot_boolean(void **conf, char *name, void *vv, intptr_t offset) ++{ ++ char *value = vv; ++ long value_y = !strcasecmp(value, "yes") || !strcmp(value, "1") || !strcasecmp(value, "on"); ++ long value_n = !strcasecmp(value, "no") || !strcmp(value, "0") || !strcasecmp(value, "off"); ++ ++ if (!value_y && !value_n) { ++ return "xml_conf_set_slot(): invalid boolean value"; ++ } ++ ++#ifdef XML_CONF_DEBUG ++ fprintf(stderr, "setting boolean '%s' => %s\n", name, value_y ? "TRUE" : "FALSE"); ++#endif ++ ++ * (int *) ((char *) *conf + offset) = value_y ? 1 : 0; ++ ++ return NULL; ++} ++ ++char *xml_conf_set_slot_string(void **conf, char *name, void *vv, intptr_t offset) ++{ ++ char *value = vv; ++ char *v = strdup(value); ++ ++ if (!v) { return "xml_conf_set_slot_string(): strdup() failed"; } ++ ++#ifdef XML_CONF_DEBUG ++ fprintf(stderr, "setting string '%s' => '%s'\n", name, v); ++#endif ++ ++ * (char **) ((char *) *conf + offset) = v; ++ ++ return NULL; ++} ++ ++char *xml_conf_set_slot_integer(void **conf, char *name, void *vv, intptr_t offset) ++{ ++ char *value = vv; ++ int v = atoi(value); ++ ++ * (int *) ((char *) *conf + offset) = v; ++ ++#ifdef XML_CONF_DEBUG ++ fprintf(stderr, "setting integer '%s' => %d\n", name, v); ++#endif ++ ++ return NULL; ++} ++ ++char *xml_conf_set_slot_time(void **conf, char *name, void *vv, intptr_t offset) ++{ ++ char *value = vv; ++ int len = strlen(value); ++ char suffix; ++ int seconds; ++ ++ if (!len) { return "xml_conf_set_slot_timeval(): invalid timeval value"; } ++ ++ suffix = value[len-1]; ++ ++ value[len-1] = '\0'; ++ ++ switch (suffix) { ++ case 's' : ++ seconds = atoi(value); ++ break; ++ case 'm' : ++ seconds = 60 * atoi(value); ++ break; ++ case 'h' : ++ seconds = 60 * 60 * atoi(value); ++ break; ++ case 'd' : ++ seconds = 24 * 60 * 60 * atoi(value); ++ break; ++ default : ++ return "xml_conf_set_slot_timeval(): unknown suffix used in timeval value"; ++ } ++ ++ * (int *) ((char *) *conf + offset) = seconds; ++ ++#ifdef XML_CONF_DEBUG ++ fprintf(stderr, "setting time '%s' => %d:%02d:%02d:%02d\n", name, expand_dhms(seconds)); ++#endif ++ ++ return NULL; ++} ++ ++char *xml_conf_parse_section(void **conf, struct xml_conf_section *section, void *xml_node) ++{ ++ xmlNode *element = xml_node; ++ char *ret = 0; ++ ++#ifdef XML_CONF_DEBUG ++ fprintf(stderr, "processing a section %s\n", section->path); ++#endif ++ ++ for ( ; element; element = element->next) { ++ if (element->type == XML_ELEMENT_NODE && !strcmp((const char *) element->name, "value") && element->children) { ++ xmlChar *name = xmlGetProp(element, (unsigned char *) "name"); ++ ++ if (name) { ++ int i; ++ ++#ifdef XML_CONF_DEBUG ++ fprintf(stderr, "found a value: %s\n", name); ++#endif ++ for (i = 0; section->parsers[i].parser; i++) { ++ if (!section->parsers[i].name || !strcmp(section->parsers[i].name, (char *) name)) { ++ break; ++ } ++ } ++ ++ if (section->parsers[i].parser) { ++ if (section->parsers[i].type == XML_CONF_SCALAR) { ++ if (element->children->type == XML_TEXT_NODE) { ++ ret = section->parsers[i].parser(conf, (char *) name, element->children->content, section->parsers[i].offset); ++ } ++ else { ++ ret = "XML_TEXT_NODE is expected, something different is given"; ++ } ++ } ++ else { ++ ret = section->parsers[i].parser(conf, (char *) name, element->children, section->parsers[i].offset); ++ } ++ ++ xmlFree(name); ++ if (ret) { return ret; } ++ else { continue; } ++ } ++ ++ fprintf(stderr, "Warning, unknown setting '%s' in section '%s'\n", (char *) name, section->path); ++ ++ xmlFree(name); ++ } ++ } ++ } ++ ++ return NULL; ++} ++ ++static char *xml_conf_parse_file(xmlNode *element) ++{ ++ char *ret = 0; ++ ++ for ( ; element; element = element->next) { ++ ++ if (element->parent && element->type == XML_ELEMENT_NODE && !strcmp((const char *) element->name, "section")) { ++ xmlChar *name = xmlGetProp(element, (unsigned char *) "name"); ++ ++ if (name) { ++ char *parent_name = (char *) xmlGetNodePath(element->parent); ++ char *full_name; ++ int i; ++ struct xml_conf_section *section = NULL; ++ ++#ifdef XML_CONF_DEBUG ++ fprintf(stderr, "got a section: %s/%s\n", parent_name, name); ++#endif ++ full_name = alloca(strlen(parent_name) + strlen((char *) name) + 1 + 1); ++ ++ sprintf(full_name, "%s/%s", parent_name, (char *) name); ++ ++ xmlFree(parent_name); ++ xmlFree(name); ++ ++ for (i = 0; i < xml_conf_sections_used; i++) { ++ if (!strcmp(xml_conf_sections[i]->path, full_name)) { ++ section = xml_conf_sections[i]; ++ } ++ } ++ ++ if (section) { /* found a registered section */ ++ void *conf = section->conf(); ++ ret = xml_conf_parse_section(&conf, section, element->children); ++ if (ret) { break; } ++ } ++ ++ } ++ } ++ ++ if (element->children) { ++ ret = xml_conf_parse_file(element->children); ++ if (ret) { break; } ++ } ++ } ++ ++ return ret; ++} ++ ++char *xml_conf_load_file(char *file) ++{ ++ char *ret = 0; ++ xmlDoc *doc; ++ ++ LIBXML_TEST_VERSION ++ ++ doc = xmlParseFile(file); ++ ++ if (doc) { ++ ret = xml_conf_parse_file(doc->children); ++ xmlFreeDoc(doc); ++ } ++ else { ++ ret = "failed to parse conf file"; ++ } ++ ++ xmlCleanupParser(); ++ return ret; ++} ++ ++int xml_conf_init() ++{ ++ return 0; ++} ++ ++void xml_conf_clean() ++{ ++ if (xml_conf_sections) { ++ free(xml_conf_sections); ++ } ++} ++ ++int xml_conf_section_register(struct xml_conf_section *section) ++{ ++ if (xml_conf_sections_allocated == xml_conf_sections_used) { ++ int new_size = xml_conf_sections_used + 10; ++ void *new_ptr = realloc(xml_conf_sections, sizeof(struct xml_conf_section *) * new_size); ++ ++ if (new_ptr) { ++ xml_conf_sections = new_ptr; ++ xml_conf_sections_allocated = new_size; ++ } ++ else { ++ fprintf(stderr, "xml_conf_section_register(): out of memory\n"); ++ return -1; ++ } ++ } ++ ++ xml_conf_sections[xml_conf_sections_used++] = section; ++ ++ return 0; ++} ++ ++int xml_conf_sections_register(struct xml_conf_section *sections[]) ++{ ++ for ( ; sections && *sections; sections++) { ++ if (0 > xml_conf_section_register(*sections)) { ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ +diff -Naur php-src-vanilla/sapi/fpm/fpm/xml_config.h php-src/sapi/fpm/fpm/xml_config.h +--- php-src-vanilla/sapi/fpm/fpm/xml_config.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/xml_config.h 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,48 @@ ++ ++ /* $Id$ */ ++ /* (c) 2004-2007 Andrei Nigmatulin */ ++ ++#ifndef XML_CONFIG_H ++#define XML_CONFIG_H 1 ++ ++#if HAVE_INTTYPES_H ++#include ++#else ++#include ++#endif ++ ++ ++struct xml_value_parser; ++ ++struct xml_value_parser { ++ int type; ++ char *name; ++ char *(*parser)(void **, char *, void *, intptr_t offset); ++ intptr_t offset; ++}; ++ ++struct xml_conf_section { ++ void *(*conf)(); ++ char *path; ++ struct xml_value_parser *parsers; ++}; ++ ++char *xml_conf_set_slot_boolean(void **conf, char *name, void *value, intptr_t offset); ++char *xml_conf_set_slot_string(void **conf, char *name, void *value, intptr_t offset); ++char *xml_conf_set_slot_integer(void **conf, char *name, void *value, intptr_t offset); ++char *xml_conf_set_slot_time(void **conf, char *name, void *value, intptr_t offset); ++ ++int xml_conf_init(); ++void xml_conf_clean(); ++char *xml_conf_load_file(char *file); ++char *xml_conf_parse_section(void **conf, struct xml_conf_section *section, void *ve); ++int xml_conf_section_register(struct xml_conf_section *section); ++int xml_conf_sections_register(struct xml_conf_section *sections[]); ++ ++#define expand_hms(value) (value) / 3600, ((value) % 3600) / 60, (value) % 60 ++ ++#define expand_dhms(value) (value) / 86400, ((value) % 86400) / 3600, ((value) % 3600) / 60, (value) % 60 ++ ++enum { XML_CONF_SCALAR = 1, XML_CONF_SUBSECTION = 2 }; ++ ++#endif +diff -Naur php-src-vanilla/sapi/fpm/fpm/zlog.c php-src/sapi/fpm/fpm/zlog.c +--- php-src-vanilla/sapi/fpm/fpm/zlog.c 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/zlog.c 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,113 @@ ++ ++ /* $Id$ */ ++ /* (c) 2004-2007 Andrei Nigmatulin */ ++ ++#include "fpm_config.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "zlog.h" ++ ++#define MAX_LINE_LENGTH 1024 ++ ++static int zlog_fd = -1; ++static int zlog_level = ZLOG_NOTICE; ++ ++static const char *level_names[] = { ++ [ZLOG_DEBUG] = "DEBUG", ++ [ZLOG_NOTICE] = "NOTICE", ++ [ZLOG_WARNING] = "WARNING", ++ [ZLOG_ERROR] = "ERROR", ++ [ZLOG_ALERT] = "ALERT", ++}; ++ ++size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len) ++{ ++ struct tm t; ++ size_t len; ++ ++ len = strftime(timebuf, timebuf_len, "%b %d %H:%M:%S", localtime_r((const time_t *) &tv->tv_sec, &t)); ++ len += snprintf(timebuf + len, timebuf_len - len, ".%06d", (int) tv->tv_usec); ++ ++ return len; ++} ++ ++int zlog_set_fd(int new_fd) ++{ ++ int old_fd = zlog_fd; ++ zlog_fd = new_fd; ++ ++ return old_fd; ++} ++ ++int zlog_set_level(int new_value) ++{ ++ int old_value = zlog_level; ++ ++ zlog_level = new_value; ++ ++ return old_value; ++} ++ ++void zlog(const char *function, int line, int flags, const char *fmt, ...) ++{ ++ struct timeval tv; ++ char buf[MAX_LINE_LENGTH]; ++ const size_t buf_size = MAX_LINE_LENGTH; ++ va_list args; ++ size_t len; ++ int truncated = 0; ++ int saved_errno; ++ ++ if ((flags & ZLOG_LEVEL_MASK) < zlog_level) { ++ return; ++ } ++ ++ saved_errno = errno; ++ ++ gettimeofday(&tv, 0); ++ ++ len = zlog_print_time(&tv, buf, buf_size); ++ ++ len += snprintf(buf + len, buf_size - len, " [%s] %s(), line %d: ", level_names[flags & ZLOG_LEVEL_MASK], function, line); ++ ++ if (len > buf_size - 1) { ++ truncated = 1; ++ } ++ ++ if (!truncated) { ++ va_start(args, fmt); ++ ++ len += vsnprintf(buf + len, buf_size - len, fmt, args); ++ ++ va_end(args); ++ ++ if (len >= buf_size) { ++ truncated = 1; ++ } ++ } ++ ++ if (!truncated) { ++ if (flags & ZLOG_HAVE_ERRNO) { ++ len += snprintf(buf + len, buf_size - len, ": %s (%d)", strerror(saved_errno), saved_errno); ++ if (len >= buf_size) { ++ truncated = 1; ++ } ++ } ++ } ++ ++ if (truncated) { ++ memcpy(buf + buf_size - sizeof("..."), "...", sizeof("...") - 1); ++ len = buf_size - 1; ++ } ++ ++ buf[len++] = '\n'; ++ ++ write(zlog_fd > -1 ? zlog_fd : STDERR_FILENO, buf, len); ++} +diff -Naur php-src-vanilla/sapi/fpm/fpm/zlog.h php-src/sapi/fpm/fpm/zlog.h +--- php-src-vanilla/sapi/fpm/fpm/zlog.h 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/fpm/zlog.h 2009-10-18 21:05:39.308376784 +0100 +@@ -0,0 +1,34 @@ ++ ++ /* $Id$ */ ++ /* (c) 2004-2007 Andrei Nigmatulin */ ++ ++#ifndef ZLOG_H ++#define ZLOG_H 1 ++ ++#define ZLOG_STUFF __func__, __LINE__ ++ ++struct timeval; ++ ++int zlog_set_fd(int new_fd); ++int zlog_set_level(int new_value); ++ ++size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len); ++ ++void zlog(const char *function, int line, int flags, const char *fmt, ...) ++ __attribute__ ((format(printf,4,5))); ++ ++enum { ++ ZLOG_DEBUG = 1, ++ ZLOG_NOTICE = 2, ++ ZLOG_WARNING = 3, ++ ZLOG_ERROR = 4, ++ ZLOG_ALERT = 5, ++}; ++ ++#define ZLOG_LEVEL_MASK 7 ++ ++#define ZLOG_HAVE_ERRNO 0x100 ++ ++#define ZLOG_SYSERROR (ZLOG_ERROR | ZLOG_HAVE_ERRNO) ++ ++#endif +diff -Naur php-src-vanilla/sapi/fpm/LICENSE php-src/sapi/fpm/LICENSE +--- php-src-vanilla/sapi/fpm/LICENSE 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/LICENSE 2009-10-18 21:05:39.302497288 +0100 +@@ -0,0 +1,23 @@ ++Copyright (c) 2007-2009, Andrei Nigmatulin ++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 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 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. +diff -Naur php-src-vanilla/sapi/fpm/man/php-fpm.1.in php-src/sapi/fpm/man/php-fpm.1.in +--- php-src-vanilla/sapi/fpm/man/php-fpm.1.in 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/man/php-fpm.1.in 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,186 @@ ++.TH PHP-FPM 1 "2009" "The PHP Group" "Scripting Language" ++.SH NAME ++.TP 15 ++@php_fpm_bin@ \- PHP FastCGI Process Manager 'PHP-FPM' ++.SH SYNOPSIS ++.B @php_fpm_bin@ ++[options] ++.LP ++.SH DESCRIPTION ++\fBPHP\fP is a widely\-used general\-purpose scripting language that is especially suited for ++Web development and can be embedded into HTML. This is a variant of PHP that will run in the background as a daemon, listening for CGI requests. Output is logged to @php_fpm_log_path@. ++.LP ++Most options are set in the xml configuration file @php_fpm_conf_path@. Unless configured otherwise, @php_fpm_bin@ will respond to CGI requests listening on http localhost port 9000 by default. Therefore @php_fpm_bin@ expects your webserver to forward all requests for '.php' files to port 9000 and you should edit your webserver configuration file appropriately. ++.SH OPTIONS ++.TP 15 ++.B \-C ++Do not chdir to the script's directory ++.TP ++.PD 0 ++.B \-\-php\-ini \fIpath\fP|\fIfile\fP ++.TP ++.PD 1 ++.B \-c \fIpath\fP|\fIfile\fP ++Look for ++.B php.ini ++file in the directory ++.IR path ++or use the specified ++.IR file ++.TP ++.PD 0 ++.B \-\-no\-php\-ini ++.TP ++.PD 1 ++.B \-n ++No ++.B php.ini ++file will be used ++.TP ++.PD 0 ++.B \-\-define \fIfoo\fP[=\fIbar\fP] ++.TP ++.PD 1 ++.B \-d \fIfoo\fP[=\fIbar\fP] ++Define INI entry ++.IR foo ++with value ++.IR bar ++.TP ++.B \-e ++Generate extended information for debugger/profiler ++.TP ++.PD 0 ++.B \-\-help ++.TP ++.PD 1 ++.B \-h ++This help ++.TP ++.PD 0 ++.B \-\-info ++.TP ++.PD 1 ++.B \-i ++PHP information and configuration ++.TP ++.PD 0 ++.B \-\-modules ++.TP ++.PD 1 ++.B \-m ++Show compiled in modules ++.TP ++.PD 0 ++.B \-\-version ++.TP ++.PD 1 ++.B \-v ++Version number ++.TP ++.PD 0 ++.B \-\-fpm\-config \fIfile\fP ++.TP ++.PD 1 ++.B \-\-y ++Specify alternative path to FastCGI process manager configuration file (the default is @php_fpm_conf_path@) ++.TP ++.PD 0 ++.B \-\-zend\-extension \fIfile\fP ++.TP ++.PD 1 ++.B \-z \fIfile\fP ++Load Zend extension ++.IR file ++.SH FILES ++.TP 15 ++.B @php_fpm_bin@.conf ++The configuration file for the @php_fpm_bin@ daemon. ++.TP ++.B php.ini ++The standard php configuration file. ++.SH EXAMPLES ++You should use the init script provided to start and stop the @php_fpm_bin@ daemon. This situation applies for any unix systems which use init.d for their main process manager. ++.P ++.PD 1 ++.RS ++sudo /etc/init.d/@php_fpm_bin@ start ++.RE ++.TP ++If your installation has no appropriate init script, launch @php_fpm_bin_path@ with no arguments. It will launch as a daemon (background process) by default. The file @php_fpm_pid_path@ determines whether @php_fpm_bin@ is already up and running. Once started, @php_fpm_bin@ then responds to several POSIX signals: ++.P ++.PD 0 ++.RS ++.B SIGINT,SIGTERM \fPimmediate termination ++.TP ++.B SIGQUIT \fPgraceful stop ++.TP ++.B SIGUSR1 \fPre-open log file ++.TP ++.B SIGUSR2 \fPgraceful reload of all workers + reload of fpm conf/binary ++.RE ++.PD 1 ++.P ++.SH TIPS ++The PHP-FPM CGI daemon will work well with most popular webservers, including Apache2 and light-httpd. For best efficiency and performance improvements its also worthwhile to consider the engine-x webserver ('nginx'), and php opcode-cacher ('php5-xcache'). ++.PD 1 ++.P ++.SH SEE ALSO ++The PHP-FPM website: ++.PD 0 ++.P ++.B http://php-fpm.org ++.PD 1 ++.P ++For a more or less complete description of PHP look here: ++.PD 0 ++.P ++.B http://www.php.net/manual/ ++.PD 1 ++.P ++A nice introduction to PHP by Stig Bakken can be found here: ++.PD 0 ++.P ++.B http://www.zend.com/zend/art/intro.php ++.PD 1 ++.SH BUGS ++You can view the list of known bugs or report any new bug you ++found at: ++.PD 0 ++.P ++.B http://bugs.php.net ++.PD 1 ++.SH AUTHORS ++PHP-FPM Sapi was written by Andrei Nigmatulin. The mailing-lists are highload-php-en (English) and highload-php-ru (Russion). ++.P ++The PHP Group: Thies C. Arntzen, Stig Bakken, Andi Gutmans, Rasmus Lerdorf, Sam Ruby, Sascha Schumann, Zeev Suraski, Jim Winstead, Andrei Zmievski. ++.P ++A List of active developers can be found here: ++.PD 0 ++.P ++.B http://www.php.net/credits.php ++.PD 1 ++.P ++And last but not least PHP was developed with the help of a huge amount of ++contributors all around the world. ++.SH VERSION INFORMATION ++This manpage describes \fBphp\fP, version @PHP_VERSION@, \fBfpm\fP, version @fpm_version@. ++.SH COPYRIGHT ++Copyright \(co 1997\-2009 The PHP Group ++.PD 0 ++.P ++Copyright (c) 2007-2009, Andrei Nigmatulin ++.PD 1 ++.LP ++This source file is subject to version 3.01 of the PHP license, ++that is bundled with this package in the file LICENSE, and is ++available through the world-wide-web at the following url: ++.PD 0 ++.P ++.B http://www.php.net/license/3_01.txt ++.PD 1 ++.P ++If you did not receive a copy of the PHP license and are unable to ++obtain it through the world-wide-web, please send a note to ++.B license@php.net ++so we can mail you a copy immediately. +diff -Naur php-src-vanilla/sapi/fpm/readme-ru.markdown php-src/sapi/fpm/readme-ru.markdown +--- php-src-vanilla/sapi/fpm/readme-ru.markdown 1970-01-01 01:00:00.000000000 +0100 ++++ php-src/sapi/fpm/readme-ru.markdown 2009-10-18 21:05:39.310440424 +0100 +@@ -0,0 +1,127 @@ ++# PHP FastCGI Менеджер процессов (PHP-FPM) ++ ++PHP-FPM это Fast-CGI фронтэнд для php и расширение php-cgi. Проект находится на [Launchpad](https://launchpad.net/php-fpm) ++ ++## Быстрый старт: ++ ++Выберите один из 2 путей сборки fpm: Или `встроенный`, или `отдельный`. Если вы не разработчик или не системный администратор, то мы рекомендуем `встроенный` вариант компиляции. Для дополнительной информации смотрите файл `readme.markdown`. ++ ++## Зависимости ++Если вы до этого не устанавливали php, то вам придётся установить пакет `libxml2-dev`. FPM также необходим `libevent-dev`. Debian / ubuntu: ++ ++ sudo aptitude install -y libxml2-dev libevent-dev ++ ++Рекомендуется использовать libevent 1.4.12-stable или позднее, но необходим, как минимум, libevent 1.4.3-stable. Если нет подходящей версии, скайте и скомпилируйте с [сайта Libevent](http://www.monkey.org/~provos/libevent/). ++ ++ export LE_VER=1.4.12-stable ++ wget "http://www.monkey.org/~provos/libevent-$LE_VER.tar.gz" ++ tar -zxvf "libevent-$LE_VER.tar.gz" ++ cd "libevent-$LE_VER" ++ ./configure && make ++ DESTDIR=$PWD make install ++ export LIBEVENT_SEARCH_PATH="$PWD/usr/local" ++ ++## Встроенная сборка ++ ++Скачайте fpm и сгенерируйте патч ++ ++ export PHP_VER=5.3.0 ++ wget "http://launchpad.net/php-fpm/master/0.6/+download/php-fpm-0.6-$PHP_VER.tar.gz" ++ tar -zxvf "php-fpm-0.6-$PHP_VER.tar.gz" ++ "php-fpm-0.6-$PHP_VER/generate-fpm-patch" ++ ++Скачайте и распакуйте исходный код PHP ++ ++ wget "http://ru2.php.net/get/php-$PHP_VER.tar.gz/from/ru2.php.net/mirror" ++ tar xvfz "php-$PHP_VER.tar.gz" ++ cd "php-$PHP_VER" ++ ++Примените патч и компилируйте ++ ++ patch -p1 < ../fpm.patch ++ ./buildconf --force ++ mkdir fpm-build && cd fpm-build ++ ../configure --with-fpm \ ++ --with-libevent="$LIBEVENT_SEARCH_PATH" && make ++ ++## Отдельная сборка ++ ++Скачайте и распакуйте исходный код PHP ++ ++ export PHP_VER=5.3.0 ++ wget "http://ru2.php.net/get/php-$PHP_VER.tar.gz/from/ru2.php.net/mirror" ++ tar xvfz "php-$PHP_VER.tar.gz" ++ cd "php-$PHP_VER" ++ mkdir php-build && cd php-build ++ ../configure && make ++ ++Теперь можете скачать, конфигурировать и компилировать FPM фронтэнд ++ ++ wget "http://launchpad.net/php-fpm/master/0.6/+download/php-fpm-0.6-$PHP_VER.tar.gz" ++ tar -zxvf "php-fpm-0.6-$PHP_VER.tar.gz" ++ cd "php-fpm-0.6-$PHP_VER" ++ mkdir fpm-build && cd fpm-build ++ ../configure --srcdir=../ \ ++ --with-php-src="../../php-$PHP_VER" \ ++ --with-php-build="../../php-$PHP_VER/php-build" \ ++ --with-libevent="$LIBEVENT_SEARCH_PATH" && make ++ ++## Флаги конфигурирования ++ ++ --with-libevent[=PATH] Путь до libevent, для fpm SAPI [/usr/local] ++ --with-fpm-bin[=PATH] Путь для откомпилированного php-fpm [/usr/local/bin/php-fpm] ++ --with-fpm-port[=PORT] TCP порт для cgi запросов [9000] ++ --with[out]-fpm-conf[=PATH] Путь до файла конфигурации php-fpm [/etc/php-fpm.conf] ++ --with[out]-fpm-init[=PATH] Путь до init-файла php-fpm [/etc/init.d/php-fpm] ++ --with-fpm-log[=PATH] Путь до лог-файла php-fpm [/var/log/php-fpm.log] ++ --with-fpm-pid[=PATH] Путь до pid-файла php-fpm [/var/run/php-fpm.pid] ++ --with-fpm-user[=USER] Пользователь, под которым запускать php-fpm [nobody] ++ --with-fpm-group[=GRP] Группа, под которой запускать php-fpm. Для системных ++ пользователей задайте имя пользователя [nobody] ++ ++## Установка ++ ++Если вы делали `встроенную` сборку, то вы получите полный php, включая исполнитель коммандной строки `php-cli` и библиотеку PEAR. `Отдельная` или `независимая` сборка установит только демон `php-fpm` и минимум файлов, необходимых для его запуска. ++ ++ # Посмотреть, какие файлы будут установлены ++ make install --dry-run ++ ++ # Установить в '/' ++ sudo make install ++ ++ # Установить в '/opt' ++ sudo INSTALL_ROOT=/opt make install ++ ++Notes: ++ ++* (Upgrade) When overwriting existing FPM installation files: A previous configuration file `php-fpm.conf` will be moved to `php-fpm.conf.old`. Then a newer (default) configuration file will be installed in it's place. If you have any custom XML settings which you wish to keep, its recommended to copy these back over manually. ++ ++* (BSD) the default init.d path is `/usr/local/etc/rc.d/php-fpm` or disable: `--without-fpm-init` ++ ++* (Nginx) An example nginx configuration file is generated. The file `nginx-site-conf.sample` may be installed into your nginx configuration directory, if exists: `/etc/nginx/`, `/usr/local/etc/nginx/`, or `/usr/local/nginx/conf` ++ ++## Больше о процессе сборки PHP-FPM ++ ++Процесс сборки можно описать так: ++ ++ 1) Компилируются исходники php в объектные файлы ++ 2) Компилируются исходники fpm в объектные файлы ++ 3) Линковка php и fpm объектных файлов ++ 4) Результат: исполняемый php5, в основе которого php и fast-CGI от fpm как фронтэнд ++ ++Fpm подмешивается в php при линковке (link-level). Андрей разделил исходный код fpm, сделав SAPI чем-то менее чуствительным к изменениям в остальном коде php. Код cgi-main.c из PHP-FPM - конктроллер запросов - вырезан из оригинального fcgi-sapi. Мы отправляем билд 0.6 в PHP Group. Мы будем отслеживать развитие PHP и периодически синхронизировать изменения с проектами встроенной / отдельной сборки. ++ ++## Buildconf ++ ++Для сборки fpm отдельно, конфигурирование (`./configure`) требует некоторой версии набора инструментов autoconf. Buildconf запустит `./generate-autotools` и попробует установить эти инструменты самостоятельно. Если `./buildconf` не работает, смотрите лог ошибок. ++ ++ ++## Обсуждение ++ ++Есть 2 группы для обсуждения php-fpm, ++ ++- [highload-php-ru](http://groups.google.com/group/highload-php-en) (english) ++ ++- [highload-php-ru](http://groups.google.com/group/highload-php-ru) (русская) ++ ++Translated by Anatoly Pashin diff --git a/php-gd_imagerotate_enable.patch b/php-gd_imagerotate_enable.patch new file mode 100644 index 0000000..6d1e74c --- /dev/null +++ b/php-gd_imagerotate_enable.patch @@ -0,0 +1,173 @@ +diff -ur php5.3-200812262130/ext/gd/config.m4 mod/ext/gd/config.m4 +--- php5.3-200812262130/ext/gd/config.m4 2008-07-18 04:34:20.000000000 +0200 ++++ mod/ext/gd/config.m4 2008-12-27 01:12:23.000000000 +0100 +@@ -255,6 +255,7 @@ + PHP_CHECK_LIBRARY(gd, gdFreeFontCache, [AC_DEFINE(HAVE_GD_FREEFONTCACHE, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) + PHP_CHECK_LIBRARY(gd, gdFontCacheMutexSetup, [AC_DEFINE(HAVE_GD_FONTMUTEX, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) + PHP_CHECK_LIBRARY(gd, gdNewDynamicCtxEx, [AC_DEFINE(HAVE_GD_DYNAMIC_CTX_EX, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) ++ PHP_CHECK_LIBRARY(gd, gdImageRotate, [AC_DEFINE(HAVE_GD_ROTATE, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) + ]) + + dnl +@@ -308,6 +309,7 @@ + AC_DEFINE(HAVE_GD_FONTMUTEX, 1, [ ]) + AC_DEFINE(HAVE_GD_DYNAMIC_CTX_EX, 1, [ ]) + AC_DEFINE(HAVE_GD_GIF_CTX, 1, [ ]) ++ AC_DEFINE(HAVE_GD_ROTATE, 1, [ ]) + + dnl Make sure the libgd/ is first in the include path + GDLIB_CFLAGS="-DHAVE_LIBPNG" +diff -ur php5.3-200812262130/ext/gd/gd.c mod/ext/gd/gd.c +--- php5.3-200812262130/ext/gd/gd.c 2008-12-12 14:35:20.000000000 +0100 ++++ mod/ext/gd/gd.c 2008-12-27 01:18:43.000000000 +0100 +@@ -296,7 +296,7 @@ + ZEND_END_ARG_INFO() + #endif + +-#ifdef HAVE_GD_BUNDLED ++#ifdef HAVE_GD_ROTATE + ZEND_BEGIN_ARG_INFO_EX(arginfo_imagerotate, 0, 0, 3) + ZEND_ARG_INFO(0, im) + ZEND_ARG_INFO(0, angle) +@@ -927,9 +927,12 @@ + PHP_FE(imagegrabscreen, arginfo_imagegrabscreen) + #endif + ++#ifdef HAVE_GD_ROTATE ++ PHP_FE(imagerotate, arginfo_imagerotate) ++#endif ++ + #ifdef HAVE_GD_BUNDLED +- PHP_FE(imagerotate, arginfo_imagerotate) +- PHP_FE(imageantialias, arginfo_imageantialias) ++ PHP_FE(imageantialias, arginfo_imageantialias) + #endif + + #if HAVE_GD_IMAGESETTILE +@@ -1079,7 +1082,7 @@ + PHP_INI_ENTRY("gd.jpeg_ignore_warning", "0", PHP_INI_ALL, NULL) + PHP_INI_END() + /* }}} */ +- ++ + /* {{{ php_free_gd_image + */ + static void php_free_gd_image(zend_rsrc_list_entry *rsrc TSRMLS_DC) +@@ -1140,7 +1143,7 @@ + #endif + + REGISTER_INI_ENTRIES(); +- ++ + REGISTER_LONG_CONSTANT("IMG_GIF", 1, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMG_JPG", 2, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMG_JPEG", 2, CONST_CS | CONST_PERSISTENT); +@@ -1168,11 +1171,14 @@ + #ifdef GD2_FMT_COMPRESSED + REGISTER_LONG_CONSTANT("IMG_GD2_COMPRESSED", GD2_FMT_COMPRESSED, CONST_CS | CONST_PERSISTENT); + #endif +-#if HAVE_GD_BUNDLED ++#if HAVE_GD_ROTATE + REGISTER_LONG_CONSTANT("IMG_EFFECT_REPLACE", gdEffectReplace, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMG_EFFECT_ALPHABLEND", gdEffectAlphaBlend, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMG_EFFECT_NORMAL", gdEffectNormal, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMG_EFFECT_OVERLAY", gdEffectOverlay, CONST_CS | CONST_PERSISTENT); ++#endif ++ ++#if HAVE_GD_BUNDLED + REGISTER_LONG_CONSTANT("GD_BUNDLED", 1, CONST_CS | CONST_PERSISTENT); + + /* Section Filters */ +@@ -1760,7 +1766,7 @@ + long cx, cy, w, h, ST, E, col, style; + gdImagePtr im; + int e, st; +- ++ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rllllllll", &IM, &cx, &cy, &w, &h, &ST, &E, &col, &style) == FAILURE) { + return; + } +@@ -2008,7 +2014,7 @@ + if ( handle == 0 ) { + goto clean; + } +- pPrintWindow = (tPrintWindow) GetProcAddress(handle, "PrintWindow"); ++ pPrintWindow = (tPrintWindow) GetProcAddress(handle, "PrintWindow"); + + if ( pPrintWindow ) { + pPrintWindow(window, memDC, (UINT) client_area); +@@ -2105,7 +2111,7 @@ + /* }}} */ + #endif /* PHP_WIN32 */ + +-#ifdef HAVE_GD_BUNDLED ++#ifdef HAVE_GD_ROTATE + /* {{{ proto resource imagerotate(resource src_im, float angle, int bgdcolor [, int ignoretransparent]) + Rotate an image using a custom angle */ + PHP_FUNCTION(imagerotate) +@@ -3362,7 +3368,7 @@ + { + zval *IM; + gdImagePtr im; +- ++ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &IM) == FAILURE) { + return; + } +@@ -3946,7 +3952,7 @@ + if (zend_hash_get_current_data_ex(HASH_OF(EXT), (void **) &item, &pos) == FAILURE) { + continue; + } +- ++ + if (strcmp("linespacing", key) == 0) { + convert_to_double_ex(item); + strex.flags |= gdFTEX_LINESPACE; +@@ -3972,7 +3978,7 @@ + #endif + + PHP_GD_CHECK_OPEN_BASEDIR((char *)fontname, "Invalid font filename"); +- ++ + #ifdef USE_GD_IMGSTRTTF + # if HAVE_GD_STRINGFTEX + if (extended) { +@@ -4373,11 +4379,11 @@ + if (argc != 3 && argc != 6) { + ZEND_WRONG_PARAM_COUNT(); + } +- ++ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "srl|lld", &str, &str_len, &fnt, &sz, &sp, &wd, &angle) == FAILURE) { + return; + } +- ++ + if (argc == 6) { + space = sp; + add_width = wd; +@@ -4562,7 +4568,7 @@ + #ifdef HAVE_GD_JPG + long ignore_warning; + #endif +- ++ + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sslll", &f_org, &f_org_len, &f_dest, &f_dest_len, &height, &width, &threshold) == FAILURE) { + return; + } +diff -ur php5.3-200812262130/ext/gd/php_gd.h mod/ext/gd/php_gd.h +--- php5.3-200812262130/ext/gd/php_gd.h 2008-07-18 04:34:20.000000000 +0200 ++++ mod/ext/gd/php_gd.h 2008-12-27 01:20:04.000000000 +0100 +@@ -119,8 +119,11 @@ + PHP_FUNCTION(imagegrabscreen); + #endif + +-#ifdef HAVE_GD_BUNDLED ++#ifdef HAVE_GD_ROTATE + PHP_FUNCTION(imagerotate); ++#endif ++ ++#ifdef HAVE_GD_BUNDLED + PHP_FUNCTION(imageantialias); + #endif + diff --git a/php-imap-annotations.patch b/php-imap-annotations.patch new file mode 100644 index 0000000..d94dcbd --- /dev/null +++ b/php-imap-annotations.patch @@ -0,0 +1,305 @@ +Provides get/set ANNOTATIONS support to PHP. [Version: 5.2.6] + +diff -r 76412c484360 ext/imap/php_imap.c +--- a/ext/imap/php_imap.c Wed Dec 23 22:18:41 2009 +0100 ++++ b/ext/imap/php_imap.c Wed Dec 23 22:46:34 2009 +0100 +@@ -161,6 +161,22 @@ + ZEND_ARG_INFO(0, mailbox) + ZEND_END_ARG_INFO() + #endif ++#if defined(HAVE_IMAP2005) ++ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_setannotation, 0, 0, 5) ++ ZEND_ARG_INFO(0, stream_id) ++ ZEND_ARG_INFO(0, mailbox) ++ ZEND_ARG_INFO(0, entry) ++ ZEND_ARG_INFO(0, attr) ++ ZEND_ARG_INFO(0, value) ++ZEND_END_ARG_INFO() ++ ++ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_getannotation, 0, 0, 4) ++ ZEND_ARG_INFO(0, stream_id) ++ ZEND_ARG_INFO(0, mailbox) ++ ZEND_ARG_INFO(0, entry) ++ ZEND_ARG_INFO(0, attr) ++ZEND_END_ARG_INFO() ++#endif + + ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_expunge, 0, 0, 1) + ZEND_ARG_INFO(0, stream_id) +@@ -402,6 +418,11 @@ + ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_status, 0, 0, 3) + ZEND_ARG_INFO(0, stream_id) + ZEND_ARG_INFO(0, mailbox) ++ ZEND_ARG_INFO(0, options) ++ZEND_END_ARG_INFO() ++ ++ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_status_current, 0, 0, 2) ++ ZEND_ARG_INFO(0, stream_id) + ZEND_ARG_INFO(0, options) + ZEND_END_ARG_INFO() + +@@ -504,6 +525,7 @@ + PHP_FE(imap_binary, arginfo_imap_binary) + PHP_FE(imap_utf8, arginfo_imap_utf8) + PHP_FE(imap_status, arginfo_imap_status) ++ PHP_FE(imap_status_current, arginfo_imap_status_current) + PHP_FE(imap_mailboxmsginfo, arginfo_imap_mailboxmsginfo) + PHP_FE(imap_setflag_full, arginfo_imap_setflag_full) + PHP_FE(imap_clearflag_full, arginfo_imap_clearflag_full) +@@ -534,6 +556,10 @@ + PHP_FE(imap_setacl, arginfo_imap_setacl) + PHP_FE(imap_getacl, arginfo_imap_getacl) + #endif ++#if defined(HAVE_IMAP2005) ++ PHP_FE(imap_setannotation, arginfo_imap_setannotation) ++ PHP_FE(imap_getannotation, arginfo_imap_getannotation) ++#endif + + PHP_FE(imap_mail, arginfo_imap_mail) + +@@ -795,6 +821,30 @@ + /* }}} */ + #endif + ++#if defined(HAVE_IMAP2005) ++/* {{{ mail_getannotation ++ * ++ * Mail GET_ANNOTATION callback ++ * Called via the mail_parameter function in c-client:src/c-client/mail.c ++ */ ++void mail_getannotation(MAILSTREAM *stream, ANNOTATION *alist) ++{ ++ ANNOTATION_VALUES *cur; ++ ++ TSRMLS_FETCH(); ++ ++ /* walk through the ANNOTATION_VALUES */ ++ ++ for(cur = alist->values; cur; cur = cur->next) { ++ if (cur->value) ++ add_assoc_stringl(IMAPG(imap_annotation_list), cur->attr, cur->value, strlen(cur->value), 1); ++ else ++ add_assoc_stringl(IMAPG(imap_annotation_list), cur->attr, "", 0, 1); ++ } ++} ++/* }}} */ ++#endif ++ + /* {{{ PHP_GINIT_FUNCTION + */ + static PHP_GINIT_FUNCTION(imap) +@@ -820,6 +870,7 @@ + #if defined(HAVE_IMAP2000) || defined(HAVE_IMAP2001) + imap_globals->quota_return = NIL; + imap_globals->imap_acl_list = NIL; ++ imap_globals->imap_annotation_list = NIL; + #endif + imap_globals->gets_stream = NIL; + } +@@ -1475,7 +1526,119 @@ + } + /* }}} */ + #endif /* HAVE_IMAP2000 || HAVE_IMAP2001 */ +- ++ ++#if defined(HAVE_IMAP2005) ++ ++/* {{{ proto bool imap_setannotation(resource stream_id, string mailbox, string entry, string attr, string value) ++ Sets an annotation for a given mailbox */ ++PHP_FUNCTION(imap_setannotation) ++{ ++ zval **streamind, **mailbox, **entry, **attr, **value; ++ pils *imap_le_struct; ++ long ret; ++ ++ // TODO: Use zend_parse_parameters here ++ if (ZEND_NUM_ARGS() != 5 || zend_get_parameters_ex(5, &streamind, &mailbox, &entry, &attr, &value) == FAILURE) { ++ ZEND_WRONG_PARAM_COUNT(); ++ } ++ ++ ZEND_FETCH_RESOURCE(imap_le_struct, pils *, streamind, -1, "imap", le_imap); ++ ++ convert_to_string_ex(mailbox); ++ convert_to_string_ex(entry); ++ convert_to_string_ex(attr); ++ convert_to_string_ex(value); ++ ++ // create annotation object ++ ANNOTATION *annotation = mail_newannotation(); ++ if (!annotation) ++ RETURN_FALSE; ++ annotation->values = mail_newannotationvalue(); ++ if (!annotation->values) { ++ mail_free_annotation(&annotation); ++ RETURN_FALSE; ++ } ++ ++ // fill in annotation values ++ annotation->mbox = Z_STRVAL_PP(mailbox); ++ annotation->entry = Z_STRVAL_PP(entry); ++ annotation->values->attr = Z_STRVAL_PP(attr); ++ annotation->values->value = Z_STRVAL_PP(value); ++ ++ ret = imap_setannotation(imap_le_struct->imap_stream, annotation); ++ ++ // make sure mail_free_annotation doesn't free our variables ++ annotation->mbox = NULL; ++ annotation->entry = NULL; ++ annotation->values->attr = NULL; ++ annotation->values->value = NULL; ++ mail_free_annotation(&annotation); ++ ++ RETURN_BOOL(ret); ++} ++/* }}} */ ++ ++/* {{{ proto array imap_getannotation(resource stream_id, string mailbox, string entry, string attr) ++ Gets the ACL for a given mailbox */ ++PHP_FUNCTION(imap_getannotation) ++{ ++ zval **streamind, **mailbox, **entry, **attr; ++ pils *imap_le_struct; ++ long ret; ++ ++ if(ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &streamind, &mailbox, &entry, &attr) == FAILURE) { ++ ZEND_WRONG_PARAM_COUNT(); ++ } ++ ++ ZEND_FETCH_RESOURCE(imap_le_struct, pils *, streamind, -1, "imap", le_imap); ++ ++ convert_to_string_ex(mailbox); ++ convert_to_string_ex(entry); ++ convert_to_string_ex(attr); ++ ++ /* initializing the special array for the return values */ ++ if (array_init(return_value) == FAILURE) { ++ RETURN_FALSE; ++ } ++ ++ // fillup calling parameters ++ STRINGLIST *entries = mail_newstringlist(); ++ if (!entries) ++ RETURN_FALSE; ++ ++ STRINGLIST *cur = entries; ++ cur->text.data = (unsigned char *)cpystr(Z_STRVAL_PP(entry)); ++ cur->text.size = Z_STRLEN_PP(entry); ++ cur->next = NIL; ++ ++ STRINGLIST *attributes = mail_newstringlist(); ++ if (!attributes) ++ RETURN_FALSE; ++ cur = attributes; ++ cur->text.data = (unsigned char *)cpystr (Z_STRVAL_PP(attr)); ++ cur->text.size = Z_STRLEN_PP(attr); ++ cur->next = NIL; ++ ++ IMAPG(imap_annotation_list) = return_value; ++ ++ /* set the callback for the GET_ANNOTATION function */ ++ mail_parameters(NIL, SET_ANNOTATION, (void *) mail_getannotation); ++ ret = imap_getannotation(imap_le_struct->imap_stream, Z_STRVAL_PP(mailbox), entries, attributes); ++ ++ mail_free_stringlist(&entries); ++ mail_free_stringlist(&attributes); ++ ++ if (!ret) { ++ zval_dtor(return_value); ++ RETURN_FALSE; ++ } ++ ++ IMAPG(imap_annotation_list) = NIL; ++} ++/* }}} */ ++ ++#endif /* HAVE_IMAP2005 */ ++ + /* {{{ proto bool imap_expunge(resource stream_id) + Permanently delete all messages marked for deletion */ + PHP_FUNCTION(imap_expunge) +@@ -3118,6 +3281,42 @@ + } + /* }}} */ + ++/* {{{ proto object imap_status_current(resource stream_id, int options) ++ Get (cached) status info from current mailbox */ ++PHP_FUNCTION(imap_status_current) ++{ ++ zval **streamind, **pflags; ++ pils *imap_le_struct; ++ long flags = 0L; ++ ++ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &streamind, &pflags) == FAILURE) { ++ ZEND_WRONG_PARAM_COUNT(); ++ } ++ ++ ZEND_FETCH_RESOURCE(imap_le_struct, pils *, streamind, -1, "imap", le_imap); ++ ++ convert_to_long_ex(pflags); ++ flags = Z_LVAL_PP(pflags); ++ ++ if (object_init(return_value) == FAILURE) { ++ RETURN_FALSE; ++ } ++ ++ if (flags & SA_MESSAGES) { ++ add_property_long(return_value, "messages", imap_le_struct->imap_stream->nmsgs); ++ } ++ if (flags & SA_RECENT) { ++ add_property_long(return_value, "recent", imap_le_struct->imap_stream->recent); ++ } ++ if (flags & SA_UIDNEXT) { ++ add_property_long(return_value, "uidnext", imap_le_struct->imap_stream->uid_last+1); ++ } ++ if (flags & SA_UIDVALIDITY) { ++ add_property_long(return_value, "uidvalidity", imap_le_struct->imap_stream->uid_validity); ++ } ++} ++/* }}} */ ++ + /* {{{ proto object imap_status(resource stream_id, string mailbox, int options) + Get status info from a mailbox */ + PHP_FUNCTION(imap_status) +diff -r 76412c484360 ext/imap/php_imap.h +--- a/ext/imap/php_imap.h Wed Dec 23 22:18:41 2009 +0100 ++++ b/ext/imap/php_imap.h Wed Dec 23 22:46:34 2009 +0100 +@@ -153,6 +153,7 @@ + PHP_FUNCTION(imap_lsub_full); + PHP_FUNCTION(imap_create); + PHP_FUNCTION(imap_rename); ++PHP_FUNCTION(imap_status_current); + PHP_FUNCTION(imap_status); + PHP_FUNCTION(imap_bodystruct); + PHP_FUNCTION(imap_fetch_overview); +@@ -173,6 +174,9 @@ + PHP_FUNCTION(imap_thread); + PHP_FUNCTION(imap_timeout); + ++// TODO: Needs fixing in configure in ++#define HAVE_IMAP2005 1 ++ + #if defined(HAVE_IMAP2000) || defined(HAVE_IMAP2001) + PHP_FUNCTION(imap_get_quota); + PHP_FUNCTION(imap_get_quotaroot); +@@ -180,7 +184,10 @@ + PHP_FUNCTION(imap_setacl); + PHP_FUNCTION(imap_getacl); + #endif +- ++#if defined(HAVE_IMAP2005) ++PHP_FUNCTION(imap_setannotation); ++PHP_FUNCTION(imap_getannotation); ++#endif + + ZEND_BEGIN_MODULE_GLOBALS(imap) + char *imap_user; +@@ -211,6 +218,9 @@ + zval **quota_return; + zval *imap_acl_list; + #endif ++#if defined(HAVE_IMAP2005) ++ zval *imap_annotation_list; ++#endif + /* php_stream for php_mail_gets() */ + php_stream *gets_stream; + ZEND_END_MODULE_GLOBALS(imap) diff --git a/php-imap-myrights.patch b/php-imap-myrights.patch new file mode 100644 index 0000000..ddadbd3 --- /dev/null +++ b/php-imap-myrights.patch @@ -0,0 +1,92 @@ +diff -r 5daa8cce8706 ext/imap/php_imap.c +--- a/ext/imap/php_imap.c Wed Dec 23 22:46:34 2009 +0100 ++++ b/ext/imap/php_imap.c Wed Dec 23 22:49:02 2009 +0100 +@@ -157,6 +157,11 @@ + ZEND_END_ARG_INFO() + + ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_getacl, 0, 0, 2) ++ ZEND_ARG_INFO(0, stream_id) ++ ZEND_ARG_INFO(0, mailbox) ++ZEND_END_ARG_INFO() ++ ++ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_myrights, 0, 0, 2) + ZEND_ARG_INFO(0, stream_id) + ZEND_ARG_INFO(0, mailbox) + ZEND_END_ARG_INFO() +@@ -555,6 +560,7 @@ + PHP_FE(imap_set_quota, arginfo_imap_set_quota) + PHP_FE(imap_setacl, arginfo_imap_setacl) + PHP_FE(imap_getacl, arginfo_imap_getacl) ++ PHP_FE(imap_myrights, arginfo_imap_myrights) + #endif + #if defined(HAVE_IMAP2005) + PHP_FE(imap_setannotation, arginfo_imap_setannotation) +@@ -817,6 +823,20 @@ + for(; alist; alist = alist->next) { + add_assoc_stringl(IMAPG(imap_acl_list), alist->identifier, alist->rights, strlen(alist->rights), 1); + } ++} ++/* }}} */ ++ ++/* {{{ mail_myrights ++ * ++ * Mail MYRIGHTS callback ++ * Called via the mail_parameter function in c-client:src/c-client/mail.c ++ */ ++void mail_myrights(MAILSTREAM *stream, char *mailbox, char *rights) ++{ ++ TSRMLS_FETCH(); ++ ++ ZVAL_STRING(IMAPG(imap_acl_list), rights, 1) ++ + } + /* }}} */ + #endif +@@ -1525,6 +1545,36 @@ + IMAPG(imap_acl_list) = NIL; + } + /* }}} */ ++ ++/* {{{ proto string imap_myrights(resource stream_id, string mailbox) ++ Gets my rights (ACL) for a given mailbox */ ++PHP_FUNCTION(imap_myrights) ++{ ++ zval **streamind, **mailbox; ++ pils *imap_le_struct; ++ ++ if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &streamind, &mailbox) == FAILURE) { ++ ZEND_WRONG_PARAM_COUNT(); ++ } ++ ++ ZEND_FETCH_RESOURCE(imap_le_struct, pils *, streamind, -1, "imap", le_imap); ++ ++ convert_to_string_ex(mailbox); ++ ++ IMAPG(imap_acl_list) = return_value; ++ ++ /* set the callback for the GET_ACL function */ ++ mail_parameters(NIL, SET_MYRIGHTS, (void *) mail_myrights); ++ if(!imap_myrights(imap_le_struct->imap_stream, Z_STRVAL_PP(mailbox))) { ++ php_error(E_WARNING, "c-client imap_myrights failed"); ++ zval_dtor(return_value); ++ RETURN_FALSE; ++ } ++ ++ IMAPG(imap_acl_list) = NIL; ++} ++/* }}} */ ++ + #endif /* HAVE_IMAP2000 || HAVE_IMAP2001 */ + + #if defined(HAVE_IMAP2005) +diff -r 5daa8cce8706 ext/imap/php_imap.h +--- a/ext/imap/php_imap.h Wed Dec 23 22:46:34 2009 +0100 ++++ b/ext/imap/php_imap.h Wed Dec 23 22:49:02 2009 +0100 +@@ -183,6 +183,7 @@ + PHP_FUNCTION(imap_set_quota); + PHP_FUNCTION(imap_setacl); + PHP_FUNCTION(imap_getacl); ++PHP_FUNCTION(imap_myrights); + #endif + #if defined(HAVE_IMAP2005) + PHP_FUNCTION(imap_setannotation); diff --git a/php-include_path.patch b/php-include_path.patch new file mode 100644 index 0000000..a1c3afe --- /dev/null +++ b/php-include_path.patch @@ -0,0 +1,11 @@ +--- php-5.2.0/configure.in.includedir ++++ php-5.2.0/configure.in +@@ -1101,7 +1101,7 @@ + EXPANDED_DATADIR=$datadir + EXPANDED_PHP_CONFIG_FILE_PATH=`eval echo "$PHP_CONFIG_FILE_PATH"` + EXPANDED_PHP_CONFIG_FILE_SCAN_DIR=`eval echo "$PHP_CONFIG_FILE_SCAN_DIR"` +-INCLUDE_PATH=.:$EXPANDED_PEAR_INSTALLDIR ++INCLUDE_PATH=.:$EXPANDED_PEAR_INSTALLDIR:${EXPANDED_DATADIR}/php + + exec_prefix=$old_exec_prefix + libdir=$old_libdir diff --git a/php-ini.patch b/php-ini.patch new file mode 100644 index 0000000..fa7cfe2 --- /dev/null +++ b/php-ini.patch @@ -0,0 +1,211 @@ +--- php-5.3.20/php.ini 2013-01-22 23:20:03.433447006 +0200 ++++ php-5.3.20/php.ini 2013-01-22 23:20:03.433447006 +0200 +@@ -82,6 +82,20 @@ + ; much more verbose when it comes to errors. We recommending using the + ; development version only in development environments as errors shown to + ; application users can inadvertently leak otherwise secure information. ++; ++; This is the default settings file for new PHP installations from ++; PLD Linux Distribution. ++; ++; It's based mainly on php.ini-production, but with some changes made with ++; security in mind (see below, consult also http://php.net/manual/en/security.php). ++; ++; Please note, that in PLD installations /etc/php/php.ini file ++; contains global settings for all SAPIs (cgi, cli, apache...), ++; and after reading this file, SAPI-specific file (/etc/php/php-cgi-fcgi.ini, ++; /etc/php/php-cli.ini, /etc/php/php-apache.ini...) is INCLUDED ++; (so you don't have to duplicate whole large file to override only ++; few options) ++ + + ;;;;;;;;;;;;;;;;;;; + ; Quick Reference ; +@@ -223,7 +237,7 @@ + ; Development Value: Off + ; Production Value: Off + ; http://php.net/short-open-tag +-short_open_tag = Off ++short_open_tag = On + + ; Allow ASP-style <% %> tags. + ; http://php.net/asp-tags +@@ -428,7 +428,7 @@ + ; threat in any way, but it makes it possible to determine whether you use PHP + ; on your server or not. + ; http://php.net/expose-php +-expose_php = On ++expose_php = Off + + ;;;;;;;;;;;;;;;;;;; + ; Resource Limits ; +@@ -804,7 +804,7 @@ + + ; Directory in which the loadable extensions (modules) reside. + ; http://php.net/extension-dir +-; extension_dir = "./" ++extension_dir = "/usr/lib/php" + ; On windows: + ; extension_dir = "ext" + +@@ -826,53 +826,6 @@ + ; http://php.net/enable-dl + enable_dl = Off + +-; cgi.force_redirect is necessary to provide security running PHP as a CGI under +-; most web servers. Left undefined, PHP turns this on by default. You can +-; turn it off here AT YOUR OWN RISK +-; **You CAN safely turn this off for IIS, in fact, you MUST.** +-; http://php.net/cgi.force-redirect +-;cgi.force_redirect = 1 +- +-; if cgi.nph is enabled it will force cgi to always sent Status: 200 with +-; every request. PHP's default behavior is to disable this feature. +-;cgi.nph = 1 +- +-; if cgi.force_redirect is turned on, and you are not running under Apache or Netscape +-; (iPlanet) web servers, you MAY need to set an environment variable name that PHP +-; will look for to know it is OK to continue execution. Setting this variable MAY +-; cause security issues, KNOW WHAT YOU ARE DOING FIRST. +-; http://php.net/cgi.redirect-status-env +-;cgi.redirect_status_env = +- +-; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's +-; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok +-; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting +-; this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting +-; of zero causes PHP to behave as before. Default is 1. You should fix your scripts +-; to use SCRIPT_FILENAME rather than PATH_TRANSLATED. +-; http://php.net/cgi.fix-pathinfo +-;cgi.fix_pathinfo=1 +- +-; FastCGI under IIS (on WINNT based OS) supports the ability to impersonate +-; security tokens of the calling client. This allows IIS to define the +-; security context that the request runs under. mod_fastcgi under Apache +-; does not currently support this feature (03/17/2002) +-; Set to 1 if running under IIS. Default is zero. +-; http://php.net/fastcgi.impersonate +-;fastcgi.impersonate = 1 +- +-; Disable logging through FastCGI connection. PHP's default behavior is to enable +-; this feature. +-;fastcgi.logging = 0 +- +-; cgi.rfc2616_headers configuration option tells PHP what type of headers to +-; use when sending HTTP response code. If it's set 0 PHP sends Status: header that +-; is supported by Apache. When this option is set to 1 PHP will send +-; RFC2616 compliant header. +-; Default is zero. +-; http://php.net/cgi.rfc2616-headers +-;cgi.rfc2616_headers = 0 +- + ;;;;;;;;;;;;;;;; + ; File Uploads ; + ;;;;;;;;;;;;;;;; +@@ -876,11 +876,7 @@ + ; + ; extension=modulename.extension + ; +-; For example, on Windows: +-; +-; extension=msql.dll +-; +-; ... or under UNIX: ++; For example under UNIX: + ; + ; extension=msql.so + ; +@@ -899,53 +899,8 @@ + ; If you only provide the name of the extension, PHP will look for it in its + ; default extension directory. + ; +-; Windows Extensions +-; Note that ODBC support is built in, so no dll is needed for it. +-; Note that many DLL files are located in the extensions/ (PHP 4) ext/ (PHP 5) +-; extension folders as well as the separate PECL DLL download (PHP 5). +-; Be sure to appropriately set the extension_dir directive. +-; +-;extension=php_bz2.dll +-;extension=php_curl.dll +-;extension=php_fileinfo.dll +-;extension=php_gd2.dll +-;extension=php_gettext.dll +-;extension=php_gmp.dll +-;extension=php_intl.dll +-;extension=php_imap.dll +-;extension=php_interbase.dll +-;extension=php_ldap.dll +-;extension=php_mbstring.dll +-;extension=php_exif.dll ; Must be after mbstring as it depends on it +-;extension=php_mysql.dll +-;extension=php_mysqli.dll +-;extension=php_oci8.dll ; Use with Oracle 10gR2 Instant Client +-;extension=php_oci8_11g.dll ; Use with Oracle 11gR2 Instant Client +-;extension=php_openssl.dll +-;extension=php_pdo_firebird.dll +-;extension=php_pdo_mssql.dll +-;extension=php_pdo_mysql.dll +-;extension=php_pdo_oci.dll +-;extension=php_pdo_odbc.dll +-;extension=php_pdo_pgsql.dll +-;extension=php_pdo_sqlite.dll +-;extension=php_pgsql.dll +-;extension=php_pspell.dll +-;extension=php_shmop.dll +- +-; The MIBS data available in the PHP distribution must be installed. +-; See http://www.php.net/manual/en/snmp.installation.php +-;extension=php_snmp.dll +- +-;extension=php_soap.dll +-;extension=php_sockets.dll +-;extension=php_sqlite.dll +-;extension=php_sqlite3.dll +-;extension=php_sybase_ct.dll +-;extension=php_tidy.dll +-;extension=php_xmlrpc.dll +-;extension=php_xsl.dll +-;extension=php_zip.dll ++; Ideally in PLD Linux you should install appropriate php- or ++; php-pecl- package. + + ;;;;;;;;;;;;;;;;;;; + ; Module Settings ; +@@ -1235,6 +1140,9 @@ + ; http://php.net/mysql.connect-timeout + mysql.connect_timeout = 60 + ++; The name of the character set to use as the default character set. ++;mysql.connect_charset=utf8 ++ + ; Trace mode. When trace_mode is active (=On), warnings for table/index scans and + ; SQL-Errors will be displayed. + ; http://php.net/mysql.trace-mode +@@ -1274,6 +1182,9 @@ + ; http://php.net/mysqli.default-socket + mysqli.default_socket = + ++; The name of the character set to use as the default character set. ++;mysqli.connect_charset=utf8 ++ + ; Default host for mysql_connect() (doesn't apply in safe mode). + ; http://php.net/mysqli.default-host + mysqli.default_host = +@@ -1440,7 +1351,7 @@ + + [browscap] + ; http://php.net/browscap +-;browscap = extra/browscap.ini ++browscap = /etc/php/browscap.ini + + [Session] + ; Handler used to store/retrieve data. +@@ -1863,7 +1774,7 @@ + + ; Sets the directory name where SOAP extension will put cache files. + ; http://php.net/soap.wsdl-cache-dir +-soap.wsdl_cache_dir="/tmp" ++soap.wsdl_cache_dir="/var/cache/php" + + ; (time to live) Sets the number of second while cached file will be used + ; instead of original one. diff --git a/php-libpq_fs_h_path.patch b/php-libpq_fs_h_path.patch new file mode 100644 index 0000000..df29656 --- /dev/null +++ b/php-libpq_fs_h_path.patch @@ -0,0 +1,12 @@ +diff -urN php5.3-200803022130/ext/pgsql/php_pgsql.h mod/ext/pgsql/php_pgsql.h +--- php5.3-200803022130/ext/pgsql/php_pgsql.h 2008-01-30 11:31:48.000000000 +0000 ++++ mod/ext/pgsql/php_pgsql.h 2008-03-02 22:27:42.292062316 +0000 +@@ -41,7 +41,7 @@ + #define PHP_PGSQL_API __declspec(dllimport) + #endif + #else +-#include ++#include + # if defined(__GNUC__) && __GNUC__ >= 4 + # define PHP_PGSQL_API __attribute__ ((visibility("default"))) + # else diff --git a/php-libtool.patch b/php-libtool.patch new file mode 100644 index 0000000..f9713d8 --- /dev/null +++ b/php-libtool.patch @@ -0,0 +1,31 @@ +--- php-5.4.6/scripts/phpize.in~ 2012-08-23 03:02:42.000000000 +0300 ++++ php-5.4.6/scripts/phpize.in 2012-08-23 10:16:37.011306948 +0300 +@@ -6,10 +6,16 @@ + exec_prefix="`eval echo @exec_prefix@`" + phpdir="`eval echo @libdir@`/php/build" + includedir="`eval echo @includedir@`/php" ++aclocaldir="$prefix/share/aclocal" + builddir="`pwd`" + SED="@SED@" + +-FILES_BUILD="mkdep.awk scan_makefile_in.awk shtool libtool.m4" ++FILES_BUILD="mkdep.awk scan_makefile_in.awk shtool" ++if [ -f "$aclocaldir/ltsugar.m4" ]; then ++ LIBTOOL_FILES="libtool.m4 ltoptions.m4 ltsugar.m4 ltversion.m4 lt~obsolete.m4" ++else ++ LIBTOOL_FILES="libtool.m4" ++fi + FILES="acinclude.m4 Makefile.global config.sub config.guess ltmain.sh run-tests*.php" + CLEAN_FILES="$FILES *.o *.lo *.la .deps .libs/ build/ include/ modules/ install-sh \ + mkinstalldirs missing config.nice config.sub config.guess configure configure.in \ +@@ -145,8 +151,9 @@ phpize_copy_files() + test -d build || mkdir build + + (cd "$phpdir" && cp $FILES_BUILD "$builddir"/build) ++ (cd "$aclocaldir" && cp $LIBTOOL_FILES "$builddir"/build) + (cd "$phpdir" && cp $FILES "$builddir") +- (cd "$builddir" && cat acinclude.m4 ./build/libtool.m4 > aclocal.m4) ++ (cd "$builddir/build" && cat ../acinclude.m4 $LIBTOOL_FILES > ../aclocal.m4) + } + + phpize_replace_prefix() diff --git a/php-link-libs.patch b/php-link-libs.patch new file mode 100644 index 0000000..23a7acc --- /dev/null +++ b/php-link-libs.patch @@ -0,0 +1,35 @@ +--- php-4.3.0/configure.in.orig Fri Dec 27 05:07:18 2002 ++++ php-4.3.0/configure.in Thu Jan 2 20:34:43 2003 +@@ -288,7 +288,6 @@ + PHP_CHECK_FUNC(htonl, socket) + PHP_CHECK_FUNC(gethostname, nsl) + PHP_CHECK_FUNC(gethostbyaddr, nsl) +-PHP_CHECK_FUNC(yp_get_default_domain, nsl) + + PHP_CHECK_FUNC(dlopen, dl) + if test "$ac_cv_func_dlopen" = "yes"; then +--- php-5.2.0/acinclude.m4.orig 2006-12-22 21:52:13.766461055 +0100 ++++ php-5.2.0/acinclude.m4 2006-12-22 21:52:37.159794165 +0100 +@@ -1740,18 +1740,18 @@ + dnl Wrapper for AC_CHECK_LIB + dnl + AC_DEFUN([PHP_CHECK_LIBRARY], [ +- save_old_LDFLAGS=$LDFLAGS ++ save_old_LIBS=$LIBS + ac_stuff="$5" + + save_ext_shared=$ext_shared + ext_shared=yes +- PHP_EVAL_LIBLINE([$]ac_stuff, LDFLAGS) ++ PHP_EVAL_LIBLINE([$]ac_stuff, LIBS) + AC_CHECK_LIB([$1],[$2],[ +- LDFLAGS=$save_old_LDFLAGS ++ LIBS=$save_old_LIBS + ext_shared=$save_ext_shared + $3 + ],[ +- LDFLAGS=$save_old_LDFLAGS ++ LIBS=$save_old_LIBS + ext_shared=$save_ext_shared + unset ac_cv_lib_$1[]_$2 + $4 diff --git a/php-m4-divert.patch b/php-m4-divert.patch new file mode 100644 index 0000000..f4e5bb5 --- /dev/null +++ b/php-m4-divert.patch @@ -0,0 +1,79 @@ +diff -ur php-5.3.0.org/configure.in php-5.3.0/configure.in +--- php-5.3.0.org/configure.in 2009-06-26 17:44:18.000000000 +0200 ++++ php-5.3.0/configure.in 2009-08-18 12:45:19.126841759 +0200 +@@ -1,7 +1,7 @@ + ## $Id$ -*- autoconf -*- + dnl ## Process this file with autoconf to produce a configure script. + +-divert(1) ++divert(1001) + + dnl ## Diversion 1 is the autoconf + automake setup phase. We also + dnl ## set the PHP version, deal with platform-specific compile +@@ -308,7 +308,7 @@ + sinclude(TSRM/tsrm.m4) + + +-divert(2) ++divert(1002) + + dnl ## Diversion 2 is where we set PHP-specific options and come up + dnl ## with reasonable default values for them. We check for pthreads here +@@ -347,7 +347,7 @@ + PTHREADS_FLAGS + fi + +-divert(3) ++divert(1003) + + dnl ## In diversion 3 we check for compile-time options to the PHP + dnl ## core and how to deal with different system dependencies. +@@ -702,7 +702,7 @@ + PHP_CRYPT_R_STYLE + fi + +-divert(4) ++divert(1004) + + dnl ## In diversion 4 we check user-configurable general settings. + +@@ -943,7 +943,7 @@ + AC_MSG_RESULT([using system default]) + fi + +-divert(5) ++divert(1005) + + dnl ## In diversion 5 we check which extensions should be compiled. + dnl ## All of these are normally in the extension directories. +diff -ur php-5.3.0.org/ext/standard/config.m4 php-5.3.0/ext/standard/config.m4 +--- php-5.3.0.org/ext/standard/config.m4 2009-01-12 00:37:16.000000000 +0100 ++++ php-5.3.0/ext/standard/config.m4 2009-08-18 12:45:19.130174674 +0200 +@@ -1,6 +1,6 @@ + dnl $Id$ -*- autoconf -*- + +-divert(3)dnl ++divert(1003)dnl + + dnl + dnl Check if flush should be called explicitly after buffered io +@@ -220,7 +220,7 @@ + AC_CHECK_FUNCS(getcwd getwd asinh acosh atanh log1p hypot glob strfmon nice fpclass isinf isnan) + AC_FUNC_FNMATCH + +-divert(5)dnl ++divert(1005)dnl + + dnl + dnl Check if there is a support means of creating a new process +diff -ur php-5.3.0.org/scripts/phpize.m4 php-5.3.0/scripts/phpize.m4 +--- php-5.3.0.org/scripts/phpize.m4 2009-06-02 21:54:03.000000000 +0200 ++++ php-5.3.0/scripts/phpize.m4 2009-08-18 12:45:19.126841759 +0200 +@@ -1,6 +1,6 @@ + dnl This file becomes configure.in for self-contained extensions. + +-divert(1) ++divert(1001) + + AC_PREREQ(2.13) + AC_INIT(config.m4) diff --git a/php-m4.patch b/php-m4.patch new file mode 100644 index 0000000..e7981a4 --- /dev/null +++ b/php-m4.patch @@ -0,0 +1,11 @@ +--- php-5.3.7/build/buildcheck.sh~ 2011-05-18 21:55:34.000000000 +0200 ++++ php-5.3.7/build/buildcheck.sh 2011-08-20 18:28:38.223862911 +0200 +@@ -51,7 +51,7 @@ + echo " On Debian/Ubuntu both autoconf2.13 and autoconf2.59 packages exist." + echo " Install autoconf2.13 and set the PHP_AUTOCONF env var to " + echo " autoconf2.13 and try again." +- exit 1 ++ echo " CONTINUING ANYWAY." + else + echo "buildconf: autoconf version $ac_version (ok)" + fi diff --git a/php-mail.patch b/php-mail.patch new file mode 100644 index 0000000..272b2f9 --- /dev/null +++ b/php-mail.patch @@ -0,0 +1,84 @@ +--- php-5.2.0/ext/standard/mail.c 2006-12-01 14:20:27.881416250 +0100 ++++ php-5.2.4/ext/standard/mail.c 2007-08-31 19:25:50.777713042 +0300 +@@ -21,6 +21,8 @@ + #include + #include + #include ++#include ++#include + #include "php.h" + #include "ext/standard/info.h" + +@@ -35,6 +37,8 @@ + #include "php_ini.h" + #include "safe_mode.h" + #include "exec.h" ++#include "zend_operators.h" ++#include "zend_globals.h" + + #ifdef PHP_WIN32 + #include "win32/sendmail.h" +@@ -107,6 +111,18 @@ + return; + } + ++ /* search for To: and Subject: headers which should be specified in proper mail() parameters, not in additional headers */ ++ if (headers != NULL) { ++ if (strncasecmp(headers, "to:", sizeof("to:") - 1) == 0 || strcasestr(headers, "\nto:")) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "To: headers aren't allowed in the additional_headers parameter. Use $to parameter for that. Mail not sent."); ++ RETURN_FALSE; ++ } ++ if (strncasecmp(headers, "subject:", sizeof("subject:") - 1) == 0 || strcasestr(headers, "\nsubject:")) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Subject: headers aren't allowed in the additional_headers parameter. Use $subject parameter for that. Mail not sent."); ++ RETURN_FALSE; ++ } ++ } ++ + if (to_len > 0) { + to_r = estrndup(to, to_len); + for (; to_len; to_len--) { +@@ -231,8 +247,42 @@ + return 0; + } + #endif +- fprintf(sendmail, "To: %s\n", to); +- fprintf(sendmail, "Subject: %s\n", subject); ++ TSRMLS_FETCH(); ++ ++ if ((to != NULL) && (strlen(to)!=0)) { ++ fprintf(sendmail, "To: %s\n", to); ++ } ++ if ((subject != NULL) && (strlen(subject)!=0)) { ++ fprintf(sendmail, "Subject: %s\n", subject); ++ } ++ ++ if (PG(http_globals)[TRACK_VARS_SERVER]) { ++ zval **remote_addr, **server_name, **server_port, ++ **script_name, **http_user_agent; ++ ++ if (zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, "REMOTE_ADDR", sizeof("REMOTE_ADDR"), (void **) &remote_addr)==SUCCESS) { ++ convert_to_string_ex(remote_addr); ++ fprintf(sendmail, "HTTP-Posting-Client: %s\n", Z_STRVAL_PP(remote_addr)); ++ } ++ if (zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, "SERVER_NAME", sizeof("SERVER_NAME"), (void **) &server_name)==SUCCESS) { ++ convert_to_string_ex(server_name); ++ fprintf(sendmail, "HTTP-Posting-URI: %s", Z_STRVAL_PP(server_name)); ++ if (zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, "SERVER_PORT", sizeof("SERVER_PORT"), (void **) &server_port)==SUCCESS) { ++ convert_to_string_ex(server_port); ++ fprintf(sendmail, ":%s", Z_STRVAL_PP(server_port)); ++ } ++ if (zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, "SCRIPT_NAME", sizeof("SCRIPT_NAME"), (void **) &script_name)==SUCCESS) { ++ convert_to_string_ex(script_name); ++ fprintf(sendmail, "%s", Z_STRVAL_PP(script_name)); ++ } ++ fprintf(sendmail, "\n"); ++ } ++ if (zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, "HTTP_USER_AGENT", sizeof("HTTP_USER_AGENT"), (void **) &http_user_agent)==SUCCESS) { ++ convert_to_string_ex(http_user_agent); ++ fprintf(sendmail, "HTTP-Posting-User-Agent: %s\n", Z_STRVAL_PP(http_user_agent)); ++ } ++ } ++ + if (hdr != NULL) { + fprintf(sendmail, "%s\n", hdr); + } diff --git a/php-mod_php.conf b/php-mod_php.conf new file mode 100644 index 0000000..9a9f298 --- /dev/null +++ b/php-mod_php.conf @@ -0,0 +1,22 @@ +LoadModule php5_module modules/libphp5.so + + + + AddType application/x-httpd-php .php + + + AddType application/x-httpd-php .php3 + + + AddType application/x-httpd-php .php4 + + + AddType application/x-httpd-php .php5 + + + AddType application/x-httpd-php .inc + + + AddType application/x-httpd-php .phtml + + diff --git a/php-mysql-charsetphpini.patch b/php-mysql-charsetphpini.patch new file mode 100644 index 0000000..d3a2a64 --- /dev/null +++ b/php-mysql-charsetphpini.patch @@ -0,0 +1,76 @@ +--- php-5.2.5_p20080206.orig/ext/mysql/php_mysql.c 2008-02-06 14:22:57.652600900 +0100 ++++ php-5.2.5_p20080206/ext/mysql/php_mysql.c 2008-02-06 14:24:40.216655403 +0100 +@@ -360,6 +360,7 @@ + PHP_INI_ENTRY("mysql.default_port", NULL, PHP_INI_ALL, OnMySQLPort) + STD_PHP_INI_ENTRY("mysql.default_socket", NULL, PHP_INI_ALL, OnUpdateStringUnempty, default_socket, zend_mysql_globals, mysql_globals) + STD_PHP_INI_ENTRY("mysql.connect_timeout", "60", PHP_INI_ALL, OnUpdateLong, connect_timeout, zend_mysql_globals, mysql_globals) ++ STD_PHP_INI_ENTRY("mysql.connect_charset", NULL, PHP_INI_ALL, OnUpdateString, connect_charset, zend_mysql_globals, mysql_globals) + STD_PHP_INI_BOOLEAN("mysql.trace_mode", "0", PHP_INI_ALL, OnUpdateLong, trace_mode, zend_mysql_globals, mysql_globals) + PHP_INI_END() + /* }}} */ +@@ -376,6 +377,7 @@ + mysql_globals->connect_errno = 0; + mysql_globals->connect_error = NULL; + mysql_globals->connect_timeout = 0; ++ mysql_globals->connect_charset = NULL; + mysql_globals->trace_mode = 0; + mysql_globals->result_allocated = 0; + } +@@ -515,6 +517,7 @@ + { + char *user=NULL, *passwd=NULL, *host_and_port=NULL, *socket=NULL, *tmp=NULL, *host=NULL; + int user_len, passwd_len, host_len; ++ char *connect_charset=NULL; + char *hashed_details=NULL; + int hashed_details_length, port = MYSQL_PORT; + int client_flags = 0; +@@ -527,6 +530,7 @@ + + + connect_timeout = MySG(connect_timeout); ++ connect_charset = MySG(connect_charset); + + socket = MySG(default_socket); + +--- php-5.3.1/ext/mysql/php_mysql.c~ 2010-02-20 00:51:52.000000000 +0200 ++++ php-5.3.1/ext/mysql/php_mysql.c 2010-02-20 00:55:43.475653264 +0200 +@@ -777,6 +777,10 @@ + if (connect_timeout != -1) { + mysql_options(mysql->conn, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&connect_timeout); + } ++ ++ if (connect_charset != NULL) ++ mysql_options(mysql->conn, MYSQL_SET_CHARSET_NAME, connect_charset); ++ + #ifndef MYSQL_USE_MYSQLND + if (mysql_real_connect(mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL) + #else +@@ -826,6 +830,8 @@ + #endif + if (mysql_ping(mysql->conn)) { + if (mysql_errno(mysql->conn) == 2006) { ++ if (connect_charset != NULL) ++ mysql_options(mysql->conn, MYSQL_SET_CHARSET_NAME, connect_charset); + #ifndef MYSQL_USE_MYSQLND + if (mysql_real_connect(mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL) + #else +@@ -898,6 +904,9 @@ + if (connect_timeout != -1) + mysql_options(mysql->conn, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&connect_timeout); + ++ if (connect_charset != NULL) ++ mysql_options(mysql->conn, MYSQL_SET_CHARSET_NAME, connect_charset); ++ + #ifndef MYSQL_USE_MYSQLND + if (mysql_real_connect(mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL) + #else +--- php-5.2.5_p20080206.orig/ext/mysql/php_mysql_structs.h 2008-02-06 14:22:57.510605687 +0100 ++++ php-5.2.5_p20080206/ext/mysql/php_mysql_structs.h 2008-02-06 14:23:27.764590355 +0100 +@@ -103,6 +103,7 @@ + long default_port; + char *default_host, *default_user, *default_password; + char *default_socket; ++ char *connect_charset; + char *connect_error; + long connect_errno; + long connect_timeout; diff --git a/php-mysql-nowarning.patch b/php-mysql-nowarning.patch new file mode 100644 index 0000000..ee6e11c --- /dev/null +++ b/php-mysql-nowarning.patch @@ -0,0 +1,22 @@ +--- php-5.3.6/ext/mysql/php_mysql.c~ 2011-04-13 20:47:29.263652096 +0200 ++++ php-5.3.6/ext/mysql/php_mysql.c 2011-04-13 20:48:30.206453191 +0200 +@@ -706,7 +706,7 @@ + + #if !defined(MYSQL_USE_MYSQLND) + if ((MYSQL_VERSION_ID / 100) != (mysql_get_client_version() / 100)) { +- php_error_docref(NULL TSRMLS_CC, E_WARNING, ++ php_error_docref(NULL TSRMLS_CC, E_NOTICE, + "Headers and client library minor version mismatch. Headers:%d Library:%ld", + MYSQL_VERSION_ID, mysql_get_client_version()); + } +--- php-5.3.6/ext/mysqli/mysqli_nonapi.c~ 2011-04-13 20:47:29.273652556 +0200 ++++ php-5.3.6/ext/mysqli/mysqli_nonapi.c 2011-04-13 20:48:41.070285840 +0200 +@@ -75,7 +75,7 @@ + + #if !defined(MYSQL_USE_MYSQLND) + if ((MYSQL_VERSION_ID / 100) != (mysql_get_client_version() / 100)) { +- php_error_docref(NULL TSRMLS_CC, E_WARNING, ++ php_error_docref(NULL TSRMLS_CC, E_NOTICE, + "Headers and client library minor version mismatch. Headers:%d Library:%ld", + MYSQL_VERSION_ID, mysql_get_client_version()); + } diff --git a/php-mysqli-charsetphpini.patch b/php-mysqli-charsetphpini.patch new file mode 100644 index 0000000..895a1a7 --- /dev/null +++ b/php-mysqli-charsetphpini.patch @@ -0,0 +1,52 @@ +--- php-5.3.1/ext/mysqli/mysqli.c~ 2010-02-20 00:58:34.000000000 +0200 ++++ php-5.3.1/ext/mysqli/mysqli.c 2010-02-20 01:00:22.459111311 +0200 +@@ -602,6 +602,7 @@ + #else + STD_PHP_INI_ENTRY("mysqli.default_socket", NULL, PHP_INI_ALL, OnUpdateStringUnempty, default_socket, zend_mysqli_globals, mysqli_globals) + #endif ++ STD_PHP_INI_ENTRY("mysqli.connect_charset", NULL, PHP_INI_ALL, OnUpdateString, connect_charset, zend_mysqli_globals, mysqli_globals) + STD_PHP_INI_BOOLEAN("mysqli.reconnect", "0", PHP_INI_SYSTEM, OnUpdateLong, reconnect, zend_mysqli_globals, mysqli_globals) + STD_PHP_INI_BOOLEAN("mysqli.allow_local_infile", "1", PHP_INI_SYSTEM, OnUpdateLong, allow_local_infile, zend_mysqli_globals, mysqli_globals) + #ifdef MYSQLI_USE_MYSQLND +@@ -475,6 +476,7 @@ + mysqli_globals->default_user = NULL; + mysqli_globals->default_pw = NULL; + mysqli_globals->default_socket = NULL; ++ mysqli_globals->connect_charset = NULL; + mysqli_globals->reconnect = 0; + mysqli_globals->report_mode = 0; + mysqli_globals->report_ht = 0; +--- php-5.3.4/ext/mysqli/mysqli_nonapi.c~ 2010-12-12 23:07:03.000000000 +0200 ++++ php-5.3.4/ext/mysqli/mysqli_nonapi.c 2010-12-12 23:07:36.497424912 +0200 +@@ -61,7 +61,7 @@ + MY_MYSQL *mysql = NULL; + MYSQLI_RESOURCE *mysqli_resource = NULL; + zval *object = getThis(); +- char *hostname = NULL, *username=NULL, *passwd=NULL, *dbname=NULL, *socket=NULL; ++ char *hostname = NULL, *username=NULL, *passwd=NULL, *dbname=NULL, *socket=NULL, *connect_charset=NULL; + int hostname_len = 0, username_len = 0, passwd_len = 0, dbname_len = 0, socket_len = 0; + zend_bool persistent = FALSE; + long port = 0, flags = 0; +@@ -241,6 +241,12 @@ + } + #endif + ++ connect_charset = MyG(connect_charset); ++ ++ if (connect_charset != NULL) { ++ mysql_options(mysql->mysql, MYSQL_SET_CHARSET_NAME, connect_charset); ++ } ++ + #if !defined(MYSQLI_USE_MYSQLND) + if (mysql_real_connect(mysql->mysql, hostname, username, passwd, dbname, port, socket, CLIENT_MULTI_RESULTS) == NULL) + #else +--- php-5.3.1/ext/mysqli/php_mysqli_structs.h~ 2009-10-14 16:51:25.000000000 +0300 ++++ php-5.3.1/ext/mysqli/php_mysqli_structs.h 2010-02-20 01:04:56.512214846 +0200 +@@ -358,6 +358,7 @@ + char *default_user; + char *default_socket; + char *default_pw; ++ char *connect_charset; + long reconnect; + long allow_local_infile; + long strict; diff --git a/php-no_pear_install.patch b/php-no_pear_install.patch new file mode 100644 index 0000000..ac326e1 --- /dev/null +++ b/php-no_pear_install.patch @@ -0,0 +1,12 @@ +diff -ur php5.3-200807242030/configure.in mod/configure.in +--- php5.3-200807242030/configure.in 2008-07-21 10:34:20.000000000 +0000 ++++ mod/configure.in 2008-07-25 07:34:45.430571275 +0000 +@@ -1385,7 +1385,7 @@ + fi; + + all_targets="$lcov_target \$(OVERALL_TARGET) \$(PHP_MODULES) \$(PHP_ZEND_EX) \$(PHP_CLI_TARGET) $pharcmd" +-install_targets="$install_modules install-build install-headers install-programs $install_pear $pharcmd_install" ++install_targets="$install_modules install-build install-headers install-programs $pharcmd_install" + + case $PHP_SAPI in + cli) diff --git a/php-nohttpd.patch b/php-nohttpd.patch new file mode 100644 index 0000000..dcaafc4 --- /dev/null +++ b/php-nohttpd.patch @@ -0,0 +1,15 @@ +diff -urBb php-5.1.0RC1.org/sapi/apache2handler/config.m4 php-5.1.0RC1/sapi/apache2handler/config.m4 +--- php-5.1.0RC1.org/sapi/apache2handler/config.m4 2005-08-05 10:14:54.000000000 +0200 ++++ php-5.1.0RC1/sapi/apache2handler/config.m4 2005-08-25 15:09:38.486655320 +0200 +@@ -58,9 +58,9 @@ + + # Test that we're trying to configure with apache 2.x + PHP_AP_EXTRACT_VERSION($APXS_HTTPD) +- if test "$APACHE_VERSION" -le 2000000; then ++ if test "$APACHE_VERSION" -gt 0 -a "$APACHE_VERSION" -le 2000000; then + AC_MSG_ERROR([You have enabled Apache 2 support while your server is Apache 1.3. Please use the appropiate switch --with-apxs (without the 2)]) +- elif test "$APACHE_VERSION" -lt 2000044; then ++ elif test "$APACHE_VERSION" -gt 0 -a "$APACHE_VERSION" -lt 2000044; then + AC_MSG_ERROR([Please note that Apache version >= 2.0.44 is required]) + fi + diff --git a/php-oracle-instantclient.patch b/php-oracle-instantclient.patch new file mode 100644 index 0000000..3322dc2 --- /dev/null +++ b/php-oracle-instantclient.patch @@ -0,0 +1,63 @@ +--- php-5.3.3/ext/oci8/config.m4.orig 2010-06-25 23:18:09.000000000 +0200 ++++ php-5.3.3/ext/oci8/config.m4 2010-09-10 19:37:23.484315002 +0200 +@@ -304,6 +304,9 @@ + + AC_MSG_CHECKING([Oracle Instant Client SDK header directory]) + ++ dnl Header directory for Instant Client SDK PLD RPM install ++ OCISDKPLDINC=$PHP_OCI8_INSTANT_CLIENT/../include/oracle/client ++ + dnl Header directory for Instant Client SDK RPM install + OCISDKRPMINC=`echo "$PHP_OCI8_INSTANT_CLIENT" | $PHP_OCI8_SED -e 's!^/usr/lib/oracle/\(.*\)/client\('${PHP_OCI8_IC_LIBDIR_SUFFIX}'\)*/lib[/]*$!/usr/include/oracle/\1/client\2!'` + +@@ -313,7 +316,11 @@ + dnl Header directory for manual installation + OCISDKMANINC=`echo "$PHP_OCI8_INSTANT_CLIENT" | $PHP_OCI8_SED -e 's!\(.*\)/lib[/]*$!\1/include!'` + +- if test -f "$OCISDKRPMINC/oci.h"; then ++ if test -f "$OCISDKPLDINC/oci.h"; then ++ AC_MSG_RESULT($OCISDKPLDINC) ++ PHP_ADD_INCLUDE($OCISDKPLDINC) ++ OCI8INCDIR=$OCISDKPLDINC ++ elif test -f "$OCISDKRPMINC/oci.h"; then + AC_MSG_RESULT($OCISDKRPMINC) + PHP_ADD_INCLUDE($OCISDKRPMINC) + OCI8INCDIR=$OCISDKRPMINC +--- php-5.3.3/ext/pdo_oci/config.m4~ 2010-02-04 02:12:14.000000000 +0100 ++++ php-5.3.3/ext/pdo_oci/config.m4 2010-09-10 19:58:31.206315023 +0200 +@@ -6,8 +6,10 @@ + AC_DEFUN([AC_PDO_OCI_VERSION],[ + AC_MSG_CHECKING([Oracle version]) + for OCI_VER in $SUPPORTED_LIB_VERS; do +- if test -f $PDO_OCI_DIR/lib/libclntsh.$SHLIB_SUFFIX_NAME.$OCI_VER; then ++ if test -f $1/lib/libclntsh.$SHLIB_SUFFIX_NAME.$OCI_VER; then + PDO_OCI_VERSION="$OCI_VER" ++ elif test -f $1/libclntsh.$SHLIB_SUFFIX_NAME.$OCI_VER; then ++ PDO_OCI_VERSION="$OCI_VER" + fi + done + if test -z "$PDO_OCI_VERSION"; then +@@ -103,6 +103,9 @@ + elif test -f $PDO_OCI_IC_PREFIX/$PDO_OCI_CLIENT_DIR/include/oci.h ; then + PHP_ADD_INCLUDE($PDO_OCI_IC_PREFIX/$PDO_OCI_CLIENT_DIR/include) + AC_MSG_RESULT($PDO_OCI_IC_PREFIX/$PDO_OCI_CLIENT_DIR/include) ++ elif test -f $PDO_OCI_IC_PREFIX/../include/oracle/client/oci.h ; then ++ PHP_ADD_INCLUDE($PDO_OCI_IC_PREFIX/../include/oracle/client) ++ AC_MSG_RESULT($PDO_OCI_IC_PREFIX/../include/oracle/client) + else + AC_MSG_ERROR([I'm too dumb to figure out where the include dir is in your Instant Client install]) + fi +@@ -103,7 +103,12 @@ + else + AC_MSG_ERROR([I'm too dumb to figure out where the libraries are in your Instant Client install]) + fi +- PDO_OCI_VERSION="`echo $PDO_OCI_IC_VERS | cut -d. -f1-2`" ++ __PDO_OCI_VERSION="`echo $PDO_OCI_IC_VERS | cut -d. -f1-2`" ++ if test -n "$__PDO_OCI_VERSION" ; then ++ PDO_OCI_VERSION=$__PDO_OCI_VERSION ++ else ++ AC_PDO_OCI_VERSION($PDO_OCI_IC_PREFIX) ++ fi + else + AC_PDO_OCI_CHECK_LIB_DIR($PDO_OCI_DIR) + diff --git a/php-pdo_mysql-charsetphpini.patch b/php-pdo_mysql-charsetphpini.patch new file mode 100644 index 0000000..36a7c95 --- /dev/null +++ b/php-pdo_mysql-charsetphpini.patch @@ -0,0 +1,66 @@ +This is damn ugly patch if you need to update it, see PHP_5_2 branch version to +understand what this patch is supposed to do as in 5.3 the ini section is +enabled only if mysqlnd driver is enabled which makes the contexts really +small. + +--- php-5.3.1/ext/pdo_mysql/mysql_driver.c~ 2010-02-20 01:08:04.000000000 +0200 ++++ php-5.3.1/ext/pdo_mysql/mysql_driver.c 2010-02-20 01:08:52.982186037 +0200 +@@ -436,6 +436,7 @@ + pdo_mysql_db_handle *H; + int i, ret = 0; + char *host = NULL, *unix_socket = NULL; ++ char *connect_charset = NULL; + unsigned int port = 3306; + char *dbname; + struct pdo_data_src_parser vars[] = { +@@ -731,6 +731,12 @@ + password_len = strlen(dbh->password); + } + ++ connect_charset = PDO_MYSQL_G(connect_charset); ++ ++ if (connect_charset != NULL) { ++ mysql_options(H->server, MYSQL_SET_CHARSET_NAME, connect_charset); ++ } ++ + if (mysqlnd_connect(H->server, host, dbh->username, dbh->password, password_len, dbname, dbname_len, + port, unix_socket, connect_opts, PDO_MYSQL_G(mysqlnd_thd_zval_cache) TSRMLS_CC) == NULL) { + #else +--- php-5.3.3/ext/pdo_mysql/pdo_mysql.c~ 2010-07-24 19:23:14.000000000 +0300 ++++ php-5.3.3/ext/pdo_mysql/pdo_mysql.c 2010-07-24 19:24:48.363581841 +0300 +@@ -56,6 +56,7 @@ + #if PDO_DBG_ENABLED + STD_PHP_INI_ENTRY("pdo_mysql.debug", NULL, PHP_INI_SYSTEM, OnUpdateString, debug, zend_pdo_mysql_globals, pdo_mysql_globals) + #endif ++ STD_PHP_INI_ENTRY("pdo_mysql.connect_charset", NULL, PHP_INI_ALL, OnUpdateString, connect_charset, zend_pdo_mysql_globals, pdo_mysql_globals) + PHP_INI_END() + /* }}} */ + +@@ -89,9 +90,7 @@ + static PHP_MSHUTDOWN_FUNCTION(pdo_mysql) + { + php_pdo_unregister_driver(&pdo_mysql_driver); +-#if PDO_USE_MYSQLND + UNREGISTER_INI_ENTRIES(); +-#endif + + return SUCCESS; + } +@@ -161,6 +161,7 @@ + pdo_mysql_globals->debug = NULL; /* The actual string */ + pdo_mysql_globals->dbg = NULL; /* The DBG object*/ + #endif ++ pdo_mysql_globals->connect_charset = NULL; + } + /* }}} */ + +--- php-5.3.2RC3/ext/pdo_mysql/php_pdo_mysql_int.h~ 2010-02-04 11:37:38.000000000 +0200 ++++ php-5.3.2RC3/ext/pdo_mysql/php_pdo_mysql_int.h 2010-02-26 19:11:47.484055898 +0200 +@@ -69,6 +69,7 @@ + char *debug; /* The actual string */ + MYSQLND_DEBUG *dbg; /* The DBG object */ + #endif ++ char *connect_charset; + #if defined(PHP_WIN32) && !PDO_DBG_ENABLED + /* dummy member so we get at least one member in the struct + * and avoids build errors. diff --git a/php-pear.patch b/php-pear.patch new file mode 100644 index 0000000..400359d --- /dev/null +++ b/php-pear.patch @@ -0,0 +1,42 @@ +--- php-5.3.1/configure.in~ 2010-02-19 23:26:13.000000000 +0200 ++++ php-5.3.1/configure.in 2010-02-19 23:27:58.273207305 +0200 +@@ -934,11 +934,6 @@ + with_pear=no + fi + +-# If CLI is disabled -> disable PEAR +-if test "$PHP_CLI" = "no"; then +- with_pear=no +-fi +- + PHP_ARG_WITH(pear, [whether to install PEAR], + [ --with-pear=DIR Install PEAR in DIR [PREFIX/lib/php] + --without-pear Do not install PEAR], DEFAULT, yes) +@@ -1023,11 +1023,11 @@ + dnl + dnl PEAR dependancies + dnl +- if test "$PHP_XML" = "no"; then +- pear_error_msg="$pear_error_msg +- PEAR requires XML to be enabled. Add --enable-xml to the configure line. (or --without-pear)" +- fi +- ++dnl if test "$PHP_XML" = "no"; then ++dnl pear_error_msg="$pear_error_msg ++dnl PEAR requires XML to be enabled. Add --enable-xml to the configure line. (or --without-pear)" ++dnl fi ++dnl + dnl + dnl if test "$PHP_XMLRPC" = "no"; then + dnl pear_error_msg="$pear_error_msg +--- php-5.2.6/sapi/cli/config.m4~ 2008-11-16 18:35:31.000000000 +0200 ++++ php-5.2.6/sapi/cli/config.m4 2008-11-20 19:04:12.585061299 +0200 +@@ -4,7 +4,7 @@ + + PHP_ARG_ENABLE(cli,, + [ --disable-cli Disable building CLI version of PHP +- (this forces --without-pear)], yes, no) ++ ], yes, no) + + AC_MSG_CHECKING(for CLI build) + if test "$PHP_CLI" != "no"; then diff --git a/php-pldlogo.patch b/php-pldlogo.patch new file mode 100644 index 0000000..2b67aac --- /dev/null +++ b/php-pldlogo.patch @@ -0,0 +1,176 @@ +--- php-4.3.3RC3/ext/standard/info.c.orig 2003-06-19 18:43:41.000000000 +0200 ++++ php-4.3.3RC3/ext/standard/info.c 2003-08-16 21:37:18.705836072 +0200 +@@ -518,6 +518,21 @@ + PUTS(!sapi_module.phpinfo_as_text?"
":"\n"); + PUTS(zend_version); + php_info_print_box_end(); ++ /* PLD Linux */ ++ php_info_print_box_start(0); ++ if (expose_php && !sapi_module.phpinfo_as_text) { ++ PUTS("\"PLD\n"); ++ } ++ PUTS("This server is using PLD Linux."); ++ if (!sapi_module.phpinfo_as_text) ++ PUTS("
More information at http://www.pld-linux.org/.
\n"); ++ else ++ PUTS("\nMore information at http://www.pld-linux.org/.\n"); ++ php_info_print_box_end(); + efree(php_uname); + } + +diff -urN php-4.2.1RC2.org/ext/standard/info.h php-4.2.1RC2/ext/standard/info.h +--- php-4.2.1RC2.org/ext/standard/info.h Sat May 11 20:49:24 2002 ++++ php-4.2.1RC2/ext/standard/info.h Sat May 11 20:49:40 2002 +@@ -54,6 +54,7 @@ + #define PHP_EGG_LOGO_GUID "PHPE9568F36-D428-11d2-A769-00AA001ACF42" + #define ZEND_LOGO_GUID "PHPE9568F35-D428-11d2-A769-00AA001ACF42" + #define PHP_CREDITS_GUID "PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000" ++#define PLD_LOGO_GUID "PHPE9568F40-D428-11d2-A769-00AA001ACF42" + + PHP_FUNCTION(phpversion); + PHP_FUNCTION(phpinfo); +--- php-4.3.0.org/main/logos.h Sat May 11 20:49:24 2002 ++++ php-4.3.0/main/logos.h Sat May 11 20:50:32 2002 +@@ -1503,1 +1503,127 @@ + 249, 249, 207, 233, 5, 4, 0, 59 }; ++ ++ ++unsigned char pld_logo[] = { ++ 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, ++ 0, 13, 73, 72, 68, 82, 0, 0, 0, 80, ++ 0, 0, 0, 50, 8, 3, 0, 0, 0, 252, ++ 243, 172, 206, 0, 0, 2, 46, 80, 76, 84, ++ 69, 192, 192, 192, 0, 0, 99, 0, 0, 97, ++ 0, 0, 96, 0, 0, 95, 0, 0, 94, 0, ++ 0, 93, 0, 0, 91, 2, 2, 98, 6, 6, ++ 102, 6, 6, 101, 11, 11, 101, 14, 14, 111, ++ 15, 15, 103, 16, 16, 107, 21, 21, 111, 26, ++ 26, 111, 27, 27, 112, 28, 28, 115, 27, 27, ++ 109, 29, 29, 114, 30, 30, 114, 31, 31, 115, ++ 34, 34, 119, 36, 36, 120, 35, 35, 117, 36, ++ 36, 119, 36, 36, 117, 38, 38, 120, 40, 40, ++ 121, 42, 42, 123, 42, 42, 122, 41, 41, 118, ++ 42, 42, 120, 44, 44, 125, 47, 47, 128, 46, ++ 46, 120, 49, 49, 124, 53, 53, 130, 55, 55, ++ 133, 59, 59, 133, 63, 63, 138, 61, 61, 134, ++ 60, 60, 131, 58, 58, 125, 64, 64, 137, 63, ++ 63, 135, 60, 60, 129, 61, 61, 129, 65, 65, ++ 135, 67, 67, 138, 64, 64, 131, 69, 69, 140, ++ 71, 71, 141, 70, 70, 139, 70, 70, 137, 70, ++ 70, 136, 71, 71, 137, 68, 68, 131, 76, 76, ++ 142, 79, 79, 146, 78, 78, 143, 79, 79, 144, ++ 79, 79, 143, 74, 74, 134, 74, 74, 133, 83, ++ 83, 147, 89, 89, 154, 82, 82, 141, 90, 90, ++ 154, 90, 90, 153, 88, 88, 150, 91, 91, 153, ++ 90, 90, 151, 93, 93, 152, 98, 98, 159, 96, ++ 96, 156, 91, 91, 148, 96, 96, 155, 94, 94, ++ 152, 88, 88, 142, 89, 89, 143, 100, 100, 160, ++ 93, 93, 147, 103, 103, 162, 101, 101, 159, 92, ++ 92, 144, 96, 96, 149, 106, 106, 164, 98, 98, ++ 152, 96, 96, 148, 108, 108, 165, 106, 106, 162, ++ 101, 101, 154, 102, 102, 155, 103, 103, 156, 111, ++ 111, 167, 103, 103, 155, 112, 112, 167, 104, 104, ++ 155, 112, 112, 164, 116, 116, 168, 109, 109, 156, ++ 118, 118, 168, 127, 127, 177, 125, 125, 174, 125, ++ 125, 173, 111, 111, 154, 127, 127, 175, 124, 124, ++ 171, 128, 128, 176, 137, 137, 184, 137, 137, 183, ++ 128, 128, 171, 125, 125, 166, 140, 140, 185, 126, ++ 126, 167, 137, 137, 180, 143, 143, 185, 141, 141, ++ 183, 146, 146, 188, 144, 144, 185, 148, 148, 189, ++ 138, 138, 175, 137, 137, 174, 148, 148, 187, 149, ++ 149, 185, 158, 158, 195, 157, 157, 193, 153, 153, ++ 187, 164, 164, 199, 166, 166, 201, 165, 165, 200, ++ 156, 156, 188, 155, 155, 187, 160, 160, 192, 171, ++ 171, 204, 169, 169, 202, 170, 170, 202, 177, 177, ++ 209, 158, 158, 187, 174, 174, 205, 166, 166, 195, ++ 173, 173, 203, 173, 173, 202, 169, 169, 197, 167, ++ 167, 194, 168, 168, 194, 184, 184, 212, 173, 173, ++ 198, 187, 187, 213, 185, 185, 210, 183, 183, 208, ++ 189, 189, 214, 194, 194, 218, 189, 189, 213, 184, ++ 184, 207, 183, 183, 206, 195, 195, 218, 199, 199, ++ 222, 200, 200, 222, 196, 196, 217, 198, 198, 218, ++ 194, 194, 214, 188, 188, 207, 204, 204, 224, 197, ++ 197, 215, 209, 209, 227, 208, 208, 226, 207, 207, ++ 225, 206, 206, 224, 205, 205, 223, 208, 208, 225, ++ 205, 205, 222, 196, 196, 212, 211, 211, 227, 206, ++ 206, 222, 213, 213, 229, 209, 209, 224, 216, 216, ++ 231, 212, 212, 227, 202, 202, 216, 219, 219, 233, ++ 217, 217, 231, 204, 204, 217, 226, 226, 235, 152, ++ 38, 201, 129, 0, 0, 0, 1, 116, 82, 78, ++ 83, 0, 64, 230, 216, 102, 0, 0, 0, 1, ++ 98, 75, 71, 68, 185, 58, 184, 22, 96, 0, ++ 0, 2, 57, 73, 68, 65, 84, 120, 218, 99, ++ 96, 24, 156, 32, 195, 207, 92, 180, 159, 138, ++ 230, 21, 123, 173, 101, 8, 148, 164, 158, 121, ++ 249, 210, 64, 98, 134, 10, 245, 12, 228, 9, ++ 3, 18, 157, 217, 212, 51, 16, 236, 217, 164, ++ 30, 170, 153, 167, 92, 2, 36, 58, 100, 168, ++ 102, 158, 115, 20, 136, 204, 76, 161, 150, 121, ++ 221, 198, 32, 114, 150, 236, 60, 106, 25, 40, ++ 54, 29, 68, 26, 53, 80, 203, 60, 241, 62, ++ 16, 25, 212, 70, 45, 243, 52, 107, 64, 100, ++ 179, 22, 181, 204, 155, 239, 2, 166, 148, 106, ++ 169, 101, 160, 4, 152, 76, 42, 164, 150, 121, ++ 222, 213, 96, 202, 140, 90, 230, 109, 115, 7, ++ 83, 174, 147, 168, 101, 96, 197, 22, 16, 57, ++ 197, 2, 72, 180, 80, 197, 192, 157, 96, 82, ++ 61, 145, 129, 97, 38, 187, 19, 181, 92, 201, ++ 16, 193, 217, 10, 36, 125, 217, 52, 168, 100, ++ 222, 10, 249, 180, 34, 16, 29, 206, 42, 69, ++ 29, 3, 155, 96, 229, 106, 48, 155, 53, 85, ++ 12, 12, 113, 128, 177, 84, 89, 230, 82, 195, ++ 192, 232, 0, 24, 107, 29, 179, 28, 53, 12, ++ 76, 48, 128, 51, 35, 89, 167, 82, 193, 192, ++ 82, 94, 4, 155, 195, 146, 10, 6, 78, 96, ++ 222, 1, 103, 219, 50, 81, 195, 207, 76, 241, ++ 112, 230, 68, 150, 201, 84, 48, 208, 159, 101, ++ 25, 156, 205, 149, 76, 13, 39, 10, 240, 65, ++ 25, 11, 54, 120, 10, 18, 171, 137, 17, 78, ++ 96, 130, 173, 220, 252, 43, 193, 140, 133, 113, ++ 237, 28, 32, 101, 64, 64, 145, 129, 12, 12, ++ 142, 58, 149, 27, 65, 180, 97, 163, 16, 84, ++ 25, 65, 19, 241, 27, 8, 4, 75, 64, 68, ++ 110, 172, 30, 220, 64, 176, 51, 17, 8, 76, ++ 65, 25, 112, 63, 48, 194, 20, 97, 49, 122, ++ 209, 108, 32, 177, 88, 209, 30, 102, 32, 212, ++ 84, 168, 129, 16, 2, 137, 135, 112, 33, 92, ++ 4, 13, 212, 167, 130, 72, 17, 109, 152, 189, ++ 48, 3, 161, 16, 46, 132, 144, 35, 96, 96, ++ 153, 9, 136, 180, 211, 71, 87, 11, 119, 24, ++ 3, 134, 57, 248, 13, 172, 50, 5, 145, 233, ++ 10, 240, 240, 96, 100, 100, 68, 210, 11, 115, ++ 24, 52, 104, 81, 194, 16, 123, 228, 116, 197, ++ 128, 200, 114, 97, 130, 233, 5, 103, 148, 163, ++ 129, 222, 80, 16, 57, 221, 138, 90, 230, 49, ++ 172, 206, 2, 83, 53, 100, 185, 16, 27, 88, ++ 227, 6, 166, 230, 64, 67, 134, 17, 150, 228, ++ 144, 248, 48, 247, 48, 34, 83, 56, 193, 52, ++ 31, 48, 181, 137, 1, 158, 118, 145, 12, 68, ++ 209, 79, 68, 190, 4, 129, 149, 57, 168, 78, ++ 64, 55, 16, 97, 14, 146, 11, 225, 110, 71, ++ 214, 2, 149, 223, 236, 65, 158, 129, 12, 8, ++ 67, 144, 19, 20, 3, 195, 246, 60, 178, 12, ++ 100, 192, 105, 224, 230, 2, 36, 3, 209, 35, ++ 133, 120, 3, 17, 202, 150, 235, 46, 69, 15, ++ 117, 202, 92, 184, 202, 6, 191, 129, 24, 177, ++ 140, 97, 32, 35, 170, 129, 12, 106, 29, 152, ++ 6, 50, 50, 162, 196, 37, 138, 48, 186, 79, ++ 81, 5, 25, 24, 214, 215, 17, 149, 186, 200, ++ 0, 0, 218, 35, 72, 230, 144, 1, 81, 42, ++ 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, ++ 96, 130 }; +diff -urN php-4.2.1RC2.org/main/php_logos.c php-4.2.1RC2/main/php_logos.c +--- php-4.2.1RC2.org/main/php_logos.c Sat May 11 20:49:24 2002 ++++ php-4.2.1RC2/main/php_logos.c Sat May 11 20:51:05 2002 +@@ -56,6 +56,7 @@ + php_register_info_logo(PHP_LOGO_GUID , "image/gif", php_logo , sizeof(php_logo)); + php_register_info_logo(PHP_EGG_LOGO_GUID, "image/gif", php_egg_logo, sizeof(php_egg_logo)); + php_register_info_logo(ZEND_LOGO_GUID , "image/gif", zend_logo , sizeof(zend_logo)); ++ php_register_info_logo(PLD_LOGO_GUID , "image/png", pld_logo , sizeof(pld_logo)); + + return SUCCESS; + } diff --git a/php-readline.patch b/php-readline.patch new file mode 100644 index 0000000..d94a353 --- /dev/null +++ b/php-readline.patch @@ -0,0 +1,12 @@ +diff -urN php-5.1.0RC1.org/sapi/cli/config.m4 php-5.1.0RC1/sapi/cli/config.m4 +--- php-5.1.0RC1.org/sapi/cli/config.m4 2005-08-25 19:54:02.051504000 +0200 ++++ php-5.1.0RC1/sapi/cli/config.m4 2005-08-25 19:54:28.699452976 +0200 +@@ -29,7 +29,7 @@ + BUILD_CLI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -Lnetware -lphp5lib -o \$(SAPI_CLI_PATH)" + ;; + *) +- BUILD_CLI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) libphp_common.la \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CLI_PATH)" ++ BUILD_CLI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) libphp_common.la \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) \$(READLINE_SHARED_LIBADD) -o \$(SAPI_CLI_PATH)" + ;; + esac + INSTALL_CLI="\$(mkinstalldirs) \$(INSTALL_ROOT)\$(bindir); \$(INSTALL) -m 0755 \$(SAPI_CLI_PATH) \$(INSTALL_ROOT)\$(bindir)/\$(program_prefix)php\$(program_suffix)\$(EXEEXT)" diff --git a/php-sapi-ini-file.patch b/php-sapi-ini-file.patch new file mode 100644 index 0000000..e282b98 --- /dev/null +++ b/php-sapi-ini-file.patch @@ -0,0 +1,79 @@ +--- php-5.3.0/main/php_ini.c 2009-07-06 17:36:45.529879052 +0200 ++++ php-5.3.2/main/php_ini.c 2010-03-17 17:55:16.800313459 +0200 +@@ -358,6 +358,11 @@ + } + /* }}} */ + ++static int php_csort(const struct dirent **a, const struct dirent **b) ++{ ++ return strcmp((*a)->d_name,(*b)->d_name); ++} ++ + /* {{{ php_init_config + */ + int php_init_config(TSRMLS_D) +@@ -480,6 +485,24 @@ + } + } + } ++ /* Search (global) php.ini file in search path */ ++ if (!fh.handle.fp) { ++ fh.handle.fp = php_fopen_with_path("php.ini", "r", php_ini_search_path, &php_ini_opened_path TSRMLS_CC); ++ if (fh.handle.fp) { ++ fh.filename = php_ini_opened_path; ++ PG(safe_mode) = safe_mode_state; ++ PG(open_basedir) = open_basedir; ++ fh.type = ZEND_HANDLE_FP; ++ zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash TSRMLS_CC); ++ safe_mode_state = PG(safe_mode); ++ open_basedir = PG(open_basedir); ++ PG(safe_mode) = 0; ++ PG(open_basedir) = NULL; ++ fh.handle.fp = NULL; ++ efree(php_ini_opened_path); ++ fh.filename = php_ini_opened_path = NULL; ++ } ++ } + + /* Otherwise search for php-%sapi-module-name%.ini file in search path */ + if (!fh.handle.fp) { +@@ -492,14 +515,6 @@ + fh.filename = php_ini_opened_path; + } + } +- +- /* If still no ini file found, search for php.ini file in search path */ +- if (!fh.handle.fp) { +- fh.handle.fp = php_fopen_with_path("php.ini", "r", php_ini_search_path, &php_ini_opened_path TSRMLS_CC); +- if (fh.handle.fp) { +- fh.filename = php_ini_opened_path; +- } +- } + } + + if (free_ini_search_path) { +@@ -610,12 +625,14 @@ + zend_llist scanned_ini_list; + zend_llist_element *element; + int l, total_l = 0; ++ const char *fmt = "%s:" PHP_CONFIG_FILE_PATH "/%s.d"; + + /* List of found ini files */ + zend_llist_init(&scanned_ini_list, sizeof(char *), (llist_dtor_func_t) free_estring, 1); + + /* Split by paths_separator and load ini-files from all paths */ +- path_copy = estrdup(php_ini_scanned_path); ++ path_copy = emalloc(strlen(php_ini_scanned_path) + strlen(fmt) + strlen(sapi_module.name)); ++ sprintf(path_copy, fmt, php_ini_scanned_path, sapi_module.name); + ini_path = php_strtok_r(path_copy, paths_separator, &last); + + while (ini_path != NULL) { +@@ -636,7 +653,7 @@ + struct dirent **namelist; + int ini_path_len = strlen(ini_path); + +- if ((ndir = php_scandir(ini_path, &namelist, 0, php_alphasort)) > 0) { ++ if ((ndir = php_scandir(ini_path, &namelist, 0, php_csort)) > 0) { + memset(&fh2, 0, sizeof(fh2)); + + for (i = 0; i < ndir; i++) { diff --git a/php-sh.patch b/php-sh.patch new file mode 100644 index 0000000..e2c6770 --- /dev/null +++ b/php-sh.patch @@ -0,0 +1,13 @@ +--- php-5.1.6/acinclude.m4.orig 2006-11-21 10:43:13.179505000 +0100 ++++ php-5.1.6/acinclude.m4 2006-11-21 10:55:32.479505000 +0100 +@@ -68,8 +68,8 @@ + changequote({,}) + ep_dir="`echo $1|$SED 's%/*[^/][^/]*/*$%%'`" + changequote([,]) +- ep_realdir="`(cd \"$ep_dir\" && pwd)`" +- $2="$ep_realdir/`basename \"$1\"`" ++ ep_realdir="$(cd "$ep_dir" && pwd)" ++ $2="$ep_realdir/$(basename "$1")" + fi + ]) + diff --git a/php-shared.patch b/php-shared.patch new file mode 100644 index 0000000..04b547b --- /dev/null +++ b/php-shared.patch @@ -0,0 +1,69 @@ +--- php-5.2.4/Makefile.global~ 2007-08-31 19:13:58.000000000 +0300 ++++ php-5.2.4/Makefile.global 2007-08-31 19:19:33.799017413 +0300 +@@ -13,8 +13,12 @@ + + build-modules: $(PHP_MODULES) + +-libphp$(PHP_MAJOR_VERSION).la: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) +- $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -rpath $(phptempdir) $(EXTRA_LDFLAGS) $(LDFLAGS) $(PHP_RPATHS) $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -o $@ ++libphp_common.la: $(PHP_GLOBAL_OBJS) ++ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -rpath $(phptempdir) -avoid-version $(LDFLAGS) $(PHP_RPATHS) $(PHP_GLOBAL_OBJS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -o $@ -release $(PHP_VERSION) ++ -@$(LIBTOOL) --silent --mode=install cp $@ $(phptempdir)/$@ >/dev/null 2>&1 ++ ++libphp$(PHP_MAJOR_VERSION).la: libphp_common.la $(PHP_SAPI_OBJS) ++ $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -rpath $(phptempdir) $(EXTRA_LDFLAGS) $(LDFLAGS) $(PHP_RPATHS) $(phptempdir)/libphp_common.la $(PHP_SAPI_OBJS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -o $@ + -@$(LIBTOOL) --silent --mode=install cp $@ $(phptempdir)/$@ >/dev/null 2>&1 + + libs/libphp$(PHP_MAJOR_VERSION).bundle: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) +@@ -25,10 +29,10 @@ + install-sapi: $(OVERALL_TARGET) + @echo "Installing PHP SAPI module: $(PHP_SAPI)" + -@$(mkinstalldirs) $(INSTALL_ROOT)$(bindir) +- -@if test ! -r $(phptempdir)/libphp$(PHP_MAJOR_VERSION).$(SHLIB_DL_SUFFIX_NAME); then \ ++ -@if test ! -r $(phptempdir)/libphp_common.$(SHLIB_DL_SUFFIX_NAME); then \ + for i in 0.0.0 0.0 0; do \ +- if test -r $(phptempdir)/libphp$(PHP_MAJOR_VERSION).$(SHLIB_DL_SUFFIX_NAME).$$i; then \ +- $(LN_S) $(phptempdir)/libphp$(PHP_MAJOR_VERSION).$(SHLIB_DL_SUFFIX_NAME).$$i $(phptempdir)/libphp$(PHP_MAJOR_VERSION).$(SHLIB_DL_SUFFIX_NAME); \ ++ if test -r $(phptempdir)/libphp_common.$(SHLIB_DL_SUFFIX_NAME).$$i; then \ ++ $(LN_S) $(phptempdir)/libphp_common.$(SHLIB_DL_SUFFIX_NAME).$$i $(phptempdir)/libphp_common.$(SHLIB_DL_SUFFIX_NAME); \ + break; \ + fi; \ + done; \ +--- php-5.0.0.org/sapi/cgi/config9.m4 2004-07-25 22:41:53.698171496 +0200 ++++ php-5.0.0/sapi/cgi/config9.m4 2004-07-25 22:42:04.894469400 +0200 +@@ -156,7 +156,7 @@ + BUILD_CGI="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_SAPI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)" + ;; + *) +- BUILD_CGI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)" ++ BUILD_CGI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) libphp_common.la \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)" + ;; + esac + +--- php-5.0.0.org/sapi/cgi/Makefile.frag 2004-07-25 22:41:53.696171800 +0200 ++++ php-5.0.0/sapi/cgi/Makefile.frag 2004-07-25 22:42:04.895469248 +0200 +@@ -1,2 +1,2 @@ +-$(SAPI_CGI_PATH): $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) ++$(SAPI_CGI_PATH): libphp_common.la $(PHP_SAPI_OBJS) + $(BUILD_CGI) +--- php-5.0.0.org/sapi/cli/config.m4 2004-07-25 22:41:53.700171192 +0200 ++++ php-5.0.0/sapi/cli/config.m4 2004-07-25 22:42:04.895469248 +0200 +@@ -27,7 +27,7 @@ + BUILD_CLI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CLI_PATH)" + ;; + *) +- BUILD_CLI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CLI_PATH)" ++ BUILD_CLI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) libphp_common.la \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CLI_PATH)" + ;; + esac + INSTALL_CLI="\$(mkinstalldirs) \$(INSTALL_ROOT)\$(bindir); \$(INSTALL) -m 0755 \$(SAPI_CLI_PATH) \$(INSTALL_ROOT)\$(bindir)/\$(program_prefix)php\$(program_suffix)" +--- php-5.0.0.org/sapi/cli/Makefile.frag 2004-07-25 22:41:53.699171344 +0200 ++++ php-5.0.0/sapi/cli/Makefile.frag 2004-07-25 22:42:04.896469096 +0200 +@@ -1,6 +1,6 @@ + cli: $(SAPI_CLI_PATH) + +-$(SAPI_CLI_PATH): $(PHP_GLOBAL_OBJS) $(PHP_CLI_OBJS) ++$(SAPI_CLI_PATH): libphp_common.la $(PHP_CLI_OBJS) + $(BUILD_CLI) + + install-cli: $(SAPI_CLI_PATH) diff --git a/php-silent-session-cleanup.patch b/php-silent-session-cleanup.patch new file mode 100644 index 0000000..5833736 --- /dev/null +++ b/php-silent-session-cleanup.patch @@ -0,0 +1,10 @@ +--- php-5.3.0/ext/session/mod_files.c~ 2009-05-18 18:10:09.000000000 +0200 ++++ php-5.3.0/ext/session/mod_files.c 2009-08-07 08:41:53.029357590 +0200 +@@ -217,7 +217,6 @@ + + dir = opendir(dirname); + if (!dir) { +- php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ps_files_cleanup_dir: opendir(%s) failed: %s (%d)", dirname, strerror(errno), errno); + return (0); + } + diff --git a/php-stupidapache_version.patch b/php-stupidapache_version.patch new file mode 100644 index 0000000..f2478a4 --- /dev/null +++ b/php-stupidapache_version.patch @@ -0,0 +1,15 @@ +--- php-5.3.1/acinclude.m4~ 2009-11-26 00:49:53.000000000 +0200 ++++ php-5.3.1/acinclude.m4 2009-11-26 00:51:11.466867803 +0200 +@@ -2582,7 +2582,11 @@ + dnl version for apache1/2. + dnl + AC_DEFUN([PHP_AP_EXTRACT_VERSION],[ +- ac_output=`$1 -v 2>&1 | grep version | $SED -e 's/Oracle-HTTP-//'` ++ if test "$with_apache_version" != "no"; then ++ ac_output="foo bar baz $with_apache_version" ++ else ++ ac_output=`$1 -v 2>&1 | grep version | $SED -e 's/Oracle-HTTP-//'` ++ fi + ac_IFS=$IFS + IFS="- /. + " diff --git a/php-systzdata.patch b/php-systzdata.patch new file mode 100644 index 0000000..f841e9b --- /dev/null +++ b/php-systzdata.patch @@ -0,0 +1,619 @@ +Add support for use of the system timezone database, rather +than embedding a copy. Discussed upstream but was not desired. + +History: +r9: fix another compile error without --with-system-tzdata configured (Michael Heimpold) +r8: fix compile error without --with-system-tzdata configured +r7: improve check for valid timezone id to exclude directories +r6: fix fd leak in r5, fix country code/BC flag use in + timezone_identifiers_list() using system db, + fix use of PECL timezonedb to override system db, +r5: reverts addition of "System/Localtime" fake tzname. + updated for 5.3.0, parses zone.tab to pick up mapping between + timezone name, country code and long/lat coords +r4: added "System/Localtime" tzname which uses /etc/localtime +r3: fix a crash if /usr/share/zoneinfo doesn't exist (Raphael Geissert) +r2: add filesystem trawl to set up name alias index +r1: initial revision + +--- a/ext/date/lib/parse_tz.c ++++ b/ext/date/lib/parse_tz.c +@@ -24,6 +24,16 @@ + + #include "timelib.h" + ++#ifdef HAVE_SYSTEM_TZDATA ++#include ++#include ++#include ++#include ++#include ++ ++#include "php_scandir.h" ++#endif ++ + #include + + #ifdef HAVE_LOCALE_H +@@ -35,7 +45,12 @@ + #else + #include + #endif ++ ++#ifndef HAVE_SYSTEM_TZDATA + #include "timezonedb.h" ++#endif ++ ++#include + + #if (defined(__APPLE__) || defined(__APPLE_CC__)) && (defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__)) + # if defined(__LITTLE_ENDIAN__) +@@ -55,9 +70,14 @@ + + static void read_preamble(const unsigned char **tzf, timelib_tzinfo *tz) + { +- /* skip ID */ +- *tzf += 4; +- ++ if (memcmp(tzf, "TZif", 4) == 0) { ++ *tzf += 20; ++ return; ++ } ++ ++ /* skip ID */ ++ *tzf += 4; ++ + /* read BC flag */ + tz->bc = (**tzf == '\1'); + *tzf += 1; +@@ -260,7 +280,397 @@ void timelib_dump_tzinfo(timelib_tzinfo + } + } + +-static int seek_to_tz_position(const unsigned char **tzf, char *timezone, const timelib_tzdb *tzdb) ++#ifdef HAVE_SYSTEM_TZDATA ++ ++#ifdef HAVE_SYSTEM_TZDATA_PREFIX ++#define ZONEINFO_PREFIX HAVE_SYSTEM_TZDATA_PREFIX ++#else ++#define ZONEINFO_PREFIX "/usr/share/zoneinfo" ++#endif ++ ++/* System timezone database pointer. */ ++static const timelib_tzdb *timezonedb_system = NULL; ++ ++/* Hash table entry for the cache of the zone.tab mapping table. */ ++struct location_info { ++ char code[2]; ++ double latitude, longitude; ++ char name[64]; ++ char *comment; ++ struct location_info *next; ++}; ++ ++/* Cache of zone.tab. */ ++static struct location_info **system_location_table; ++ ++/* Size of the zone.tab hash table; a random-ish prime big enough to ++ * prevent too many collisions. */ ++#define LOCINFO_HASH_SIZE (1021) ++ ++static uint32_t tz_hash(const char *str) ++{ ++ const unsigned char *p = (const unsigned char *)str; ++ uint32_t hash = 5381; ++ int c; ++ ++ while ((c = *p++) != '\0') { ++ hash = (hash << 5) ^ hash ^ c; ++ } ++ ++ return hash % LOCINFO_HASH_SIZE; ++} ++ ++/* Parse an ISO-6709 date as used in zone.tab. Returns end of the ++ * parsed string on success, or NULL on parse error. On success, ++ * writes the parsed number to *result. */ ++static char *parse_iso6709(char *p, double *result) ++{ ++ double v, sign; ++ char *pend; ++ size_t len; ++ ++ if (*p == '+') ++ sign = 1.0; ++ else if (*p == '-') ++ sign = -1.0; ++ else ++ return NULL; ++ ++ p++; ++ for (pend = p; *pend >= '0' && *pend <= '9'; pend++) ++ ;; ++ ++ /* Annoying encoding used by zone.tab has no decimal point, so use ++ * the length to determine the format: ++ * ++ * 4 = DDMM ++ * 5 = DDDMM ++ * 6 = DDMMSS ++ * 7 = DDDMMSS ++ */ ++ len = pend - p; ++ if (len < 4 || len > 7) { ++ return NULL; ++ } ++ ++ /* p => [D]DD */ ++ v = (p[0] - '0') * 10.0 + (p[1] - '0'); ++ p += 2; ++ if (len == 5 || len == 7) ++ v = v * 10.0 + (*p++ - '0'); ++ /* p => MM[SS] */ ++ v += (10.0 * (p[0] - '0') ++ + p[1] - '0') / 60.0; ++ p += 2; ++ /* p => [SS] */ ++ if (len > 5) { ++ v += (10.0 * (p[0] - '0') ++ + p[1] - '0') / 3600.0; ++ p += 2; ++ } ++ ++ /* Round to five decimal place, not because it's a good idea, ++ * but, because the builtin data uses rounded data, so, match ++ * that. */ ++ *result = round(v * sign * 100000.0) / 100000.0; ++ ++ return p; ++} ++ ++/* This function parses the zone.tab file to build up the mapping of ++ * timezone to country code and geographic location, and returns a ++ * hash table. The hash table is indexed by the function: ++ * ++ * tz_hash(timezone-name) ++ */ ++static struct location_info **create_location_table(void) ++{ ++ struct location_info **li, *i; ++ char zone_tab[PATH_MAX]; ++ char line[512]; ++ FILE *fp; ++ ++ strncpy(zone_tab, ZONEINFO_PREFIX "/zone.tab", sizeof zone_tab); ++ ++ fp = fopen(zone_tab, "r"); ++ if (!fp) { ++ return NULL; ++ } ++ ++ li = calloc(LOCINFO_HASH_SIZE, sizeof *li); ++ ++ while (fgets(line, sizeof line, fp)) { ++ char *p = line, *code, *name, *comment; ++ uint32_t hash; ++ double latitude, longitude; ++ ++ while (isspace(*p)) ++ p++; ++ ++ if (*p == '#' || *p == '\0' || *p == '\n') ++ continue; ++ ++ if (!isalpha(p[0]) || !isalpha(p[1]) || p[2] != '\t') ++ continue; ++ ++ /* code => AA */ ++ code = p; ++ p[2] = 0; ++ p += 3; ++ ++ /* coords => [+-][D]DDMM[SS][+-][D]DDMM[SS] */ ++ p = parse_iso6709(p, &latitude); ++ if (!p) { ++ continue; ++ } ++ p = parse_iso6709(p, &longitude); ++ if (!p) { ++ continue; ++ } ++ ++ if (!p || *p != '\t') { ++ continue; ++ } ++ ++ /* name = string */ ++ name = ++p; ++ while (*p != '\t' && *p && *p != '\n') ++ p++; ++ ++ *p++ = '\0'; ++ ++ /* comment = string */ ++ comment = p; ++ while (*p != '\t' && *p && *p != '\n') ++ p++; ++ ++ if (*p == '\n' || *p == '\t') ++ *p = '\0'; ++ ++ hash = tz_hash(name); ++ i = malloc(sizeof *i); ++ memcpy(i->code, code, 2); ++ strncpy(i->name, name, sizeof i->name); ++ i->comment = strdup(comment); ++ i->longitude = longitude; ++ i->latitude = latitude; ++ i->next = li[hash]; ++ li[hash] = i; ++ /* printf("%s [%u, %f, %f]\n", name, hash, latitude, longitude); */ ++ } ++ ++ fclose(fp); ++ ++ return li; ++} ++ ++/* Return location info from hash table, using given timezone name. ++ * Returns NULL if the name could not be found. */ ++const struct location_info *find_zone_info(struct location_info **li, ++ const char *name) ++{ ++ uint32_t hash = tz_hash(name); ++ const struct location_info *l; ++ ++ if (!li) { ++ return NULL; ++ } ++ ++ for (l = li[hash]; l; l = l->next) { ++ if (strcasecmp(l->name, name) == 0) ++ return l; ++ } ++ ++ return NULL; ++} ++ ++/* Filter out some non-tzdata files and the posix/right databases, if ++ * present. */ ++static int index_filter(const struct dirent *ent) ++{ ++ return strcmp(ent->d_name, ".") != 0 ++ && strcmp(ent->d_name, "..") != 0 ++ && strcmp(ent->d_name, "posix") != 0 ++ && strcmp(ent->d_name, "posixrules") != 0 ++ && strcmp(ent->d_name, "right") != 0 ++ && strstr(ent->d_name, ".tab") == NULL; ++} ++ ++static int sysdbcmp(const void *first, const void *second) ++{ ++ const timelib_tzdb_index_entry *alpha = first, *beta = second; ++ ++ return strcmp(alpha->id, beta->id); ++} ++ ++ ++/* Create the zone identifier index by trawling the filesystem. */ ++static void create_zone_index(timelib_tzdb *db) ++{ ++ size_t dirstack_size, dirstack_top; ++ size_t index_size, index_next; ++ timelib_tzdb_index_entry *db_index; ++ char **dirstack; ++ ++ /* LIFO stack to hold directory entries to scan; each slot is a ++ * directory name relative to the zoneinfo prefix. */ ++ dirstack_size = 32; ++ dirstack = malloc(dirstack_size * sizeof *dirstack); ++ dirstack_top = 1; ++ dirstack[0] = strdup(""); ++ ++ /* Index array. */ ++ index_size = 64; ++ db_index = malloc(index_size * sizeof *db_index); ++ index_next = 0; ++ ++ do { ++ struct dirent **ents; ++ char name[PATH_MAX], *top; ++ int count; ++ ++ /* Pop the top stack entry, and iterate through its contents. */ ++ top = dirstack[--dirstack_top]; ++ snprintf(name, sizeof name, ZONEINFO_PREFIX "/%s", top); ++ ++ count = php_scandir(name, &ents, index_filter, php_alphasort); ++ ++ while (count > 0) { ++ struct stat st; ++ const char *leaf = ents[count - 1]->d_name; ++ ++ snprintf(name, sizeof name, ZONEINFO_PREFIX "/%s/%s", ++ top, leaf); ++ ++ if (strlen(name) && stat(name, &st) == 0) { ++ /* Name, relative to the zoneinfo prefix. */ ++ const char *root = top; ++ ++ if (root[0] == '/') root++; ++ ++ snprintf(name, sizeof name, "%s%s%s", root, ++ *root ? "/": "", leaf); ++ ++ if (S_ISDIR(st.st_mode)) { ++ if (dirstack_top == dirstack_size) { ++ dirstack_size *= 2; ++ dirstack = realloc(dirstack, ++ dirstack_size * sizeof *dirstack); ++ } ++ dirstack[dirstack_top++] = strdup(name); ++ } ++ else { ++ if (index_next == index_size) { ++ index_size *= 2; ++ db_index = realloc(db_index, ++ index_size * sizeof *db_index); ++ } ++ ++ db_index[index_next++].id = strdup(name); ++ } ++ } ++ ++ free(ents[--count]); ++ } ++ ++ if (count != -1) free(ents); ++ free(top); ++ } while (dirstack_top); ++ ++ qsort(db_index, index_next, sizeof *db_index, sysdbcmp); ++ ++ db->index = db_index; ++ db->index_size = index_next; ++ ++ free(dirstack); ++} ++ ++#define FAKE_HEADER "1234\0??\1??" ++#define FAKE_UTC_POS (7 - 4) ++ ++/* Create a fake data segment for database 'sysdb'. */ ++static void fake_data_segment(timelib_tzdb *sysdb, ++ struct location_info **info) ++{ ++ size_t n; ++ char *data, *p; ++ ++ data = malloc(3 * sysdb->index_size + 7); ++ ++ p = mempcpy(data, FAKE_HEADER, sizeof(FAKE_HEADER) - 1); ++ ++ for (n = 0; n < sysdb->index_size; n++) { ++ const struct location_info *li; ++ timelib_tzdb_index_entry *ent; ++ ++ ent = (timelib_tzdb_index_entry *)&sysdb->index[n]; ++ ++ /* Lookup the timezone name in the hash table. */ ++ if (strcmp(ent->id, "UTC") == 0) { ++ ent->pos = FAKE_UTC_POS; ++ continue; ++ } ++ ++ li = find_zone_info(info, ent->id); ++ if (li) { ++ /* If found, append the BC byte and the ++ * country code; set the position for this ++ * section of timezone data. */ ++ ent->pos = (p - data) - 4; ++ *p++ = '\1'; ++ *p++ = li->code[0]; ++ *p++ = li->code[1]; ++ } ++ else { ++ /* If not found, the timezone data can ++ * point at the header. */ ++ ent->pos = 0; ++ } ++ } ++ ++ sysdb->data = (unsigned char *)data; ++} ++ ++/* Returns true if the passed-in stat structure describes a ++ * probably-valid timezone file. */ ++static int is_valid_tzfile(const struct stat *st) ++{ ++ return S_ISREG(st->st_mode) && st->st_size > 20; ++} ++ ++/* Return the mmap()ed tzfile if found, else NULL. On success, the ++ * length of the mapped data is placed in *length. */ ++static char *map_tzfile(const char *timezone, size_t *length) ++{ ++ char fname[PATH_MAX]; ++ struct stat st; ++ char *p; ++ int fd; ++ ++ if (timezone[0] == '\0' || strstr(timezone, "..") != NULL) { ++ return NULL; ++ } ++ ++ snprintf(fname, sizeof fname, ZONEINFO_PREFIX "/%s", timezone); ++ ++ fd = open(fname, O_RDONLY); ++ if (fd == -1) { ++ return NULL; ++ } else if (fstat(fd, &st) != 0 || !is_valid_tzfile(&st)) { ++ close(fd); ++ return NULL; ++ } ++ ++ *length = st.st_size; ++ p = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); ++ close(fd); ++ ++ return p != MAP_FAILED ? p : NULL; ++} ++ ++#endif ++ ++static int inmem_seek_to_tz_position(const unsigned char **tzf, char *timezone, const timelib_tzdb *tzdb) + { + int left = 0, right = tzdb->index_size - 1; + #ifdef HAVE_SETLOCALE +@@ -299,36 +709,128 @@ static int seek_to_tz_position(const uns + return 0; + } + ++static int seek_to_tz_position(const unsigned char **tzf, char *timezone, ++ char **map, size_t *maplen, ++ const timelib_tzdb *tzdb) ++{ ++#ifdef HAVE_SYSTEM_TZDATA ++ if (tzdb == timezonedb_system) { ++ char *orig; ++ ++ orig = map_tzfile(timezone, maplen); ++ if (orig == NULL) { ++ return 0; ++ } ++ ++ (*tzf) = (unsigned char *)orig ; ++ *map = orig; ++ ++ return 1; ++ } ++ else ++#endif ++ { ++ return inmem_seek_to_tz_position(tzf, timezone, tzdb); ++ } ++} ++ + const timelib_tzdb *timelib_builtin_db(void) + { ++#ifdef HAVE_SYSTEM_TZDATA ++ if (timezonedb_system == NULL) { ++ timelib_tzdb *tmp = malloc(sizeof *tmp); ++ ++ tmp->version = "0.system"; ++ tmp->data = NULL; ++ create_zone_index(tmp); ++ system_location_table = create_location_table(); ++ fake_data_segment(tmp, system_location_table); ++ timezonedb_system = tmp; ++ } ++ ++ ++ return timezonedb_system; ++#else + return &timezonedb_builtin; ++#endif + } + + const timelib_tzdb_index_entry *timelib_timezone_builtin_identifiers_list(int *count) + { ++#ifdef HAVE_SYSTEM_TZDATA ++ *count = timezonedb_system->index_size; ++ return timezonedb_system->index; ++#else + *count = sizeof(timezonedb_idx_builtin) / sizeof(*timezonedb_idx_builtin); + return timezonedb_idx_builtin; ++#endif + } + + int timelib_timezone_id_is_valid(char *timezone, const timelib_tzdb *tzdb) + { + const unsigned char *tzf; +- return (seek_to_tz_position(&tzf, timezone, tzdb)); ++ ++#ifdef HAVE_SYSTEM_TZDATA ++ if (tzdb == timezonedb_system) { ++ char fname[PATH_MAX]; ++ struct stat st; ++ ++ if (timezone[0] == '\0' || strstr(timezone, "..") != NULL) { ++ return 0; ++ } ++ ++ snprintf(fname, sizeof fname, ZONEINFO_PREFIX "/%s", timezone); ++ ++ return stat(fname, &st) == 0 && is_valid_tzfile(&st); ++ } ++#endif ++ ++ return (inmem_seek_to_tz_position(&tzf, timezone, tzdb)); + } + + timelib_tzinfo *timelib_parse_tzfile(char *timezone, const timelib_tzdb *tzdb) + { + const unsigned char *tzf; ++ char *memmap = NULL; ++ size_t maplen; + timelib_tzinfo *tmp; + +- if (seek_to_tz_position(&tzf, timezone, tzdb)) { ++ if (seek_to_tz_position(&tzf, timezone, &memmap, &maplen, tzdb)) { + tmp = timelib_tzinfo_ctor(timezone); + + read_preamble(&tzf, tmp); + read_header(&tzf, tmp); + read_transistions(&tzf, tmp); + read_types(&tzf, tmp); +- read_location(&tzf, tmp); ++ ++#ifdef HAVE_SYSTEM_TZDATA ++ if (memmap) { ++ const struct location_info *li; ++ ++ /* TZif-style - grok the location info from the system database, ++ * if possible. */ ++ ++ if ((li = find_zone_info(system_location_table, timezone)) != NULL) { ++ tmp->location.comments = strdup(li->comment); ++ strncpy(tmp->location.country_code, li->code, 2); ++ tmp->location.longitude = li->longitude; ++ tmp->location.latitude = li->latitude; ++ tmp->bc = 1; ++ } ++ else { ++ strcpy(tmp->location.country_code, "??"); ++ tmp->bc = 0; ++ tmp->location.comments = strdup(""); ++ } ++ ++ /* Now done with the mmap segment - discard it. */ ++ munmap(memmap, maplen); ++ } else ++#endif ++ { ++ /* PHP-style - use the embedded info. */ ++ read_location(&tzf, tmp); ++ } + } else { + tmp = NULL; + } +--- a/ext/date/lib/timelib.m4 ++++ b/ext/date/lib/timelib.m4 +@@ -78,3 +78,17 @@ stdlib.h + + dnl Check for strtoll, atoll + AC_CHECK_FUNCS(strtoll atoll strftime) ++ ++PHP_ARG_WITH(system-tzdata, for use of system timezone data, ++[ --with-system-tzdata[=DIR] to specify use of system timezone data], ++no, no) ++ ++if test "$PHP_SYSTEM_TZDATA" != "no"; then ++ AC_DEFINE(HAVE_SYSTEM_TZDATA, 1, [Define if system timezone data is used]) ++ ++ if test "$PHP_SYSTEM_TZDATA" != "yes"; then ++ AC_DEFINE_UNQUOTED(HAVE_SYSTEM_TZDATA_PREFIX, "$PHP_SYSTEM_TZDATA", ++ [Define for location of system timezone data]) ++ fi ++fi ++ diff --git a/php-tds.patch b/php-tds.patch new file mode 100644 index 0000000..ef036a7 --- /dev/null +++ b/php-tds.patch @@ -0,0 +1,11 @@ +--- php-5.3.3/ext/sybase_ct/config.m4~ 2010-07-07 13:15:24.000000000 +0300 ++++ php-5.3.3/ext/sybase_ct/config.m4 2010-07-24 19:21:13.897144810 +0300 +@@ -31,7 +31,7 @@ + fi + + PHP_ADD_LIBPATH($SYBASE_CT_LIBDIR, SYBASE_CT_SHARED_LIBADD) +- if test -f $SYBASE_CT_INCDIR/tds.h || test -f $SYBASE_CT_INCDIR/tds_sysdep_public.h; then ++ if test -f $SYBASE_CT_INCDIR/tds.h || test -f $SYBASE_CT_INCDIR/tds_sysdep_public.h || test -f $SYBASE_CT_INCDIR/sybdb.h; then + PHP_ADD_LIBRARY(ct,, SYBASE_CT_SHARED_LIBADD) + SYBASE_CT_LIBS="-L$SYBASE_CT_LIBDIR -lct" + elif test -f $SYBASE_CT_INCDIR/libsybct64; then diff --git a/php-uint32_t.patch b/php-uint32_t.patch new file mode 100644 index 0000000..5e9ba01 --- /dev/null +++ b/php-uint32_t.patch @@ -0,0 +1,11 @@ +diff -ur php5.3-200903291030/Zend/zend_strtod.c mod/Zend/zend_strtod.c +--- php5.3-200903291030/Zend/zend_strtod.c 2009-03-18 12:36:20.000000000 +0100 ++++ mod/Zend/zend_strtod.c 2009-03-29 18:34:10.000000000 +0200 +@@ -93,6 +93,7 @@ + + #include + #include ++#include + + #ifdef ZTS + #include diff --git a/php-use-prog_sendmail.patch b/php-use-prog_sendmail.patch new file mode 100644 index 0000000..5f4af4e --- /dev/null +++ b/php-use-prog_sendmail.patch @@ -0,0 +1,15 @@ +--- php-5.2.6/acinclude.m4~ 2008-10-15 13:44:25.000000000 +0300 ++++ php-5.2.6/acinclude.m4 2008-10-15 13:55:05.359850285 +0300 +@@ -2037,8 +2037,10 @@ + dnl Search for the sendmail binary + dnl + AC_DEFUN([PHP_PROG_SENDMAIL], [ +- PHP_ALT_PATH=/usr/bin:/usr/sbin:/usr/etc:/etc:/usr/ucblib:/usr/lib +- AC_PATH_PROG(PROG_SENDMAIL, sendmail,[], $PATH:$PHP_ALT_PATH) ++ if test -z "$PROG_SENDMAIL"; then ++ PHP_ALT_PATH=/usr/bin:/usr/sbin:/usr/etc:/etc:/usr/ucblib:/usr/lib ++ AC_PATH_PROG(PROG_SENDMAIL, sendmail,[], $PATH:$PHP_ALT_PATH) ++ fi + PHP_SUBST(PROG_SENDMAIL) + ]) + diff --git a/php-zlib-for-getimagesize.patch b/php-zlib-for-getimagesize.patch new file mode 100644 index 0000000..9a2bc9d --- /dev/null +++ b/php-zlib-for-getimagesize.patch @@ -0,0 +1,42 @@ +make compressed .swf parsing possible, +link core php with -lz for getimagesize() +see also http://bugs.php.net/bug.php?id=29611 + +--- php-4.4.1/ext/standard/image.c 2005-07-27 14:22:36.000000000 +0300 ++++ /tmp/image.c 2006-01-06 19:14:00.000000000 +0200 +@@ -31,7 +31,7 @@ + #endif + #include "php_image.h" + +-#if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB) ++#if HAVE_ZLIB + #include "zlib.h" + #endif + +@@ -80,7 +80,7 @@ + REGISTER_LONG_CONSTANT("IMAGETYPE_JP2", IMAGE_FILETYPE_JP2, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMAGETYPE_JPX", IMAGE_FILETYPE_JPX, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("IMAGETYPE_JB2", IMAGE_FILETYPE_JB2, CONST_CS | CONST_PERSISTENT); +-#if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB) ++#if HAVE_ZLIB + REGISTER_LONG_CONSTANT("IMAGETYPE_SWC", IMAGE_FILETYPE_SWC, CONST_CS | CONST_PERSISTENT); + #endif + REGISTER_LONG_CONSTANT("IMAGETYPE_IFF", IMAGE_FILETYPE_IFF, CONST_CS | CONST_PERSISTENT); +@@ -184,7 +184,7 @@ + } + /* }}} */ + +-#if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB) ++#if HAVE_ZLIB + /* {{{ php_handle_swc + */ + static struct gfxinfo *php_handle_swc(php_stream * stream TSRMLS_DC) +@@ -1267,7 +1290,7 @@ + result = php_handle_swf(stream TSRMLS_CC); + break; + case IMAGE_FILETYPE_SWC: +-#if HAVE_ZLIB && !defined(COMPILE_DL_ZLIB) ++#if HAVE_ZLIB + result = php_handle_swc(stream TSRMLS_CC); + #else + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "The image is a compressed SWF file, but you do not have a static version of the zlib extension enabled."); diff --git a/php-zlib.patch b/php-zlib.patch new file mode 100644 index 0000000..1ee4b30 --- /dev/null +++ b/php-zlib.patch @@ -0,0 +1,15 @@ +diff -burN php-5.0.0b3/ext/zlib/zlib.c php-5.0.0b3-zlib/ext/zlib/zlib.c +--- php-5.0.0b3/ext/zlib/zlib.c 2003-09-26 10:09:53.000000000 +0200 ++++ php-5.0.0b3-zlib/ext/zlib/zlib.c 2003-12-27 00:40:53.000000000 +0100 +@@ -979,6 +979,11 @@ + + if (ZLIBG(output_handler) && strlen(ZLIBG(output_handler))) { + php_start_ob_buffer_named(ZLIBG(output_handler), 0, 1 TSRMLS_CC); ++ if (sapi_add_header("Content-Encoding: gzip", sizeof("Content-Encoding: gzip") - 1 , 1)!=FAILURE) { ++ if (sapi_add_header("Vary: Accept-Encoding", sizeof("Vary: Accept-Encoding") - 1, 1)==FAILURE) { ++ SG(sapi_headers).send_default_content_type = 0; ++ } ++ } + } + return SUCCESS; + } diff --git a/php5324.spec.patch b/php5324.spec.patch new file mode 100644 index 0000000..0d7ff5c --- /dev/null +++ b/php5324.spec.patch @@ -0,0 +1,54 @@ +diff --git a/php.spec b/php.spec +index 7179ac8..408ea04 100644 +--- a/php.spec ++++ b/php.spec +@@ -118,7 +118,7 @@ ERROR: You need to select at least one Apache SAPI to build shared modules. + %define php_suffix %{nil} + %endif + +-%define rel 2 ++%define rel 1 + Summary: PHP: Hypertext Preprocessor + Summary(fr.UTF-8): Le langage de script embarque-HTML PHP + Summary(pl.UTF-8): Język skryptowy PHP +@@ -126,13 +126,13 @@ Summary(pt_BR.UTF-8): A linguagem de script PHP + Summary(ru.UTF-8): PHP Версии 5 - язык препроцессирования HTML-файлов, выполняемый на сервере + Summary(uk.UTF-8): PHP Версії 5 - мова препроцесування HTML-файлів, виконувана на сервері + Name: %{orgname}%{php_suffix} +-Version: 5.3.23 ++Version: 5.3.24 + Release: %{rel}%{?with_type_hints:.th}%{?with_oci8:.oci} + Epoch: 4 + License: PHP + Group: Libraries + Source0: http://www.php.net/distributions/%{orgname}-%{version}.tar.bz2 +-# Source0-md5: ab7bd1dd3bbc8364cb9fcaa2d79fb502 ++# Source0-md5: 9820604df98c648297dcd31ffb8214e8 + Source2: %{orgname}-mod_%{orgname}.conf + Source3: %{orgname}-cgi-fcgi.ini + Source4: %{orgname}-apache.ini +@@ -145,7 +145,7 @@ Source12: %{orgname}-branch.sh + Source13: dep-tests.sh + Source14: skip-tests.sh + Source15: http://litespeedtech.com/packages/lsapi/%{orgname}-litespeed-%{litespeed_version}.tgz +-# Source15-md5: 9d58485d5fd6b5f5fefcec41b9ce283e ++# Source15-md5: 0478a087be50f6d785764cf182156189 + Patch0: %{orgname}-shared.patch + Patch1: %{orgname}-pldlogo.patch + Patch2: %{orgname}-mail.patch +@@ -202,7 +202,6 @@ Patch64: %{orgname}-m4.patch + # http://spot.fedorapeople.org/php-5.3.6-libzip.patch + Patch65: system-libzip.patch + Patch66: %{orgname}-db.patch +-Patch67: php-litespeed.patch + URL: http://www.php.net/ + %{?with_interbase:%{!?with_interbase_inst:BuildRequires: Firebird-devel >= 1.0.2.908-2}} + %{?with_pspell:BuildRequires: aspell-devel >= 2:0.50.0} +@@ -1960,7 +1959,6 @@ cp -p php.ini-production php.ini + %patch66 -p1 + %{__rm} -r sapi/litespeed + gzip -dc %{SOURCE15} | tar xf - -C sapi/ +-%patch67 -p1 + + sed -i -e '/PHP_ADD_LIBRARY_WITH_PATH/s#xmlrpc,#xmlrpc-epi,#' ext/xmlrpc/config.m4 + diff --git a/skip-tests.sh b/skip-tests.sh new file mode 100644 index 0000000..7bad37a --- /dev/null +++ b/skip-tests.sh @@ -0,0 +1,275 @@ +#!/bin/sh +# easter_date() +mv ext/calendar/tests/easter_date.phpt{,.skip} +# unixtojd() +mv ext/calendar/tests/unixtojd.phpt{,.skip} +# curl_setopt() basic parameter test +mv ext/curl/tests/curl_setopt_error.phpt{,.skip} +# timezone_abbreviations_list() tests +mv ext/date/tests/010.phpt{,.skip} +# Test DateTime::modify() function : usage variation - Passing unexpected values to first argument $modify. +mv ext/date/tests/DateTime_modify_variation1.phpt{,.skip} +# Bug #48187 (DateTime::diff() corrupting microtime() result) +mv ext/date/tests/bug48187.phpt{,.skip} +# Bug #50475 (DateTime::setISODate followed by DateTime::setTime) +mv ext/date/tests/bug50475.phpt{,.skip} +# Bug #51819 (Case discrepancy in timezone names cause Uncaught exception and fatal error) +mv ext/date/tests/bug51819.phpt{,.skip} +# Bug #51994 (date_parse_from_format is parsing invalid date using 'yz' format) +mv ext/date/tests/bug51994.phpt{,.skip} +# Bug #52290 (setDate, setISODate, setTime works wrong when DateTime created from timestamp) +mv ext/date/tests/bug52290.phpt{,.skip} +# Test date_modify() function : usage variation - Passing unexpected values to second argument $format. +mv ext/date/tests/date_modify_variation2.phpt{,.skip} +# Test timezone_abbreviations_list() function : basic functionality +mv ext/date/tests/timezone_abbreviations_list_basic1.phpt{,.skip} +# Test 5: HTML Test +mv ext/dom/tests/dom005.phpt{,.skip} +# Bug #48555 (ImageFTBBox() differs from previous versions for texts with new lines) +mv ext/gd/tests/bug48555.phpt{,.skip} +# Feature Request #50283 (allow base in gmp_strval to use full range: 2 to 62, and -2 to -36) +mv ext/gmp/tests/bug50283.phpt{,.skip} +# gmp_nextprime() +mv ext/gmp/tests/gmp_nextprime.phpt{,.skip} +# InterBase: connect, close and pconnect +mv ext/interbase/tests/002.phpt{,.skip} +# InterBase: misc sql types (may take a while) +mv ext/interbase/tests/003.phpt{,.skip} +# InterBase: BLOB test +mv ext/interbase/tests/004.phpt{,.skip} +# InterBase: transactions +mv ext/interbase/tests/005.phpt{,.skip} +# InterBase: binding (may take a while) +mv ext/interbase/tests/006.phpt{,.skip} +# InterBase: array handling +mv ext/interbase/tests/007.phpt{,.skip} +# InterBase: event handling +mv ext/interbase/tests/008.phpt{,.skip} +# Bug #45373 (php crash on query with errors in params) +mv ext/interbase/tests/bug45373.phpt{,.skip} +# Bug #45575 (Segfault with invalid non-string as event handler callback) +mv ext/interbase/tests/bug45575.phpt{,.skip} +# Bug #46247 (ibase_set_event_handler() is allowing to pass callback without event) +mv ext/interbase/tests/bug46247.phpt{,.skip} +# Bug #46543 (ibase_trans() memory leaks when using wrong parameters) +mv ext/interbase/tests/bug46543.phpt{,.skip} +# ibase_affected_rows(): Basic test +mv ext/interbase/tests/ibase_affected_rows_001.phpt{,.skip} +# ibase_close(): Basic test +mv ext/interbase/tests/ibase_close_001.phpt{,.skip} +# ibase_drop_db(): Basic test +mv ext/interbase/tests/ibase_drop_db_001.phpt{,.skip} +# ibase_errmsg(): Basic test +mv ext/interbase/tests/ibase_errmsg_001.phpt{,.skip} +# ibase_free_query(): Basic test +mv ext/interbase/tests/ibase_free_query_001.phpt{,.skip} +# ibase_num_fields(): Basic test +mv ext/interbase/tests/ibase_num_fields_001.phpt{,.skip} +# ibase_num_params(): Basic test +mv ext/interbase/tests/ibase_num_params_001.phpt{,.skip} +# ibase_param_info(): Basic test +mv ext/interbase/tests/ibase_param_info_001.phpt{,.skip} +# ibase_rollback(): Basic test +mv ext/interbase/tests/ibase_rollback_001.phpt{,.skip} +# ibase_trans(): Basic test +mv ext/interbase/tests/ibase_trans_001.phpt{,.skip} +# ibase_trans(): Basic operations +mv ext/interbase/tests/ibase_trans_002.phpt{,.skip} +# get_locale() +mv ext/intl/tests/collator_get_locale.phpt{,.skip} +# collator_get_sort_key() +mv ext/intl/tests/collator_get_sort_key.phpt{,.skip} +# datefmt_format_code() and datefmt_parse_code() +mv ext/intl/tests/dateformat_format_parse.phpt{,.skip} +# datefmt_get_pattern_code and datefmt_set_pattern_code() +mv ext/intl/tests/dateformat_get_set_pattern.phpt{,.skip} +# datefmt_localtime_code() +mv ext/intl/tests/dateformat_localtime.phpt{,.skip} +# datefmt_parse_code() +mv ext/intl/tests/dateformat_parse.phpt{,.skip} +# datefmt_parse_localtime() with parse pos +mv ext/intl/tests/dateformat_parse_localtime_parsepos.phpt{,.skip} +# datefmt_parse_timestamp_code() with parse pos +mv ext/intl/tests/dateformat_parse_timestamp_parsepos.phpt{,.skip} +# datefmt_set_timezone_id_code() +mv ext/intl/tests/dateformat_set_timezone_id.phpt{,.skip} +# numfmt_format() +mv ext/intl/tests/formatter_format.phpt{,.skip} +# numfmt_format_currency() +mv ext/intl/tests/formatter_format_currency.phpt{,.skip} +# numfmt_get/set_attribute() +mv ext/intl/tests/formatter_get_set_attribute.phpt{,.skip} +# grapheme() +mv ext/intl/tests/grapheme.phpt{,.skip} +# locale_get_display_name() +mv ext/intl/tests/locale_get_display_name.phpt{,.skip} +# locale_get_display_script() +mv ext/intl/tests/locale_get_display_script.phpt{,.skip} +# locale_get_display_variant() +mv ext/intl/tests/locale_get_display_variant.phpt{,.skip} +# ldap_sasl_bind() - Basic anonymous binding +mv ext/ldap/tests/ldap_sasl_bind_basic.phpt{,.skip} +# mysql connect +mv ext/mysql/tests/001.phpt{,.skip} +# mysql_connect() +mv ext/mysql/tests/mysql_connect.phpt{,.skip} +# mysql_[p]connect() - max_links/max_persistent +mv ext/mysql/tests/mysql_max_links.phpt{,.skip} +# mysql_[p]connect() - safe_mode +mv ext/mysql/tests/mysql_sql_safe_mode.phpt{,.skip} +# mysqli_connect() +mv ext/mysqli/tests/mysqli_connect.phpt{,.skip} +# new mysqli() +mv ext/mysqli/tests/mysqli_connect_oo.phpt{,.skip} +# new mysqli() +mv ext/mysqli/tests/mysqli_connect_oo_defaults.phpt{,.skip} +# Bug #28382 (openssl_x509_parse extensions support) +mv ext/openssl/tests/bug28382.phpt{,.skip} +# Bug #47828 (segfaults when a UTF-8 conversion fails openssl_x509_parse()) +mv ext/openssl/tests/bug47828.phpt{,.skip} +# openssl_x509_parse() basic test +mv ext/openssl/tests/openssl_x509_parse_basic.phpt{,.skip} +# PDO_Firebird: connect/disconnect +mv ext/pdo_firebird/tests/connect.phpt{,.skip} +# PDO_Firebird: DDL/transactions +mv ext/pdo_firebird/tests/ddl.phpt{,.skip} +# PDO_Firebird: prepare/execute/binding +mv ext/pdo_firebird/tests/execute.phpt{,.skip} +# MySQL PDO->__construct(), options +mv ext/pdo_mysql/tests/pdo_mysql___construct_options.phpt{,.skip} +# MySQL PDO->__construct(), libmysql only options +mv ext/pdo_mysql/tests/pdo_mysql___construct_options_libmysql.phpt{,.skip} +# MySQL PDO class interface +mv ext/pdo_mysql/tests/pdo_mysql_interface.phpt{,.skip} +# PDO ODBC "long" columns +mv ext/pdo_odbc/tests/long_columns.phpt{,.skip} +# PDO SQLite Feature Request #42589 (getColumnMeta() should also return table name) +mv ext/pdo_sqlite/tests/bug_42589.phpt{,.skip} +# Test for bug 52013 about Phar::decompressFiles(). +mv ext/phar/tests/bug52013.phpt{,.skip} +# Phar and RecursiveDirectoryIterator +mv ext/phar/tests/phar_oo_005.phpt{,.skip} +# Test posix_getgrgid() function : basic functionality +mv ext/posix/tests/posix_getgrgid_basic.phpt{,.skip} +# ReflectionClass::getConstructor() +mv ext/reflection/tests/ReflectionClass_getConstructor_basic.phpt{,.skip} +# ReflectionMethod::isConstructor() +mv ext/reflection/tests/ReflectionMethod_constructor_basic.phpt{,.skip} +# ReflectionObject::getConstructor() - basic function test +mv ext/reflection/tests/ReflectionObject_getConstructor_basic.phpt{,.skip} +# a script should not be able to modify session.use_trans_sid +mv ext/session/tests/014.phpt{,.skip} +# use_trans_sid should not affect SID +mv ext/session/tests/015.phpt{,.skip} +# rewriter correctly handles attribute names which contain dashes +mv ext/session/tests/018.phpt{,.skip} +# rewriter uses arg_seperator.output for modifying URLs +mv ext/session/tests/020.phpt{,.skip} +# rewriter handles form and fieldset tags correctly +mv ext/session/tests/021.phpt{,.skip} +# Bug #31454 (Incorrect adding PHPSESSID to links, which contains \r\n) +mv ext/session/tests/bug36459.phpt{,.skip} +# Bug #41600 (url rewriter tags doesn't work with namespaced tags) +mv ext/session/tests/bug41600.phpt{,.skip} +# Test session_encode() function : error functionality +mv ext/session/tests/session_encode_error2.phpt{,.skip} +# SimpleXML: XPath +mv ext/simplexml/tests/008.phpt{,.skip} +# SOAP Server 9: setclass and setpersistence(SOAP_PERSISTENCE_SESSION) +mv ext/soap/tests/server009.phpt{,.skip} +# ext/sockets - socket_strerror - basic test +mv ext/sockets/tests/socket_strerror.phpt{,.skip} +# Bug #38759 (sqlite2 empty query causes segfault) +mv ext/sqlite/tests/bug38759.phpt{,.skip} +# sqlite, session storage test +mv ext/sqlite/tests/sqlite_session_001.phpt{,.skip} +# sqlite, session destroy test +mv ext/sqlite/tests/sqlite_session_002.phpt{,.skip} +# SQLite3::loadExtension with empty extension test +mv ext/sqlite3/tests/sqlite3_33_load_extension_param.phpt{,.skip} +# SQLite3::loadExtension with disabled extensions +mv ext/sqlite3/tests/sqlite3_34_load_extension_ext_dir.phpt{,.skip} +# SQLite3::loadExtension test with wrong parameter type +mv ext/sqlite3/tests/sqlite3_loadextension_with_wrong_param.phpt{,.skip} +# Test fscanf() function: usage variations - unsigned int formats with integer values +mv ext/standard/tests/file/fscanf_variation39.phpt{,.skip} +# Test fscanf() function: usage variations - tracking file pointer while reading +mv ext/standard/tests/file/fscanf_variation55.phpt{,.skip} +# Bug #44394 (Last two bytes missing from output) with session.use_trans_id +mv ext/standard/tests/general_functions/bug44394_2.phpt{,.skip} +# Test function getservbyname() +mv ext/standard/tests/general_functions/getservbyname_basic.phpt{,.skip} +# proc_open +mv ext/standard/tests/general_functions/proc_open02.phpt{,.skip} +# time_sleep_until() function - basic test for time_sleep_until() +mv ext/standard/tests/misc/time_sleep_until_basic.phpt{,.skip} +# htmlentities() test 2 (setlocale / fr_FR.ISO-8859-15) +mv ext/standard/tests/strings/htmlentities02.phpt{,.skip} +# htmlentities() test 4 (setlocale / ja_JP.EUC-JP) +mv ext/standard/tests/strings/htmlentities04.phpt{,.skip} +# htmlentities() test 10 (default_charset / cp1252) +mv ext/standard/tests/strings/htmlentities10.phpt{,.skip} +# htmlentities() test 11 (default_charset / ISO-8859-15) +mv ext/standard/tests/strings/htmlentities11.phpt{,.skip} +# htmlentities() test 13 (default_charset / EUC-JP) +mv ext/standard/tests/strings/htmlentities13.phpt{,.skip} +# htmlentities() test 15 (setlocale / KOI8-R) +mv ext/standard/tests/strings/htmlentities15.phpt{,.skip} +# htmlentities() / html_entity_decode() #8592 - #9002 table test +mv ext/standard/tests/strings/htmlentities17.phpt{,.skip} +# Test setlocale() function : usage variations - Setting all available locales in the platform +mv ext/standard/tests/strings/setlocale_variation2.phpt{,.skip} +# Test sscanf() function : basic functionality - unsigned format +mv ext/standard/tests/strings/sscanf_basic6.phpt{,.skip} +# msg_send() data types when not serializing +mv ext/sysvmsg/tests/006.phpt{,.skip} +# wddx session serializer handler (serialize) +mv ext/wddx/tests/004.phpt{,.skip} +# wddx session serializer handler (deserialize) +mv ext/wddx/tests/005.phpt{,.skip} +# xmlrpc_encode_request() and various arguments +mv ext/xmlrpc/tests/002.phpt{,.skip} +# Bug #40576 (double values are truncated to 6 decimal digits when encoding) +mv ext/xmlrpc/tests/bug40576_64bit.phpt{,.skip} +# Bug #45555 (Segfault with invalid non-string as register_introspection_callback) +mv ext/xmlrpc/tests/bug45555.phpt{,.skip} +# Bug #45556 (Return value from callback isn't freed) +mv ext/xmlrpc/tests/bug45556.phpt{,.skip} +# Test 10: EXSLT Support +mv ext/xsl/tests/xslt010.phpt{,.skip} +# Check xsltprocessor::registerPHPFunctions and a non-string function in xsl +mv ext/xsl/tests/xsltprocessor_registerPHPFunctions-funcnostring.phpt{,.skip} +# Check xsltprocessor::registerPHPFunctions and a undefined php function +mv ext/xsl/tests/xsltprocessor_registerPHPFunctions-funcundef.phpt{,.skip} +# show information about extension +mv sapi/cli/tests/006.phpt{,.skip} +# CLI -a and readline +mv sapi/cli/tests/016.phpt{,.skip} +# Phar::buildFromIterator() RegexIterator(RecursiveIteratorIterator), SplFileInfo as current +mv ext/phar/tests/phar_buildfromiterator10.phpt{,.skip} +# output buffering - fatalism +mv tests/output/ob_011.phpt{,.skip} +# Inconsistencies when accessing protected members +mv Zend/tests/access_modifiers_008.phpt{,.skip} +# Inconsistencies when accessing protected members - 2 +mv Zend/tests/access_modifiers_009.phpt{,.skip} +# Bug #48770 (call_user_func_array() fails to call parent from inheriting class) +mv Zend/tests/bug48770.phpt{,.skip} +# Bug #48770 (call_user_func_array() fails to call parent from inheriting class) +mv Zend/tests/bug48770_2.phpt{,.skip} +# Bug #48770 (call_user_func_array() fails to call parent from inheriting class) +mv Zend/tests/bug48770_3.phpt{,.skip} +# DBA with persistent connections +mv ext/dba/tests/dba015.phpt{,.skip} +# DBA DB4 with persistent connections +mv ext/dba/tests/dba_db4_018.phpt{,.skip} +# Bug #42718 (unsafe_raw filter not applied when configured as default filter) +mv ext/filter/tests/bug42718.phpt{,.skip} +# SimpleXML: array casting bug +mv ext/simplexml/tests/034.phpt{,.skip} +# Bug #39863 (file_exists() silently truncates after a null byte) +mv ext/standard/tests/file/bug39863.phpt{,.skip} +# DOMDocument::$validateOnParse - effectual determination (dom_document_validate_on_parse_read/dom_document_validate_on_parse_write) +mv ext/dom/tests/DOMDocument_validate_on_parse_variation.phpt{,.skip} +# Bug #40576 (double values are truncated to 6 decimal digits when encoding) +mv ext/xmlrpc/tests/bug40576.phpt{,.skip} diff --git a/spl-shared.patch b/spl-shared.patch new file mode 100644 index 0000000..0e326fd --- /dev/null +++ b/spl-shared.patch @@ -0,0 +1,86 @@ +--- php-5.3.1/ext/spl/config.m4~ 2009-11-26 23:54:34.000000000 +0000 ++++ php-5.3.1/ext/spl/config.m4 2009-11-27 08:04:05.788823797 +0000 +@@ -22,6 +22,6 @@ + CPPFLAGS=$old_CPPFLAGS + AC_DEFINE_UNQUOTED(HAVE_PACKED_OBJECT_VALUE, $ac_result, [Whether struct _zend_object_value is packed]) + AC_DEFINE(HAVE_SPL, 1, [Whether you want SPL (Standard PHP Library) support]) +- PHP_NEW_EXTENSION(spl, php_spl.c spl_functions.c spl_engine.c spl_iterators.c spl_array.c spl_directory.c spl_exceptions.c spl_observer.c spl_dllist.c spl_heap.c spl_fixedarray.c, no) ++ PHP_NEW_EXTENSION(spl, php_spl.c spl_functions.c spl_engine.c spl_iterators.c spl_array.c spl_directory.c spl_exceptions.c spl_observer.c spl_dllist.c spl_heap.c spl_fixedarray.c, $ext_shared) + PHP_INSTALL_HEADERS([ext/spl], [php_spl.h spl_array.h spl_directory.h spl_engine.h spl_exceptions.h spl_functions.h spl_iterators.h spl_observer.h spl_dllist.h spl_heap.h spl_fixedarray.h]) + PHP_ADD_EXTENSION_DEP(spl, pcre, true) +--- php-5.3.1/ext/spl/spl_iterators.c~ 2009-07-04 20:31:27.000000000 +0000 ++++ php-5.3.1/ext/spl/spl_iterators.c 2009-11-27 16:35:33.729087793 +0000 +@@ -58,7 +58,13 @@ + PHPAPI zend_class_entry *spl_ce_AppendIterator; + PHPAPI zend_class_entry *spl_ce_RegexIterator; + PHPAPI zend_class_entry *spl_ce_RecursiveRegexIterator; ++#if COMPILE_DL_SPL ++#undef spl_ce_Countable ++zend_class_entry *spl_ce_Countable; // real instance ++extern PHPAPI zend_class_entry *spl_ce_Countable_p; // external one ++#else + PHPAPI zend_class_entry *spl_ce_Countable; ++#endif + PHPAPI zend_class_entry *spl_ce_RecursiveTreeIterator; + + ZEND_BEGIN_ARG_INFO(arginfo_recursive_it_void, 0) +@@ -3286,6 +3292,10 @@ + REGISTER_SPL_STD_CLASS_EX(EmptyIterator, NULL, spl_funcs_EmptyIterator); + REGISTER_SPL_ITERATOR(EmptyIterator); + ++#if COMPILE_DL_SPL ++ spl_ce_Countable_p = spl_ce_Countable; ++#endif ++ + REGISTER_SPL_SUB_CLASS_EX(RecursiveTreeIterator, RecursiveIteratorIterator, spl_RecursiveTreeIterator_new, spl_funcs_RecursiveTreeIterator); + REGISTER_SPL_CLASS_CONST_LONG(RecursiveTreeIterator, "BYPASS_CURRENT", RTIT_BYPASS_CURRENT); + REGISTER_SPL_CLASS_CONST_LONG(RecursiveTreeIterator, "BYPASS_KEY", RTIT_BYPASS_KEY); +--- php-5.3.1/ext/spl/spl_iterators.h~ 2008-12-31 11:15:49.000000000 +0000 ++++ php-5.3.1/ext/spl/spl_iterators.h 2009-11-27 16:36:35.215748808 +0000 +@@ -51,7 +51,12 @@ + extern PHPAPI zend_class_entry *spl_ce_AppendIterator; + extern PHPAPI zend_class_entry *spl_ce_RegexIterator; + extern PHPAPI zend_class_entry *spl_ce_RecursiveRegexIterator; ++#if COMPILE_DL_SPL ++#define spl_ce_Countable spl_ce_Countable_p ++extern PHPAPI zend_class_entry *spl_ce_Countable_p; ++#else + extern PHPAPI zend_class_entry *spl_ce_Countable; ++#endif + + PHP_MINIT_FUNCTION(spl_iterators); + +--- php-5.3.1/ext/standard/array.c~ 2009-08-14 06:20:21.000000000 +0000 ++++ php-5.3.1/ext/standard/array.c 2009-11-27 16:37:15.029078323 +0000 +@@ -49,6 +49,9 @@ + #ifdef HAVE_SPL + #include "ext/spl/spl_array.h" + #endif ++#if COMPILE_DL_SPL ++PHPAPI zend_class_entry *spl_ce_Countable_p = NULL; // external one ++#endif + + /* {{{ defines */ + #define EXTR_OVERWRITE 0 +--- php-5.3.1/ext/pdo/pdo.c~ 2009-07-19 22:46:03.000000000 +0000 ++++ php-5.3.1/ext/pdo/pdo.c 2009-11-27 16:37:51.332409104 +0000 +@@ -132,7 +132,7 @@ + /* {{{ pdo_functions[] */ + #if ZEND_MODULE_API_NO >= 20050922 + static const zend_module_dep pdo_deps[] = { +-#ifdef HAVE_SPL ++#ifdef HAVE_SPL && !COMPILE_DL_SPL + ZEND_MOD_REQUIRED("spl") + #endif + {NULL, NULL, NULL} +--- php-5.3.1/ext/phar/Makefile.frag~ 2009-07-23 15:48:04.000000000 +0000 ++++ php-5.3.1/ext/phar/Makefile.frag 2009-11-30 16:10:29.687175948 +0000 +@@ -10,7 +10,7 @@ + $(top_srcdir)/build/shtool echo -n -- "$(top_builddir)/$(SAPI_CLI_PATH) -n"; \ + if test "x$(PHP_MODULES)" != "x"; then \ + $(top_srcdir)/build/shtool echo -n -- " -d extension_dir=$(top_builddir)/modules"; \ +- for i in bz2 zlib phar; do \ ++ for i in pcre spl bz2 zlib phar; do \ + if test -f "$(top_builddir)/modules/$$i.la"; then \ + . $(top_builddir)/modules/$$i.la; $(top_srcdir)/build/shtool echo -n -- " -d extension=$$dlname"; \ + fi; \ diff --git a/suhosin.patch b/suhosin.patch new file mode 100644 index 0000000..2a22f75 --- /dev/null +++ b/suhosin.patch @@ -0,0 +1,5778 @@ +diff -Nura php-5.3.9/Zend/Makefile.am suhosin-patch-5.3.9-0.9.10/Zend/Makefile.am +--- php-5.3.9/Zend/Makefile.am 2009-03-18 11:18:10.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/Zend/Makefile.am 2012-01-11 19:29:07.000000000 +0100 +@@ -17,7 +17,7 @@ + zend_objects_API.c zend_ts_hash.c zend_stream.c \ + zend_default_classes.c \ + zend_iterators.c zend_interfaces.c zend_exceptions.c \ +- zend_strtod.c zend_closures.c zend_float.c ++ zend_strtod.c zend_closures.c zend_float.c zend_canary.c zend_alloc_canary.c + + libZend_la_LDFLAGS = + libZend_la_LIBADD = @ZEND_EXTRA_LIBS@ +diff -Nura php-5.3.9/Zend/Zend.dsp suhosin-patch-5.3.9-0.9.10/Zend/Zend.dsp +--- php-5.3.9/Zend/Zend.dsp 2009-03-18 11:18:10.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/Zend/Zend.dsp 2012-01-11 19:29:07.000000000 +0100 +@@ -247,6 +247,14 @@ + # End Source File + # Begin Source File + ++SOURCE=.\zend_canary.c ++# End Source File ++# Begin Source File ++ ++SOURCE=.\zend_alloc_canary.c ++# End Source File ++# Begin Source File ++ + SOURCE=.\zend_ts_hash.c + # End Source File + # Begin Source File +diff -Nura php-5.3.9/Zend/ZendTS.dsp suhosin-patch-5.3.9-0.9.10/Zend/ZendTS.dsp +--- php-5.3.9/Zend/ZendTS.dsp 2008-07-14 11:49:03.000000000 +0200 ++++ suhosin-patch-5.3.9-0.9.10/Zend/ZendTS.dsp 2012-01-11 19:29:07.000000000 +0100 +@@ -277,6 +277,14 @@ + # End Source File + # Begin Source File + ++SOURCE=.\zend_canary.c ++# End Source File ++# Begin Source File ++ ++SOURCE=.\zend_alloc_canary.c ++# End Source File ++# Begin Source File ++ + SOURCE=.\zend_ts_hash.c + # End Source File + # Begin Source File +diff -Nura php-5.3.9/Zend/zend.c suhosin-patch-5.3.9-0.9.10/Zend/zend.c +--- php-5.3.9/Zend/zend.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/Zend/zend.c 2012-01-11 19:29:07.000000000 +0100 +@@ -60,6 +60,10 @@ + ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC); + ZEND_API char *(*zend_resolve_path)(const char *filename, int filename_len TSRMLS_DC); + ++#if SUHOSIN_PATCH ++ZEND_API void (*zend_suhosin_log)(int loglevel, char *fmt, ...); ++#endif ++ + void (*zend_on_timeout)(int seconds TSRMLS_DC); + + static void (*zend_message_dispatcher_p)(long message, void *data TSRMLS_DC); +@@ -88,6 +92,74 @@ + } + /* }}} */ + ++#if SUHOSIN_PATCH ++static ZEND_INI_MH(OnUpdateSuhosin_log_syslog) ++{ ++ if (!new_value) { ++ SPG(log_syslog) = S_ALL & ~S_SQL | S_MEMORY; ++ } else { ++ SPG(log_syslog) = atoi(new_value) | S_MEMORY; ++ } ++ return SUCCESS; ++} ++static ZEND_INI_MH(OnUpdateSuhosin_log_syslog_facility) ++{ ++ if (!new_value) { ++ SPG(log_syslog_facility) = LOG_USER; ++ } else { ++ SPG(log_syslog_facility) = atoi(new_value); ++ } ++ return SUCCESS; ++} ++static ZEND_INI_MH(OnUpdateSuhosin_log_syslog_priority) ++{ ++ if (!new_value) { ++ SPG(log_syslog_priority) = LOG_ALERT; ++ } else { ++ SPG(log_syslog_priority) = atoi(new_value); ++ } ++ return SUCCESS; ++} ++static ZEND_INI_MH(OnUpdateSuhosin_log_sapi) ++{ ++ if (!new_value) { ++ SPG(log_sapi) = S_ALL & ~S_SQL; ++ } else { ++ SPG(log_sapi) = atoi(new_value); ++ } ++ return SUCCESS; ++} ++static ZEND_INI_MH(OnUpdateSuhosin_log_script) ++{ ++ if (!new_value) { ++ SPG(log_script) = S_ALL & ~S_MEMORY; ++ } else { ++ SPG(log_script) = atoi(new_value) & (~S_MEMORY) & (~S_INTERNAL); ++ } ++ return SUCCESS; ++} ++static ZEND_INI_MH(OnUpdateSuhosin_log_scriptname) ++{ ++ if (SPG(log_scriptname)) { ++ pefree(SPG(log_scriptname),1); ++ } ++ SPG(log_scriptname) = NULL; ++ if (new_value) { ++ SPG(log_scriptname) = pestrdup(new_value,1); ++ } ++ return SUCCESS; ++} ++static ZEND_INI_MH(OnUpdateSuhosin_log_phpscript) ++{ ++ if (!new_value) { ++ SPG(log_phpscript) = S_ALL & ~S_MEMORY; ++ } else { ++ SPG(log_phpscript) = atoi(new_value) & (~S_MEMORY) & (~S_INTERNAL); ++ } ++ return SUCCESS; ++} ++#endif ++ + ZEND_INI_BEGIN() + ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting) + STD_ZEND_INI_BOOLEAN("zend.enable_gc", "1", ZEND_INI_ALL, OnUpdateGCEnabled, gc_enabled, zend_gc_globals, gc_globals) +diff -Nura php-5.3.9/Zend/zend.h suhosin-patch-5.3.9-0.9.10/Zend/zend.h +--- php-5.3.9/Zend/zend.h 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/Zend/zend.h 2012-01-11 19:29:07.000000000 +0100 +@@ -627,6 +627,9 @@ + extern int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap); + extern ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC); + extern ZEND_API char *(*zend_resolve_path)(const char *filename, int filename_len TSRMLS_DC); ++#if SUHOSIN_PATCH ++extern ZEND_API void (*zend_suhosin_log)(int loglevel, char *fmt, ...); ++#endif + + ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); + +@@ -774,6 +777,16 @@ + #define DEBUG_BACKTRACE_PROVIDE_OBJECT (1<<0) + #define DEBUG_BACKTRACE_IGNORE_ARGS (1<<1) + ++#if SUHOSIN_PATCH ++#include "suhosin_globals.h" ++#include "suhosin_patch.h" ++#include "php_syslog.h" ++ ++ZEND_API void zend_canary(void *buf, int len); ++ZEND_API char suhosin_get_config(int element); ++ ++#endif ++ + #endif /* ZEND_H */ + + /* +diff -Nura php-5.3.9/Zend/zend_alloc.c suhosin-patch-5.3.9-0.9.10/Zend/zend_alloc.c +--- php-5.3.9/Zend/zend_alloc.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/Zend/zend_alloc.c 2012-01-11 19:29:07.000000000 +0100 +@@ -32,6 +32,10 @@ + # include + #endif + ++#if SUHOSIN_PATCH ++#include "suhosin_patch.h" ++#endif ++ + #ifdef ZEND_WIN32 + # include + # include +@@ -59,6 +63,7 @@ + # define PTR_FMT "0x%0.8lx" + #endif + ++#ifndef SUHOSIN_MM_CLONE_FILE + #if ZEND_DEBUG + void zend_debug_alloc_output(char *format, ...) + { +@@ -76,6 +81,7 @@ + #endif + } + #endif ++#endif + + #if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX) + static void zend_mm_panic(const char *message) __attribute__ ((noreturn)); +@@ -134,6 +140,8 @@ + # endif + #endif + ++static zend_intptr_t SUHOSIN_POINTER_GUARD = 0; ++ + static zend_mm_storage* zend_mm_mem_dummy_init(void *params) + { + return malloc(sizeof(zend_mm_storage)); +@@ -332,13 +340,28 @@ + #define MEM_BLOCK_GUARD 0x2A8FCC84 + #define MEM_BLOCK_LEAK 0x6C5E8F2D + ++#if SUHOSIN_MM_WITH_CANARY_PROTECTION ++# define CANARY_SIZE sizeof(size_t) ++#else ++# define CANARY_SIZE 0 ++#endif ++ + /* mm block type */ + typedef struct _zend_mm_block_info { + #if ZEND_MM_COOKIES + size_t _cookie; + #endif +- size_t _size; +- size_t _prev; ++#if SUHOSIN_MM_WITH_CANARY_PROTECTION ++ size_t canary_1; ++#endif ++ size_t _size; ++ size_t _prev; ++#if SUHOSIN_PATCH ++ size_t size; ++#if SUHOSIN_MM_WITH_CANARY_PROTECTION ++ size_t canary_2; ++#endif ++#endif + } zend_mm_block_info; + + #if ZEND_DEBUG +@@ -412,7 +435,7 @@ + # define ZEND_MM_CACHE_STAT 0 + #endif + +-struct _zend_mm_heap { ++typedef struct _zend_mm_heap { + int use_zend_alloc; + void *(*_malloc)(size_t); + void (*_free)(void*); +@@ -447,6 +470,9 @@ + int miss; + } cache_stat[ZEND_MM_NUM_BUCKETS+1]; + #endif ++#if SUHOSIN_PATCH ++ size_t canary_1,canary_2,canary_3; ++#endif + }; + + #define ZEND_MM_SMALL_FREE_BUCKET(heap, index) \ +@@ -520,18 +546,31 @@ + /* optimized access */ + #define ZEND_MM_FREE_BLOCK_SIZE(b) (b)->info._size + ++#ifndef ZEND_MM_ALIGNMENT ++# define ZEND_MM_ALIGNMENT 8 ++# define ZEND_MM_ALIGNMENT_LOG2 3 ++#elif ZEND_MM_ALIGNMENT < 4 ++# undef ZEND_MM_ALIGNMENT ++# undef ZEND_MM_ALIGNMENT_LOG2 ++# define ZEND_MM_ALIGNMENT 4 ++# define ZEND_MM_ALIGNMENT_LOG2 2 ++#endif ++ ++#define ZEND_MM_ALIGNMENT_MASK ~(ZEND_MM_ALIGNMENT-1) ++ + /* Aligned header size */ ++#define ZEND_MM_ALIGNED_SIZE(size) ((size + ZEND_MM_ALIGNMENT - 1) & ZEND_MM_ALIGNMENT_MASK) + #define ZEND_MM_ALIGNED_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_block)) + #define ZEND_MM_ALIGNED_FREE_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_small_free_block)) +-#define ZEND_MM_MIN_ALLOC_BLOCK_SIZE ZEND_MM_ALIGNED_SIZE(ZEND_MM_ALIGNED_HEADER_SIZE + END_MAGIC_SIZE) ++#define ZEND_MM_MIN_ALLOC_BLOCK_SIZE ZEND_MM_ALIGNED_SIZE(ZEND_MM_ALIGNED_HEADER_SIZE + END_MAGIC_SIZE + CANARY_SIZE) + #define ZEND_MM_ALIGNED_MIN_HEADER_SIZE (ZEND_MM_MIN_ALLOC_BLOCK_SIZE>ZEND_MM_ALIGNED_FREE_HEADER_SIZE?ZEND_MM_MIN_ALLOC_BLOCK_SIZE:ZEND_MM_ALIGNED_FREE_HEADER_SIZE) + #define ZEND_MM_ALIGNED_SEGMENT_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_segment)) + +-#define ZEND_MM_MIN_SIZE ((ZEND_MM_ALIGNED_MIN_HEADER_SIZE>(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE))?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE-(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE)):0) ++#define ZEND_MM_MIN_SIZE ((ZEND_MM_ALIGNED_MIN_HEADER_SIZE>(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE))?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE-(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE)):0) + + #define ZEND_MM_MAX_SMALL_SIZE ((ZEND_MM_NUM_BUCKETS<>ZEND_MM_ALIGNMENT_LOG2)-(ZEND_MM_ALIGNED_MIN_HEADER_SIZE>>ZEND_MM_ALIGNMENT_LOG2)) + +@@ -593,6 +632,44 @@ + + #endif + ++#if SUHOSIN_MM_WITH_CANARY_PROTECTION ++ ++# define SUHOSIN_MM_CHECK_CANARIES(block, MFUNCTION) do { \ ++ char *p = SUHOSIN_MM_END_CANARY_PTR(block); size_t check; \ ++ if (((block)->info.canary_1 != heap->canary_1) || ((block)->info.canary_2 != heap->canary_2)) { \ ++ canary_mismatch: \ ++ zend_suhosin_log(S_MEMORY, "canary mismatch on " MFUNCTION " - heap overflow detected at %p", (block)); \ ++ if (SUHOSIN_CONFIG(SUHOSIN_MM_IGNORE_CANARY_VIOLATION) == 0) { _exit(1); } else { (block)->info.canary_1 = heap->canary_1; (block)->info.canary_2 = heap->canary_2; }\ ++ } \ ++ memcpy(&check, p, CANARY_SIZE); \ ++ if (check != heap->canary_3) { \ ++ zend_suhosin_log(S_MEMORY, "end canary mismatch on " MFUNCTION " - heap overflow detected at %p", (block)); \ ++ if (SUHOSIN_CONFIG(SUHOSIN_MM_IGNORE_CANARY_VIOLATION) == 0) { _exit(1); } else { memcpy(p, heap->canary_3, CANARY_SIZE); } \ ++ } \ ++ } while (0) ++ ++# define SUHOSIN_MM_SET_CANARIES(block) do { \ ++ (block)->info.canary_1 = heap->canary_1; \ ++ (block)->info.canary_2 = heap->canary_2; \ ++ } while (0) ++ ++# define SUHOSIN_MM_END_CANARY_PTR(block) \ ++ (char *)(((char*)(ZEND_MM_DATA_OF(block))) + ((zend_mm_block*)(block))->info.size + END_MAGIC_SIZE) ++ ++# define SUHOSIN_MM_SET_END_CANARY(block) do { \ ++ char *p = SUHOSIN_MM_END_CANARY_PTR(block); \ ++ memcpy(p, &heap->canary_3, CANARY_SIZE); \ ++ } while (0) ++ ++#else ++ ++# define SUHOSIN_MM_CHECK_CANARIES(block, MFUNCTION) ++# define SUHOSIN_MM_SET_CANARIES(block) ++# define SUHOSIN_MM_END_CANARY_PTR(block) ++# define SUHOSIN_MM_SET_END_CANARY(block) ++ ++#endif ++ + + #if ZEND_MM_HEAP_PROTECTION + +@@ -715,7 +792,7 @@ + #endif + } + +-static inline void zend_mm_add_to_rest_list(zend_mm_heap *heap, zend_mm_free_block *mm_block) ++static void zend_mm_add_to_rest_list(zend_mm_heap *heap, zend_mm_free_block *mm_block) + { + zend_mm_free_block *prev, *next; + +@@ -725,14 +802,14 @@ + mm_block->parent = NULL; + } + +- prev = heap->rest_buckets[0]; +- next = prev->next_free_block; +- mm_block->prev_free_block = prev; +- mm_block->next_free_block = next; +- prev->next_free_block = next->prev_free_block = mm_block; ++ prev = SUHOSIN_MANGLE_PTR(heap->rest_buckets[0]); ++ next = SUHOSIN_MANGLE_PTR(prev->next_free_block); ++ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev); ++ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next); ++ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block); + } + +-static inline void zend_mm_add_to_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block) ++static void zend_mm_add_to_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block) + { + size_t size; + size_t index; +@@ -749,7 +826,7 @@ + if (!*p) { + *p = mm_block; + mm_block->parent = p; +- mm_block->prev_free_block = mm_block->next_free_block = mm_block; ++ mm_block->prev_free_block = mm_block->next_free_block = SUHOSIN_MANGLE_PTR(mm_block); + heap->large_free_bitmap |= (ZEND_MM_LONG_CONST(1) << index); + } else { + size_t m; +@@ -762,15 +839,15 @@ + if (!*p) { + *p = mm_block; + mm_block->parent = p; +- mm_block->prev_free_block = mm_block->next_free_block = mm_block; ++ mm_block->prev_free_block = mm_block->next_free_block = SUHOSIN_MANGLE_PTR(mm_block); + break; + } + } else { +- zend_mm_free_block *next = prev->next_free_block; ++ zend_mm_free_block *next = SUHOSIN_MANGLE_PTR(prev->next_free_block); + +- prev->next_free_block = next->prev_free_block = mm_block; +- mm_block->next_free_block = next; +- mm_block->prev_free_block = prev; ++ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block); ++ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next); ++ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev); + mm_block->parent = NULL; + break; + } +@@ -782,27 +859,33 @@ + index = ZEND_MM_BUCKET_INDEX(size); + + prev = ZEND_MM_SMALL_FREE_BUCKET(heap, index); +- if (prev->prev_free_block == prev) { ++ if (SUHOSIN_MANGLE_PTR(prev->prev_free_block) == prev) { + heap->free_bitmap |= (ZEND_MM_LONG_CONST(1) << index); + } +- next = prev->next_free_block; ++ next = SUHOSIN_MANGLE_PTR(prev->next_free_block); + +- mm_block->prev_free_block = prev; +- mm_block->next_free_block = next; +- prev->next_free_block = next->prev_free_block = mm_block; ++ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev); ++ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next); ++ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block); + } + } + +-static inline void zend_mm_remove_from_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block) ++static void zend_mm_remove_from_free_list(zend_mm_heap *heap, zend_mm_free_block *mm_block) + { +- zend_mm_free_block *prev = mm_block->prev_free_block; +- zend_mm_free_block *next = mm_block->next_free_block; ++ zend_mm_free_block *prev = SUHOSIN_MANGLE_PTR(mm_block->prev_free_block); ++ zend_mm_free_block *next = SUHOSIN_MANGLE_PTR(mm_block->next_free_block); + + ZEND_MM_CHECK_MAGIC(mm_block, MEM_BLOCK_FREED); + + if (EXPECTED(prev == mm_block)) { + zend_mm_free_block **rp, **cp; + ++#if SUHOSIN_PATCH ++ if (next != mm_block) { ++ zend_suhosin_log(S_MEMORY, "zend_mm_heap corrupted at %p", mm_block); ++ _exit(1); ++ } ++#endif + #if ZEND_MM_SAFE_UNLINKING + if (UNEXPECTED(next != mm_block)) { + zend_mm_panic("zend_mm_heap corrupted"); +@@ -841,14 +924,21 @@ + } + } else { + ++#if SUHOSIN_PATCH ++ if (SUHOSIN_MANGLE_PTR(prev->next_free_block) != mm_block || SUHOSIN_MANGLE_PTR(next->prev_free_block) != mm_block) { ++ zend_suhosin_log(S_MEMORY, "zend_mm_head corrupted at %p", mm_block); ++ _exit(1); ++ } ++#endif ++ + #if ZEND_MM_SAFE_UNLINKING +- if (UNEXPECTED(prev->next_free_block != mm_block) || UNEXPECTED(next->prev_free_block != mm_block)) { ++ if (UNEXPECTED(SUHOSIN_MANGLE_PTR(prev->next_free_block) != mm_block) || UNEXPECTED(SUHOSIN_MANGLE_PTR(next->prev_free_block) != mm_block)) { + zend_mm_panic("zend_mm_heap corrupted"); + } + #endif + +- prev->next_free_block = next; +- next->prev_free_block = prev; ++ prev->next_free_block = SUHOSIN_MANGLE_PTR(next); ++ next->prev_free_block = SUHOSIN_MANGLE_PTR(prev); + + if (EXPECTED(ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block)))) { + if (EXPECTED(prev == next)) { +@@ -864,7 +954,7 @@ + } + } + +-static inline void zend_mm_init(zend_mm_heap *heap) ++static void zend_mm_init(zend_mm_heap *heap) + { + zend_mm_free_block* p; + int i; +@@ -882,12 +972,19 @@ + #endif + p = ZEND_MM_SMALL_FREE_BUCKET(heap, 0); + for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) { +- p->next_free_block = p; +- p->prev_free_block = p; ++ p->next_free_block = SUHOSIN_MANGLE_PTR(p); ++ p->prev_free_block = SUHOSIN_MANGLE_PTR(p); + p = (zend_mm_free_block*)((char*)p + sizeof(zend_mm_free_block*) * 2); + heap->large_free_buckets[i] = NULL; + } +- heap->rest_buckets[0] = heap->rest_buckets[1] = ZEND_MM_REST_BUCKET(heap); ++ heap->rest_buckets[0] = heap->rest_buckets[1] = SUHOSIN_MANGLE_PTR(ZEND_MM_REST_BUCKET(heap)); ++#if SUHOSIN_PATCH ++ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION)) { ++ zend_canary(&heap->canary_1, sizeof(heap->canary_1)); ++ zend_canary(&heap->canary_2, sizeof(heap->canary_2)); ++ zend_canary(&heap->canary_3, sizeof(heap->canary_3)); ++ } ++#endif + } + + static void zend_mm_del_segment(zend_mm_heap *heap, zend_mm_segment *segment) +@@ -908,12 +1005,13 @@ + int i; + + for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) { ++ /* NULL means NULL even MANGLED */ + if (heap->cache[i]) { +- zend_mm_free_block *mm_block = heap->cache[i]; ++ zend_mm_free_block *mm_block = SUHOSIN_MANGLE_PTR(heap->cache[i]); + + while (mm_block) { + size_t size = ZEND_MM_BLOCK_SIZE(mm_block); +- zend_mm_free_block *q = mm_block->prev_free_block; ++ zend_mm_free_block *q = SUHOSIN_MANGLE_PTR(mm_block->prev_free_block); + zend_mm_block *next_block = ZEND_MM_NEXT_BLOCK(mm_block); + + heap->cached -= size; +@@ -1009,14 +1107,20 @@ + /* }}} */ + #endif + ++ + /* Notes: + * - This function may alter the block_sizes values to match platform alignment + * - This function does *not* perform sanity checks on the arguments + */ +-ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params) ++#if SUHOSIN_MM_WITH_CANARY_PROTECTION ++zend_mm_heap *__zend_mm_startup_canary_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params) ++#else ++static zend_mm_heap *__zend_mm_startup_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params) ++#endif + { + zend_mm_storage *storage; + zend_mm_heap *heap; ++ zend_mm_free_block *tmp; + + #if 0 + int i; +@@ -1050,6 +1154,12 @@ + } + #endif + ++ /* get the pointer guardian and ensure low 3 bits are 1 */ ++ if (SUHOSIN_POINTER_GUARD == 0) { ++ zend_canary(&SUHOSIN_POINTER_GUARD, sizeof(SUHOSIN_POINTER_GUARD)); ++ SUHOSIN_POINTER_GUARD |= 7; ++ } ++ + if (zend_mm_low_bit(block_size) != zend_mm_high_bit(block_size)) { + fprintf(stderr, "'block_size' must be a power of two\n"); + /* See http://support.microsoft.com/kb/190351 */ +@@ -1077,6 +1187,7 @@ + #endif + exit(255); + } ++ + heap->storage = storage; + heap->block_size = block_size; + heap->compact_size = 0; +@@ -1097,12 +1208,12 @@ + heap->reserve = NULL; + heap->reserve_size = reserve_size; + if (reserve_size > 0) { +- heap->reserve = _zend_mm_alloc_int(heap, reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC); ++ heap->reserve = _zend_mm_alloc(heap, reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC); + } + if (internal) { + int i; + zend_mm_free_block *p, *q, *orig; +- zend_mm_heap *mm_heap = _zend_mm_alloc_int(heap, sizeof(zend_mm_heap) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC); ++ zend_mm_heap *mm_heap = _zend_mm_alloc(heap, sizeof(zend_mm_heap) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC); + + *mm_heap = *heap; + +@@ -1110,22 +1221,22 @@ + orig = ZEND_MM_SMALL_FREE_BUCKET(heap, 0); + for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) { + q = p; +- while (q->prev_free_block != orig) { +- q = q->prev_free_block; ++ while (SUHOSIN_MANGLE_PTR(q->prev_free_block) != orig) { ++ q = SUHOSIN_MANGLE_PTR(q->prev_free_block); + } +- q->prev_free_block = p; ++ q->prev_free_block = SUHOSIN_MANGLE_PTR(p); + q = p; +- while (q->next_free_block != orig) { +- q = q->next_free_block; ++ while (SUHOSIN_MANGLE_PTR(q->next_free_block) != orig) { ++ q = SUHOSIN_MANGLE_PTR(q->next_free_block); + } +- q->next_free_block = p; ++ q->next_free_block = SUHOSIN_MANGLE_PTR(p); + p = (zend_mm_free_block*)((char*)p + sizeof(zend_mm_free_block*) * 2); + orig = (zend_mm_free_block*)((char*)orig + sizeof(zend_mm_free_block*) * 2); + if (mm_heap->large_free_buckets[i]) { + mm_heap->large_free_buckets[i]->parent = &mm_heap->large_free_buckets[i]; + } + } +- mm_heap->rest_buckets[0] = mm_heap->rest_buckets[1] = ZEND_MM_REST_BUCKET(mm_heap); ++ mm_heap->rest_buckets[0] = mm_heap->rest_buckets[1] = SUHOSIN_MANGLE_PTR(ZEND_MM_REST_BUCKET(mm_heap)); + + free(heap); + heap = mm_heap; +@@ -1133,7 +1244,11 @@ + return heap; + } + +-ZEND_API zend_mm_heap *zend_mm_startup(void) ++#if SUHOSIN_MM_WITH_CANARY_PROTECTION ++zend_mm_heap *__zend_mm_startup_canary(void) ++#else ++static zend_mm_heap *__zend_mm_startup(void) ++#endif + { + int i; + size_t seg_size; +@@ -1203,6 +1318,27 @@ + return heap; + } + ++#ifndef SUHOSIN_MM_CLONE_FILE ++zend_mm_heap_canary *__zend_mm_startup_canary_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params); ++zend_mm_heap_canary *__zend_mm_startup_canary(void); ++ ++ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params) ++{ ++ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION)) { ++ return (zend_mm_heap *)__zend_mm_startup_canary_ex(handlers, block_size, reserve_size, internal, params); ++ } ++ return __zend_mm_startup_ex(handlers, block_size, reserve_size, internal, params); ++} ++ZEND_API zend_mm_heap *zend_mm_startup(void) ++{ ++ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION)) { ++ return (zend_mm_heap *)__zend_mm_startup_canary(); ++ } ++ return __zend_mm_startup(); ++} ++ ++#endif ++ + #if ZEND_DEBUG + static long zend_mm_find_leaks(zend_mm_segment *segment, zend_mm_block *b) + { +@@ -1571,7 +1707,11 @@ + } + #endif + +-ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC) ++#if SUHOSIN_MM_WITH_CANARY_PROTECTION ++void __zend_mm_shutdown_canary(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC) ++#else ++static void __zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC) ++#endif + { + zend_mm_storage *storage; + zend_mm_segment *segment; +@@ -1581,7 +1721,7 @@ + if (heap->reserve) { + #if ZEND_DEBUG + if (!silent) { +- _zend_mm_free_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC); ++ _zend_mm_free(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC); + } + #endif + heap->reserve = NULL; +@@ -1664,12 +1804,23 @@ + heap->size = 0; + heap->peak = 0; + if (heap->reserve_size) { +- heap->reserve = _zend_mm_alloc_int(heap, heap->reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC); ++ heap->reserve = _zend_mm_alloc(heap, heap->reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC); + } + heap->overflow = 0; + } + } + ++#ifndef SUHOSIN_MM_CLONE_FILE ++ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC) ++{ ++ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION)) { ++ __zend_mm_shutdown_canary(heap, full_shutdown, silent TSRMLS_CC); ++ return; ++ } ++ __zend_mm_shutdown(heap, full_shutdown, silent TSRMLS_CC); ++} ++#endif ++ + static void zend_mm_safe_error(zend_mm_heap *heap, + const char *format, + size_t limit, +@@ -1680,7 +1831,11 @@ + size_t size) + { + if (heap->reserve) { ++#if SUHOSIN_MM_WITH_CANARY_PROTECTION ++ _zend_mm_free_canary_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC); ++#else + _zend_mm_free_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC); ++#endif + heap->reserve = NULL; + } + if (heap->overflow == 0) { +@@ -1755,7 +1910,7 @@ + p = heap->large_free_buckets[index]; + for (m = true_size << (ZEND_MM_NUM_BUCKETS - index); ; m <<= 1) { + if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) { +- return p->next_free_block; ++ return SUHOSIN_MANGLE_PTR(p->next_free_block); + } else if (ZEND_MM_FREE_BLOCK_SIZE(p) >= true_size && + ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) { + best_size = ZEND_MM_FREE_BLOCK_SIZE(p); +@@ -1779,7 +1934,7 @@ + + for (p = rst; p; p = p->child[p->child[0] != NULL]) { + if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) { +- return p->next_free_block; ++ return SUHOSIN_MANGLE_PTR(p->next_free_block); + } else if (ZEND_MM_FREE_BLOCK_SIZE(p) > true_size && + ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) { + best_size = ZEND_MM_FREE_BLOCK_SIZE(p); +@@ -1788,7 +1943,7 @@ + } + + if (best_fit) { +- return best_fit->next_free_block; ++ return SUHOSIN_MANGLE_PTR(best_fit->next_free_block); + } + bitmap = bitmap >> 1; + if (!bitmap) { +@@ -1804,9 +1959,12 @@ + best_fit = p; + } + } +- return best_fit->next_free_block; ++ return SUHOSIN_MANGLE_PTR(best_fit->next_free_block); + } + ++#if SUHOSIN_PATCH ++void *_zend_mm_alloc_canary_int(zend_mm_heap_canary *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); ++#endif + static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) + { + zend_mm_free_block *best_fit; +@@ -1816,7 +1974,7 @@ + size_t segment_size; + zend_mm_segment *segment; + int keep_rest = 0; +- ++ + if (EXPECTED(ZEND_MM_SMALL_SIZE(true_size))) { + size_t index = ZEND_MM_BUCKET_INDEX(true_size); + size_t bitmap; +@@ -1831,9 +1989,14 @@ + heap->cache_stat[index].count--; + heap->cache_stat[index].hit++; + #endif +- best_fit = heap->cache[index]; ++ best_fit = SUHOSIN_MANGLE_PTR(heap->cache[index]); + heap->cache[index] = best_fit->prev_free_block; + heap->cached -= true_size; ++#if SUHOSIN_PATCH ++ SUHOSIN_MM_SET_CANARIES(best_fit); ++ ((zend_mm_block*)best_fit)->info.size = size; ++ SUHOSIN_MM_SET_END_CANARY(best_fit); ++#endif + ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED); + ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0); + return ZEND_MM_DATA_OF(best_fit); +@@ -1847,7 +2010,7 @@ + if (bitmap) { + /* Found some "small" free block that can be used */ + index += zend_mm_low_bit(bitmap); +- best_fit = heap->free_buckets[index*2]; ++ best_fit = SUHOSIN_MANGLE_PTR(heap->free_buckets[index*2]); + #if ZEND_MM_CACHE_STAT + heap->cache_stat[ZEND_MM_NUM_BUCKETS].hit++; + #endif +@@ -1862,7 +2025,7 @@ + best_fit = zend_mm_search_large_block(heap, true_size); + + if (!best_fit && heap->real_size >= heap->limit - heap->block_size) { +- zend_mm_free_block *p = heap->rest_buckets[0]; ++ zend_mm_free_block *p = SUHOSIN_MANGLE_PTR(heap->rest_buckets[0]); + size_t best_size = -1; + + while (p != ZEND_MM_REST_BUCKET(heap)) { +@@ -1874,7 +2037,7 @@ + best_size = ZEND_MM_FREE_BLOCK_SIZE(p); + best_fit = p; + } +- p = p->prev_free_block; ++ p = SUHOSIN_MANGLE_PTR(p->prev_free_block); + } + } + +@@ -1973,13 +2136,19 @@ + + ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 1); + ++#if SUHOSIN_PATCH ++ SUHOSIN_MM_SET_CANARIES(best_fit); ++ ((zend_mm_block*)best_fit)->info.size = size; ++ SUHOSIN_MM_SET_END_CANARY(best_fit); ++#endif ++ + heap->size += true_size; + if (heap->peak < heap->size) { + heap->peak = heap->size; + } + + HANDLE_UNBLOCK_INTERRUPTIONS(); +- ++ + return ZEND_MM_DATA_OF(best_fit); + } + +@@ -1996,19 +2165,26 @@ + + mm_block = ZEND_MM_HEADER_OF(p); + size = ZEND_MM_BLOCK_SIZE(mm_block); ++#if SUHOSIN_PATCH ++ SUHOSIN_MM_CHECK_CANARIES(mm_block, "efree()"); ++#endif + ZEND_MM_CHECK_PROTECTION(mm_block); + + #if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION + memset(ZEND_MM_DATA_OF(mm_block), 0x5a, mm_block->debug.size); + #endif +- ++#if SUHOSIN_PATCH ++ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_DESTROY_FREE_MEMORY))) { ++ memset(ZEND_MM_DATA_OF(mm_block), 0x5a, mm_block->info.size); ++ } ++#endif + #if ZEND_MM_CACHE + if (EXPECTED(ZEND_MM_SMALL_SIZE(size)) && EXPECTED(heap->cached < ZEND_MM_CACHE_SIZE)) { + size_t index = ZEND_MM_BUCKET_INDEX(size); + zend_mm_free_block **cache = &heap->cache[index]; + + ((zend_mm_free_block*)mm_block)->prev_free_block = *cache; +- *cache = (zend_mm_free_block*)mm_block; ++ *cache = (zend_mm_free_block*)SUHOSIN_MANGLE_PTR(mm_block); + heap->cached += size; + ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED); + #if ZEND_MM_CACHE_STAT +@@ -2044,6 +2220,9 @@ + HANDLE_UNBLOCK_INTERRUPTIONS(); + } + ++#if SUHOSIN_PATCH ++void *_zend_mm_realloc_canary_int(zend_mm_heap_canary *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); ++#endif + static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) + { + zend_mm_block *mm_block = ZEND_MM_HEADER_OF(p); +@@ -2053,11 +2232,18 @@ + void *ptr; + + if (UNEXPECTED(!p) || !ZEND_MM_VALID_PTR(p)) { ++#ifdef SUHOSIN_MM_WITH_CANARY_PROTECTION ++ return _zend_mm_alloc_canary_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#else + return _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#endif + } + mm_block = ZEND_MM_HEADER_OF(p); + true_size = ZEND_MM_TRUE_SIZE(size); + orig_size = ZEND_MM_BLOCK_SIZE(mm_block); ++#if SUHOSIN_PATCH ++ SUHOSIN_MM_CHECK_CANARIES(mm_block, "erealloc()"); ++#endif + ZEND_MM_CHECK_PROTECTION(mm_block); + + if (UNEXPECTED(true_size < size)) { +@@ -2089,6 +2275,11 @@ + HANDLE_UNBLOCK_INTERRUPTIONS(); + } + ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0); ++#if SUHOSIN_PATCH ++ SUHOSIN_MM_SET_CANARIES(mm_block); ++ ((zend_mm_block*)mm_block)->info.size = size; ++ SUHOSIN_MM_SET_END_CANARY(mm_block); ++#endif + return p; + } + +@@ -2104,17 +2295,22 @@ + heap->cache_stat[index].count--; + heap->cache_stat[index].hit++; + #endif +- best_fit = heap->cache[index]; ++ best_fit = SUHOSIN_MANGLE_PTR(heap->cache[index]); + heap->cache[index] = best_fit->prev_free_block; + ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED); +- ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0); +- ++ ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0); ++#if SUHOSIN_PATCH ++ SUHOSIN_MM_SET_CANARIES(best_fit); ++ ((zend_mm_block*)best_fit)->info.size = size; ++ SUHOSIN_MM_SET_END_CANARY(best_fit); ++#endif ++ + ptr = ZEND_MM_DATA_OF(best_fit); + + #if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION + memcpy(ptr, p, mm_block->debug.size); + #else +- memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE); ++ memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE - CANARY_SIZE); + #endif + + heap->cached -= true_size - orig_size; +@@ -2123,14 +2319,13 @@ + cache = &heap->cache[index]; + + ((zend_mm_free_block*)mm_block)->prev_free_block = *cache; +- *cache = (zend_mm_free_block*)mm_block; ++ *cache = (zend_mm_free_block*)SUHOSIN_MANGLE_PTR(mm_block); + ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED); + #if ZEND_MM_CACHE_STAT + if (++heap->cache_stat[index].count > heap->cache_stat[index].max_count) { + heap->cache_stat[index].max_count = heap->cache_stat[index].count; + } + #endif +- + return ptr; + } + } +@@ -2173,6 +2368,11 @@ + heap->peak = heap->size; + } + HANDLE_UNBLOCK_INTERRUPTIONS(); ++#if SUHOSIN_PATCH ++ SUHOSIN_MM_SET_CANARIES(mm_block); ++ ((zend_mm_block*)mm_block)->info.size = size; ++ SUHOSIN_MM_SET_END_CANARY(mm_block); ++#endif + return p; + } else if (ZEND_MM_IS_FIRST_BLOCK(mm_block) && + ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(next_block, ZEND_MM_FREE_BLOCK_SIZE(next_block)))) { +@@ -2275,38 +2475,74 @@ + } + + HANDLE_UNBLOCK_INTERRUPTIONS(); ++#if SUHOSIN_PATCH ++ SUHOSIN_MM_SET_CANARIES(mm_block); ++ ((zend_mm_block*)mm_block)->info.size = size; ++ SUHOSIN_MM_SET_END_CANARY(mm_block); ++#endif + return ZEND_MM_DATA_OF(mm_block); + } + ++#ifdef SUHOSIN_MM_WITH_CANARY_PROTECTION ++ ptr = _zend_mm_alloc_canary_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#else + ptr = _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#endif + #if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION + memcpy(ptr, p, mm_block->debug.size); + #else +- memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE); ++ memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE - CANARY_SIZE); + #endif ++#ifdef SUHOSIN_MM_WITH_CANARY_PROTECTION ++ _zend_mm_free_canary_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#else + _zend_mm_free_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#endif + return ptr; + } + ++#ifndef SUHOSIN_MM_CLONE_FILE + ZEND_API void *_zend_mm_alloc(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) + { +- return _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#if SUHOSIN_PATCH ++ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0)) ++#endif ++ return _zend_mm_alloc_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#if SUHOSIN_PATCH ++ return _zend_mm_alloc_canary_int((zend_mm_heap_canary *)heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#endif + } + + ZEND_API void _zend_mm_free(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) + { +- _zend_mm_free_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#if SUHOSIN_PATCH ++ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0)) ++#endif ++ { _zend_mm_free_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); return; } ++#if SUHOSIN_PATCH ++ _zend_mm_free_canary_int((zend_mm_heap_canary *)heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#endif + } + + ZEND_API void *_zend_mm_realloc(zend_mm_heap *heap, void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) + { +- return _zend_mm_realloc_int(heap, ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#if SUHOSIN_PATCH ++ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0)) ++#endif ++ return _zend_mm_realloc_int(heap, ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#if SUHOSIN_PATCH ++ return _zend_mm_realloc_canary_int((zend_mm_heap_canary *)heap, ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#endif + } + + ZEND_API size_t _zend_mm_block_size(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) + { + zend_mm_block *mm_block; + ++ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) != 0) { ++ return _zend_mm_block_size_canary((zend_mm_heap_canary *)heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++ } ++ + if (!ZEND_MM_VALID_PTR(p)) { + return 0; + } +@@ -2318,6 +2554,24 @@ + return ZEND_MM_BLOCK_SIZE(mm_block); + #endif + } ++#else ++ZEND_API size_t _zend_mm_block_size_canary(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ++{ ++ zend_mm_block *mm_block; ++ ++ if (!ZEND_MM_VALID_PTR(p)) { ++ return 0; ++ } ++ mm_block = ZEND_MM_HEADER_OF(p); ++ ZEND_MM_CHECK_PROTECTION(mm_block); ++#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION ++ return mm_block->debug.size; ++#else ++ return ZEND_MM_BLOCK_SIZE(mm_block); ++#endif ++} ++ ++#endif + + /**********************/ + /* Allocation Manager */ +@@ -2335,6 +2589,7 @@ + static zend_alloc_globals alloc_globals; + #endif + ++#ifndef SUHOSIN_MM_CLONE_FILE + ZEND_API int is_zend_mm(TSRMLS_D) + { + return AG(mm_heap)->use_zend_alloc; +@@ -2347,7 +2602,13 @@ + if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) { + return AG(mm_heap)->_malloc(size); + } ++#if SUHOSIN_PATCH ++ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0)) ++#endif + return _zend_mm_alloc_int(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#if SUHOSIN_PATCH ++ return _zend_mm_alloc_canary_int((zend_mm_heap_canary *)AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#endif + } + + ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +@@ -2358,7 +2619,13 @@ + AG(mm_heap)->_free(ptr); + return; + } +- _zend_mm_free_int(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#if SUHOSIN_PATCH ++ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0)) ++#endif ++ { _zend_mm_free_int(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); return; } ++#if SUHOSIN_PATCH ++ _zend_mm_free_canary_int((zend_mm_heap_canary *)AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#endif + } + + ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +@@ -2368,7 +2635,13 @@ + if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) { + return AG(mm_heap)->_realloc(ptr, size); + } ++#if SUHOSIN_PATCH ++ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0)) ++#endif + return _zend_mm_realloc_int(AG(mm_heap), ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#if SUHOSIN_PATCH ++ return _zend_mm_realloc_canary_int((zend_mm_heap_canary *)AG(mm_heap), ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#endif + } + + ZEND_API size_t _zend_mem_block_size(void *ptr TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +@@ -2376,8 +2649,15 @@ + if (UNEXPECTED(!AG(mm_heap)->use_zend_alloc)) { + return 0; + } +- return _zend_mm_block_size(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#if SUHOSIN_PATCH ++ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION) == 0)) ++#endif ++ return _zend_mm_block_size(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#if SUHOSIN_PATCH ++ return _zend_mm_block_size_canary((zend_mm_heap_canary *)AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#endif + } ++#endif + + #if defined(__GNUC__) && defined(i386) + +@@ -2448,7 +2728,7 @@ + } + #endif + +- ++#ifndef SUHOSIN_MM_CLONE_FILE + ZEND_API void *_safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) + { + return emalloc_rel(safe_address(nmemb, size, offset)); +@@ -2561,6 +2841,7 @@ + { + zend_mm_shutdown(AG(mm_heap), full_shutdown, silent TSRMLS_CC); + } ++#endif + + static void alloc_globals_ctor(zend_alloc_globals *alloc_globals TSRMLS_DC) + { +@@ -2585,6 +2866,7 @@ + } + #endif + ++#ifndef SUHOSIN_MM_CLONE_FILE + ZEND_API void start_memory_manager(TSRMLS_D) + { + #ifdef ZTS +@@ -2649,6 +2931,7 @@ + zend_debug_alloc_output("------------------------------------------------\n"); + } + #endif ++#endif + + /* + * Local variables: +diff -Nura php-5.3.9/Zend/zend_alloc.h suhosin-patch-5.3.9-0.9.10/Zend/zend_alloc.h +--- php-5.3.9/Zend/zend_alloc.h 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/Zend/zend_alloc.h 2012-01-11 19:29:07.000000000 +0100 +@@ -203,6 +203,8 @@ + + /* Heap functions */ + typedef struct _zend_mm_heap zend_mm_heap; ++typedef struct _zend_mm_heap_canary zend_mm_heap_canary; ++ + + ZEND_API zend_mm_heap *zend_mm_startup(void); + ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, int full_shutdown, int silent TSRMLS_DC); +diff -Nura php-5.3.9/Zend/zend_alloc_canary.c suhosin-patch-5.3.9-0.9.10/Zend/zend_alloc_canary.c +--- php-5.3.9/Zend/zend_alloc_canary.c 1970-01-01 01:00:00.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/Zend/zend_alloc_canary.c 2012-01-11 19:30:47.000000000 +0100 +@@ -0,0 +1,2509 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | Suhosin-Patch for PHP | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 2004-2011 Stefan Esser | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.txt. | ++ | If you did not receive a copy of the PHP license and are unable to | ++ | obtain it through the world-wide-web, please send a note to | ++ | license@php.net so we can mail you a copy immediately. | ++ +----------------------------------------------------------------------+ ++ | Author: Stefan Esser | ++ +----------------------------------------------------------------------+ ++ */ ++/* $Id: zend_alloc_canary.c, $ */ ++ ++#include "zend.h" ++#include "zend_alloc.h" ++#include "zend_globals.h" ++#include "zend_operators.h" ++ ++#ifdef HAVE_SIGNAL_H ++# include ++#endif ++#ifdef HAVE_UNISTD_H ++# include ++#endif ++ ++#if SUHOSIN_PATCH ++#include "suhosin_patch.h" ++#endif ++ ++#ifdef ZEND_WIN32 ++# include ++# include ++#endif ++ ++#ifndef ZEND_MM_HEAP_PROTECTION ++# define ZEND_MM_HEAP_PROTECTION ZEND_DEBUG ++#endif ++ ++#ifndef ZEND_MM_SAFE_UNLINKING ++# define ZEND_MM_SAFE_UNLINKING 1 ++#endif ++ ++#ifndef ZEND_MM_COOKIES ++# define ZEND_MM_COOKIES ZEND_DEBUG ++#endif ++ ++#ifdef _WIN64 ++# define PTR_FMT "0x%0.16I64x" ++/* ++#elif sizeof(long) == 8 ++# define PTR_FMT "0x%0.16lx" ++*/ ++#else ++# define PTR_FMT "0x%0.8lx" ++#endif ++ ++#define SUHOSIN_MM_WITH_CANARY_PROTECTION 1 ++ ++#if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX) ++static void zend_mm_panic(const char *message) __attribute__ ((noreturn)); ++#endif ++ ++static void zend_mm_panic(const char *message) ++{ ++ fprintf(stderr, "%s\n", message); ++/* See http://support.microsoft.com/kb/190351 */ ++#ifdef PHP_WIN32 ++ fflush(stderr); ++#endif ++#if ZEND_DEBUG && defined(HAVE_KILL) && defined(HAVE_GETPID) ++ kill(getpid(), SIGSEGV); ++#endif ++ exit(1); ++} ++ ++/*******************/ ++/* Storage Manager */ ++/*******************/ ++ ++#ifdef ZEND_WIN32 ++# define HAVE_MEM_WIN32 /* use VirtualAlloc() to allocate memory */ ++#endif ++#define HAVE_MEM_MALLOC /* use malloc() to allocate segments */ ++ ++#include ++#include ++#if HAVE_LIMITS_H ++#include ++#endif ++#include ++#include ++ ++#if defined(HAVE_MEM_MMAP_ANON) || defined(HAVE_MEM_MMAP_ZERO) ++# ifdef HAVE_MREMAP ++# ifndef _GNU_SOURCE ++# define _GNU_SOURCE ++# endif ++# ifndef __USE_GNU ++# define __USE_GNU ++# endif ++# endif ++# include ++# ifndef MAP_ANON ++# ifdef MAP_ANONYMOUS ++# define MAP_ANON MAP_ANONYMOUS ++# endif ++# endif ++# ifndef MREMAP_MAYMOVE ++# define MREMAP_MAYMOVE 0 ++# endif ++# ifndef MAP_FAILED ++# define MAP_FAILED ((void*)-1) ++# endif ++#endif ++ ++static zend_intptr_t SUHOSIN_POINTER_GUARD = 0; ++ ++static zend_mm_storage* zend_mm_mem_dummy_init(void *params) ++{ ++ return malloc(sizeof(zend_mm_storage)); ++} ++ ++static void zend_mm_mem_dummy_dtor(zend_mm_storage *storage) ++{ ++ free(storage); ++} ++ ++static void zend_mm_mem_dummy_compact(zend_mm_storage *storage) ++{ ++} ++ ++#if defined(HAVE_MEM_MMAP_ANON) || defined(HAVE_MEM_MMAP_ZERO) ++ ++static zend_mm_segment* zend_mm_mem_mmap_realloc(zend_mm_storage *storage, zend_mm_segment* segment, size_t size) ++{ ++ zend_mm_segment *ret; ++#ifdef HAVE_MREMAP ++#if defined(__NetBSD__) ++ /* NetBSD 5 supports mremap but takes an extra newp argument */ ++ ret = (zend_mm_segment*)mremap(segment, segment->size, segment, size, MREMAP_MAYMOVE); ++#else ++ ret = (zend_mm_segment*)mremap(segment, segment->size, size, MREMAP_MAYMOVE); ++#endif ++ if (ret == MAP_FAILED) { ++#endif ++ ret = storage->handlers->_alloc(storage, size); ++ if (ret) { ++ memcpy(ret, segment, size > segment->size ? segment->size : size); ++ storage->handlers->_free(storage, segment); ++ } ++#ifdef HAVE_MREMAP ++ } ++#endif ++ return ret; ++} ++ ++static void zend_mm_mem_mmap_free(zend_mm_storage *storage, zend_mm_segment* segment) ++{ ++ munmap((void*)segment, segment->size); ++} ++ ++#endif ++ ++#ifdef HAVE_MEM_MMAP_ANON ++ ++static zend_mm_segment* zend_mm_mem_mmap_anon_alloc(zend_mm_storage *storage, size_t size) ++{ ++ zend_mm_segment *ret = (zend_mm_segment*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); ++ if (ret == MAP_FAILED) { ++ ret = NULL; ++ } ++ return ret; ++} ++ ++# define ZEND_MM_MEM_MMAP_ANON_DSC {"mmap_anon", zend_mm_mem_dummy_init, zend_mm_mem_dummy_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_mmap_anon_alloc, zend_mm_mem_mmap_realloc, zend_mm_mem_mmap_free} ++ ++#endif ++ ++#ifdef HAVE_MEM_MMAP_ZERO ++ ++static int zend_mm_dev_zero_fd = -1; ++ ++static zend_mm_storage* zend_mm_mem_mmap_zero_init(void *params) ++{ ++ if (zend_mm_dev_zero_fd != -1) { ++ zend_mm_dev_zero_fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR); ++ } ++ if (zend_mm_dev_zero_fd >= 0) { ++ return malloc(sizeof(zend_mm_storage)); ++ } else { ++ return NULL; ++ } ++} ++ ++static void zend_mm_mem_mmap_zero_dtor(zend_mm_storage *storage) ++{ ++ close(zend_mm_dev_zero_fd); ++ free(storage); ++} ++ ++static zend_mm_segment* zend_mm_mem_mmap_zero_alloc(zend_mm_storage *storage, size_t size) ++{ ++ zend_mm_segment *ret = (zend_mm_segment*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, zend_mm_dev_zero_fd, 0); ++ if (ret == MAP_FAILED) { ++ ret = NULL; ++ } ++ return ret; ++} ++ ++# define ZEND_MM_MEM_MMAP_ZERO_DSC {"mmap_zero", zend_mm_mem_mmap_zero_init, zend_mm_mem_mmap_zero_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_mmap_zero_alloc, zend_mm_mem_mmap_realloc, zend_mm_mem_mmap_free} ++ ++#endif ++ ++#ifdef HAVE_MEM_WIN32 ++ ++static zend_mm_storage* zend_mm_mem_win32_init(void *params) ++{ ++ HANDLE heap = HeapCreate(HEAP_NO_SERIALIZE, 0, 0); ++ zend_mm_storage* storage; ++ ++ if (heap == NULL) { ++ return NULL; ++ } ++ storage = (zend_mm_storage*)malloc(sizeof(zend_mm_storage)); ++ if (storage == NULL) { ++ HeapDestroy(heap); ++ return NULL; ++ } ++ storage->data = (void*) heap; ++ return storage; ++} ++ ++static void zend_mm_mem_win32_dtor(zend_mm_storage *storage) ++{ ++ HeapDestroy((HANDLE)storage->data); ++ free(storage); ++} ++ ++static void zend_mm_mem_win32_compact(zend_mm_storage *storage) ++{ ++ HeapDestroy((HANDLE)storage->data); ++ storage->data = (void*)HeapCreate(HEAP_NO_SERIALIZE, 0, 0); ++} ++ ++static zend_mm_segment* zend_mm_mem_win32_alloc(zend_mm_storage *storage, size_t size) ++{ ++ return (zend_mm_segment*) HeapAlloc((HANDLE)storage->data, HEAP_NO_SERIALIZE, size); ++} ++ ++static void zend_mm_mem_win32_free(zend_mm_storage *storage, zend_mm_segment* segment) ++{ ++ HeapFree((HANDLE)storage->data, HEAP_NO_SERIALIZE, segment); ++} ++ ++static zend_mm_segment* zend_mm_mem_win32_realloc(zend_mm_storage *storage, zend_mm_segment* segment, size_t size) ++{ ++ return (zend_mm_segment*) HeapReAlloc((HANDLE)storage->data, HEAP_NO_SERIALIZE, segment, size); ++} ++ ++# define ZEND_MM_MEM_WIN32_DSC {"win32", zend_mm_mem_win32_init, zend_mm_mem_win32_dtor, zend_mm_mem_win32_compact, zend_mm_mem_win32_alloc, zend_mm_mem_win32_realloc, zend_mm_mem_win32_free} ++ ++#endif ++ ++#ifdef HAVE_MEM_MALLOC ++ ++static zend_mm_segment* zend_mm_mem_malloc_alloc(zend_mm_storage *storage, size_t size) ++{ ++ return (zend_mm_segment*)malloc(size); ++} ++ ++static zend_mm_segment* zend_mm_mem_malloc_realloc(zend_mm_storage *storage, zend_mm_segment *ptr, size_t size) ++{ ++ return (zend_mm_segment*)realloc(ptr, size); ++} ++ ++static void zend_mm_mem_malloc_free(zend_mm_storage *storage, zend_mm_segment *ptr) ++{ ++ free(ptr); ++} ++ ++# define ZEND_MM_MEM_MALLOC_DSC {"malloc", zend_mm_mem_dummy_init, zend_mm_mem_dummy_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_malloc_alloc, zend_mm_mem_malloc_realloc, zend_mm_mem_malloc_free} ++ ++#endif ++ ++static const zend_mm_mem_handlers mem_handlers[] = { ++#ifdef HAVE_MEM_WIN32 ++ ZEND_MM_MEM_WIN32_DSC, ++#endif ++#ifdef HAVE_MEM_MALLOC ++ ZEND_MM_MEM_MALLOC_DSC, ++#endif ++#ifdef HAVE_MEM_MMAP_ANON ++ ZEND_MM_MEM_MMAP_ANON_DSC, ++#endif ++#ifdef HAVE_MEM_MMAP_ZERO ++ ZEND_MM_MEM_MMAP_ZERO_DSC, ++#endif ++ {NULL, NULL, NULL, NULL, NULL, NULL} ++}; ++ ++# define ZEND_MM_STORAGE_DTOR() heap->storage->handlers->dtor(heap->storage) ++# define ZEND_MM_STORAGE_ALLOC(size) heap->storage->handlers->_alloc(heap->storage, size) ++# define ZEND_MM_STORAGE_REALLOC(ptr, size) heap->storage->handlers->_realloc(heap->storage, ptr, size) ++# define ZEND_MM_STORAGE_FREE(ptr) heap->storage->handlers->_free(heap->storage, ptr) ++ ++/****************/ ++/* Heap Manager */ ++/****************/ ++ ++#define MEM_BLOCK_VALID 0x7312F8DC ++#define MEM_BLOCK_FREED 0x99954317 ++#define MEM_BLOCK_CACHED 0xFB8277DC ++#define MEM_BLOCK_GUARD 0x2A8FCC84 ++#define MEM_BLOCK_LEAK 0x6C5E8F2D ++ ++#if SUHOSIN_MM_WITH_CANARY_PROTECTION ++# define CANARY_SIZE sizeof(size_t) ++#else ++# define CANARY_SIZE 0 ++#endif ++ ++/* mm block type */ ++typedef struct _zend_mm_block_info_canary { ++#if ZEND_MM_COOKIES ++ size_t _cookie; ++#endif ++#if SUHOSIN_MM_WITH_CANARY_PROTECTION ++ size_t canary_1; ++#endif ++ size_t _size; ++ size_t _prev; ++#if SUHOSIN_PATCH ++ size_t size; ++#if SUHOSIN_MM_WITH_CANARY_PROTECTION ++ size_t canary_2; ++#endif ++#endif ++} zend_mm_block_info_canary; ++ ++#if ZEND_DEBUG ++ ++typedef struct _zend_mm_debug_info_canary { ++ char *filename; ++ uint lineno; ++ char *orig_filename; ++ uint orig_lineno; ++ size_t size; ++#if ZEND_MM_HEAP_PROTECTION ++ unsigned int start_magic; ++#endif ++} zend_mm_debug_info_canary; ++ ++#elif ZEND_MM_HEAP_PROTECTION ++ ++typedef struct _zend_mm_debug_info_canary { ++ size_t size; ++ unsigned int start_magic; ++} zend_mm_debug_info_canary; ++ ++#endif ++ ++typedef struct _zend_mm_block_canary { ++ zend_mm_block_info_canary info; ++#if ZEND_DEBUG ++ unsigned int magic; ++# ifdef ZTS ++ THREAD_T thread_id; ++# endif ++ zend_mm_debug_info_canary debug; ++#elif ZEND_MM_HEAP_PROTECTION ++ zend_mm_debug_info_canary debug; ++#endif ++} zend_mm_block_canary; ++ ++typedef struct _zend_mm_small_free_block_canary { ++ zend_mm_block_info_canary info; ++#if ZEND_DEBUG ++ unsigned int magic; ++# ifdef ZTS ++ THREAD_T thread_id; ++# endif ++#endif ++ struct _zend_mm_free_block_canary *prev_free_block; ++ struct _zend_mm_free_block_canary *next_free_block; ++} zend_mm_small_free_block_canary; ++ ++typedef struct _zend_mm_free_block_canary { ++ zend_mm_block_info_canary info; ++#if ZEND_DEBUG ++ unsigned int magic; ++# ifdef ZTS ++ THREAD_T thread_id; ++# endif ++#endif ++ struct _zend_mm_free_block_canary *prev_free_block; ++ struct _zend_mm_free_block_canary *next_free_block; ++ ++ struct _zend_mm_free_block_canary **parent; ++ struct _zend_mm_free_block_canary *child[2]; ++} zend_mm_free_block_canary; ++ ++#define ZEND_MM_NUM_BUCKETS (sizeof(size_t) << 3) ++ ++#define ZEND_MM_CACHE 1 ++#define ZEND_MM_CACHE_SIZE (ZEND_MM_NUM_BUCKETS * 4 * 1024) ++ ++#ifndef ZEND_MM_CACHE_STAT ++# define ZEND_MM_CACHE_STAT 0 ++#endif ++ ++typedef struct _zend_mm_heap_canary { ++ int use_zend_alloc; ++ void *(*_malloc)(size_t); ++ void (*_free)(void*); ++ void *(*_realloc)(void*, size_t); ++ size_t free_bitmap; ++ size_t large_free_bitmap; ++ size_t block_size; ++ size_t compact_size; ++ zend_mm_segment *segments_list; ++ zend_mm_storage *storage; ++ size_t real_size; ++ size_t real_peak; ++ size_t limit; ++ size_t size; ++ size_t peak; ++ size_t reserve_size; ++ void *reserve; ++ int overflow; ++ int internal; ++#if ZEND_MM_CACHE ++ unsigned int cached; ++ zend_mm_free_block_canary *cache[ZEND_MM_NUM_BUCKETS]; ++#endif ++ zend_mm_free_block_canary *free_buckets[ZEND_MM_NUM_BUCKETS*2]; ++ zend_mm_free_block_canary *large_free_buckets[ZEND_MM_NUM_BUCKETS]; ++ zend_mm_free_block_canary *rest_buckets[2]; ++#if ZEND_MM_CACHE_STAT ++ struct { ++ int count; ++ int max_count; ++ int hit; ++ int miss; ++ } cache_stat[ZEND_MM_NUM_BUCKETS+1]; ++#endif ++#if SUHOSIN_PATCH ++ size_t canary_1,canary_2,canary_3; ++#endif ++}; ++ ++#define ZEND_MM_SMALL_FREE_BUCKET(heap, index) \ ++ (zend_mm_free_block_canary*) ((char*)&heap->free_buckets[index * 2] + \ ++ sizeof(zend_mm_free_block_canary*) * 2 - \ ++ sizeof(zend_mm_small_free_block_canary)) ++ ++#define ZEND_MM_REST_BUCKET(heap) \ ++ (zend_mm_free_block_canary*)((char*)&heap->rest_buckets[0] + \ ++ sizeof(zend_mm_free_block_canary*) * 2 - \ ++ sizeof(zend_mm_small_free_block_canary)) ++ ++#if ZEND_MM_COOKIES ++ ++static unsigned int _zend_mm_cookie = 0; ++ ++# define ZEND_MM_COOKIE(block) \ ++ (((size_t)(block)) ^ _zend_mm_cookie) ++# define ZEND_MM_SET_COOKIE(block) \ ++ (block)->info._cookie = ZEND_MM_COOKIE(block) ++# define ZEND_MM_CHECK_COOKIE(block) \ ++ if (UNEXPECTED((block)->info._cookie != ZEND_MM_COOKIE(block))) { \ ++ zend_mm_panic("zend_mm_heap corrupted"); \ ++ } ++#else ++# define ZEND_MM_SET_COOKIE(block) ++# define ZEND_MM_CHECK_COOKIE(block) ++#endif ++ ++/* Default memory segment size */ ++#define ZEND_MM_SEG_SIZE (256 * 1024) ++ ++/* Reserved space for error reporting in case of memory overflow */ ++#define ZEND_MM_RESERVE_SIZE (8*1024) ++ ++#ifdef _WIN64 ++# define ZEND_MM_LONG_CONST(x) (x##i64) ++#else ++# define ZEND_MM_LONG_CONST(x) (x##L) ++#endif ++ ++#define ZEND_MM_TYPE_MASK ZEND_MM_LONG_CONST(0x3) ++ ++#define ZEND_MM_FREE_BLOCK ZEND_MM_LONG_CONST(0x0) ++#define ZEND_MM_USED_BLOCK ZEND_MM_LONG_CONST(0x1) ++#define ZEND_MM_GUARD_BLOCK ZEND_MM_LONG_CONST(0x3) ++ ++#define ZEND_MM_BLOCK(b, type, size) do { \ ++ size_t _size = (size); \ ++ (b)->info._size = (type) | _size; \ ++ ZEND_MM_BLOCK_AT(b, _size)->info._prev = (type) | _size; \ ++ ZEND_MM_SET_COOKIE(b); \ ++ } while (0); ++#define ZEND_MM_LAST_BLOCK(b) do { \ ++ (b)->info._size = ZEND_MM_GUARD_BLOCK | ZEND_MM_ALIGNED_HEADER_SIZE; \ ++ ZEND_MM_SET_MAGIC(b, MEM_BLOCK_GUARD); \ ++ } while (0); ++#define ZEND_MM_BLOCK_SIZE(b) ((b)->info._size & ~ZEND_MM_TYPE_MASK) ++#define ZEND_MM_IS_FREE_BLOCK(b) (!((b)->info._size & ZEND_MM_USED_BLOCK)) ++#define ZEND_MM_IS_USED_BLOCK(b) ((b)->info._size & ZEND_MM_USED_BLOCK) ++#define ZEND_MM_IS_GUARD_BLOCK(b) (((b)->info._size & ZEND_MM_TYPE_MASK) == ZEND_MM_GUARD_BLOCK) ++ ++#define ZEND_MM_NEXT_BLOCK(b) ZEND_MM_BLOCK_AT(b, ZEND_MM_BLOCK_SIZE(b)) ++#define ZEND_MM_PREV_BLOCK(b) ZEND_MM_BLOCK_AT(b, -(ssize_t)((b)->info._prev & ~ZEND_MM_TYPE_MASK)) ++ ++#define ZEND_MM_PREV_BLOCK_IS_FREE(b) (!((b)->info._prev & ZEND_MM_USED_BLOCK)) ++ ++#define ZEND_MM_MARK_FIRST_BLOCK(b) ((b)->info._prev = ZEND_MM_GUARD_BLOCK) ++#define ZEND_MM_IS_FIRST_BLOCK(b) ((b)->info._prev == ZEND_MM_GUARD_BLOCK) ++ ++/* optimized access */ ++#define ZEND_MM_FREE_BLOCK_SIZE(b) (b)->info._size ++ ++#ifndef ZEND_MM_ALIGNMENT ++# define ZEND_MM_ALIGNMENT 8 ++# define ZEND_MM_ALIGNMENT_LOG2 3 ++#elif ZEND_MM_ALIGNMENT < 4 ++# undef ZEND_MM_ALIGNMENT ++# undef ZEND_MM_ALIGNMENT_LOG2 ++# define ZEND_MM_ALIGNMENT 4 ++# define ZEND_MM_ALIGNMENT_LOG2 2 ++#endif ++ ++#define ZEND_MM_ALIGNMENT_MASK ~(ZEND_MM_ALIGNMENT-1) ++ ++/* Aligned header size */ ++#define ZEND_MM_ALIGNED_SIZE(size) ((size + ZEND_MM_ALIGNMENT - 1) & ZEND_MM_ALIGNMENT_MASK) ++#define ZEND_MM_ALIGNED_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_block_canary)) ++#define ZEND_MM_ALIGNED_FREE_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_small_free_block_canary)) ++#define ZEND_MM_MIN_ALLOC_BLOCK_SIZE ZEND_MM_ALIGNED_SIZE(ZEND_MM_ALIGNED_HEADER_SIZE + END_MAGIC_SIZE + CANARY_SIZE) ++#define ZEND_MM_ALIGNED_MIN_HEADER_SIZE (ZEND_MM_MIN_ALLOC_BLOCK_SIZE>ZEND_MM_ALIGNED_FREE_HEADER_SIZE?ZEND_MM_MIN_ALLOC_BLOCK_SIZE:ZEND_MM_ALIGNED_FREE_HEADER_SIZE) ++#define ZEND_MM_ALIGNED_SEGMENT_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_segment)) ++ ++#define ZEND_MM_MIN_SIZE ((ZEND_MM_ALIGNED_MIN_HEADER_SIZE>(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE))?(ZEND_MM_ALIGNED_MIN_HEADER_SIZE-(ZEND_MM_ALIGNED_HEADER_SIZE+END_MAGIC_SIZE+CANARY_SIZE)):0) ++ ++#define ZEND_MM_MAX_SMALL_SIZE ((ZEND_MM_NUM_BUCKETS<>ZEND_MM_ALIGNMENT_LOG2)-(ZEND_MM_ALIGNED_MIN_HEADER_SIZE>>ZEND_MM_ALIGNMENT_LOG2)) ++ ++#define ZEND_MM_SMALL_SIZE(true_size) (true_size < ZEND_MM_MAX_SMALL_SIZE) ++ ++/* Memory calculations */ ++#define ZEND_MM_BLOCK_AT(blk, offset) ((zend_mm_block_canary *) (((char *) (blk))+(offset))) ++#define ZEND_MM_DATA_OF(p) ((void *) (((char *) (p))+ZEND_MM_ALIGNED_HEADER_SIZE)) ++#define ZEND_MM_HEADER_OF(blk) ZEND_MM_BLOCK_AT(blk, -(int)ZEND_MM_ALIGNED_HEADER_SIZE) ++ ++/* Debug output */ ++#if ZEND_DEBUG ++ ++# ifdef ZTS ++# define ZEND_MM_SET_THREAD_ID(block) \ ++ ((zend_mm_block_canary*)(block))->thread_id = tsrm_thread_id() ++# define ZEND_MM_BAD_THREAD_ID(block) ((block)->thread_id != tsrm_thread_id()) ++# else ++# define ZEND_MM_SET_THREAD_ID(block) ++# define ZEND_MM_BAD_THREAD_ID(block) 0 ++# endif ++ ++# define ZEND_MM_VALID_PTR(block) \ ++ zend_mm_check_ptr(heap, block, 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC) ++ ++# define ZEND_MM_SET_MAGIC(block, val) do { \ ++ (block)->magic = (val); \ ++ } while (0) ++ ++# define ZEND_MM_CHECK_MAGIC(block, val) do { \ ++ if ((block)->magic != (val)) { \ ++ zend_mm_panic("zend_mm_heap corrupted"); \ ++ } \ ++ } while (0) ++ ++# define ZEND_MM_SET_DEBUG_INFO(block, __size, set_valid, set_thread) do { \ ++ ((zend_mm_block_canary*)(block))->debug.filename = __zend_filename; \ ++ ((zend_mm_block_canary*)(block))->debug.lineno = __zend_lineno; \ ++ ((zend_mm_block_canary*)(block))->debug.orig_filename = __zend_orig_filename; \ ++ ((zend_mm_block_canary*)(block))->debug.orig_lineno = __zend_orig_lineno; \ ++ ZEND_MM_SET_BLOCK_SIZE(block, __size); \ ++ if (set_valid) { \ ++ ZEND_MM_SET_MAGIC(block, MEM_BLOCK_VALID); \ ++ } \ ++ if (set_thread) { \ ++ ZEND_MM_SET_THREAD_ID(block); \ ++ } \ ++ } while (0) ++ ++#else ++ ++# define ZEND_MM_VALID_PTR(ptr) EXPECTED(ptr != NULL) ++ ++# define ZEND_MM_SET_MAGIC(block, val) ++ ++# define ZEND_MM_CHECK_MAGIC(block, val) ++ ++# define ZEND_MM_SET_DEBUG_INFO(block, __size, set_valid, set_thread) ZEND_MM_SET_BLOCK_SIZE(block, __size) ++ ++#endif ++ ++#if SUHOSIN_MM_WITH_CANARY_PROTECTION ++ ++# define SUHOSIN_MM_CHECK_CANARIES(block, MFUNCTION) do { \ ++ char *p = SUHOSIN_MM_END_CANARY_PTR(block); size_t check; \ ++ if (((block)->info.canary_1 != heap->canary_1) || ((block)->info.canary_2 != heap->canary_2)) { \ ++ canary_mismatch: \ ++ zend_suhosin_log(S_MEMORY, "canary mismatch on " MFUNCTION " - heap overflow detected at %p", (block)); \ ++ if (SUHOSIN_CONFIG(SUHOSIN_MM_IGNORE_CANARY_VIOLATION) == 0) { _exit(1); } else { (block)->info.canary_1 = heap->canary_1; (block)->info.canary_2 = heap->canary_2; }\ ++ } \ ++ memcpy(&check, p, CANARY_SIZE); \ ++ if (check != heap->canary_3) { \ ++ zend_suhosin_log(S_MEMORY, "end canary mismatch on " MFUNCTION " - heap overflow detected at %p", (block)); \ ++ if (SUHOSIN_CONFIG(SUHOSIN_MM_IGNORE_CANARY_VIOLATION) == 0) { _exit(1); } else { memcpy(p, heap->canary_3, CANARY_SIZE); } \ ++ } \ ++ } while (0) ++ ++# define SUHOSIN_MM_SET_CANARIES(block) do { \ ++ (block)->info.canary_1 = heap->canary_1; \ ++ (block)->info.canary_2 = heap->canary_2; \ ++ } while (0) ++ ++# define SUHOSIN_MM_END_CANARY_PTR(block) \ ++ (char *)(((char*)(ZEND_MM_DATA_OF(block))) + ((zend_mm_block_canary*)(block))->info.size + END_MAGIC_SIZE) ++ ++# define SUHOSIN_MM_SET_END_CANARY(block) do { \ ++ char *p = SUHOSIN_MM_END_CANARY_PTR(block); \ ++ memcpy(p, &heap->canary_3, CANARY_SIZE); \ ++ } while (0) ++ ++#else ++ ++# define SUHOSIN_MM_CHECK_CANARIES(block, MFUNCTION) ++# define SUHOSIN_MM_SET_CANARIES(block) ++# define SUHOSIN_MM_END_CANARY_PTR(block) ++# define SUHOSIN_MM_SET_END_CANARY(block) ++ ++#endif ++ ++ ++#if ZEND_MM_HEAP_PROTECTION ++ ++# define ZEND_MM_CHECK_PROTECTION(block) \ ++ do { \ ++ if ((block)->debug.start_magic != _mem_block_start_magic || \ ++ memcmp(ZEND_MM_END_MAGIC_PTR(block), &_mem_block_end_magic, END_MAGIC_SIZE) != 0) { \ ++ zend_mm_panic("zend_mm_heap corrupted"); \ ++ } \ ++ } while (0) ++ ++# define ZEND_MM_END_MAGIC_PTR(block) \ ++ (((char*)(ZEND_MM_DATA_OF(block))) + ((zend_mm_block_canary*)(block))->debug.size) ++ ++# define END_MAGIC_SIZE sizeof(unsigned int) ++ ++# define ZEND_MM_SET_BLOCK_SIZE(block, __size) do { \ ++ char *p; \ ++ ((zend_mm_block_canary*)(block))->debug.size = (__size); \ ++ p = ZEND_MM_END_MAGIC_PTR(block); \ ++ ((zend_mm_block_canary*)(block))->debug.start_magic = _mem_block_start_magic; \ ++ memcpy(p, &_mem_block_end_magic, END_MAGIC_SIZE); \ ++ } while (0) ++ ++static unsigned int _mem_block_start_magic = 0; ++static unsigned int _mem_block_end_magic = 0; ++ ++#else ++ ++# if ZEND_DEBUG ++# define ZEND_MM_SET_BLOCK_SIZE(block, _size) \ ++ ((zend_mm_block_canary*)(block))->debug.size = (_size) ++# else ++# define ZEND_MM_SET_BLOCK_SIZE(block, _size) ++# endif ++ ++# define ZEND_MM_CHECK_PROTECTION(block) ++ ++# define END_MAGIC_SIZE 0 ++ ++#endif ++ ++#if ZEND_MM_SAFE_UNLINKING ++# define ZEND_MM_CHECK_BLOCK_LINKAGE(block) \ ++ if (UNEXPECTED((block)->info._size != ZEND_MM_BLOCK_AT(block, ZEND_MM_FREE_BLOCK_SIZE(block))->info._prev) || \ ++ UNEXPECTED(!UNEXPECTED(ZEND_MM_IS_FIRST_BLOCK(block)) && \ ++ UNEXPECTED(ZEND_MM_PREV_BLOCK(block)->info._size != (block)->info._prev))) { \ ++ zend_mm_panic("zend_mm_heap corrupted"); \ ++ } ++#define ZEND_MM_CHECK_TREE(block) \ ++ if (UNEXPECTED(*((block)->parent) != (block))) { \ ++ zend_mm_panic("zend_mm_heap corrupted"); \ ++ } ++#else ++# define ZEND_MM_CHECK_BLOCK_LINKAGE(block) ++# define ZEND_MM_CHECK_TREE(block) ++#endif ++ ++#define ZEND_MM_LARGE_BUCKET_INDEX(S) zend_mm_high_bit(S) ++ ++void *_zend_mm_alloc_canary_int(zend_mm_heap_canary *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC; ++void _zend_mm_free_canary_int(zend_mm_heap_canary *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); ++void *_zend_mm_realloc_canary_int(zend_mm_heap_canary *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); ++ ++ ++static inline unsigned int zend_mm_high_bit(size_t _size) ++{ ++#if defined(__GNUC__) && defined(i386) ++ unsigned int n; ++ ++ __asm__("bsrl %1,%0\n\t" : "=r" (n) : "rm" (_size)); ++ return n; ++#elif defined(__GNUC__) && defined(__x86_64__) ++ unsigned long n; ++ ++ __asm__("bsrq %1,%0\n\t" : "=r" (n) : "rm" (_size)); ++ return (unsigned int)n; ++#elif defined(_MSC_VER) && defined(_M_IX86) ++ __asm { ++ bsr eax, _size ++ } ++#else ++ unsigned int n = 0; ++ while (_size != 0) { ++ _size = _size >> 1; ++ n++; ++ } ++ return n-1; ++#endif ++} ++ ++static inline unsigned int zend_mm_low_bit(size_t _size) ++{ ++#if defined(__GNUC__) && defined(i386) ++ unsigned int n; ++ ++ __asm__("bsfl %1,%0\n\t" : "=r" (n) : "rm" (_size)); ++ return n; ++#elif defined(__GNUC__) && defined(__x86_64__) ++ unsigned long n; ++ ++ __asm__("bsfq %1,%0\n\t" : "=r" (n) : "rm" (_size)); ++ return (unsigned int)n; ++#elif defined(_MSC_VER) && defined(_M_IX86) ++ __asm { ++ bsf eax, _size ++ } ++#else ++ static const int offset[16] = {4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0}; ++ unsigned int n; ++ unsigned int index = 0; ++ ++ n = offset[_size & 15]; ++ while (n == 4) { ++ _size >>= 4; ++ index += n; ++ n = offset[_size & 15]; ++ } ++ ++ return index + n; ++#endif ++} ++ ++static void zend_mm_add_to_rest_list(zend_mm_heap_canary *heap, zend_mm_free_block_canary *mm_block) ++{ ++ zend_mm_free_block_canary *prev, *next; ++ ++ ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_FREED); ++ ++ if (!ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block))) { ++ mm_block->parent = NULL; ++ } ++ ++ prev = SUHOSIN_MANGLE_PTR(heap->rest_buckets[0]); ++ next = SUHOSIN_MANGLE_PTR(prev->next_free_block); ++ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev); ++ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next); ++ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block); ++} ++ ++static void zend_mm_add_to_free_list(zend_mm_heap_canary *heap, zend_mm_free_block_canary *mm_block) ++{ ++ size_t size; ++ size_t index; ++ ++ ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_FREED); ++ ++ size = ZEND_MM_FREE_BLOCK_SIZE(mm_block); ++ if (EXPECTED(!ZEND_MM_SMALL_SIZE(size))) { ++ zend_mm_free_block_canary **p; ++ ++ index = ZEND_MM_LARGE_BUCKET_INDEX(size); ++ p = &heap->large_free_buckets[index]; ++ mm_block->child[0] = mm_block->child[1] = NULL; ++ if (!*p) { ++ *p = mm_block; ++ mm_block->parent = p; ++ mm_block->prev_free_block = mm_block->next_free_block = SUHOSIN_MANGLE_PTR(mm_block); ++ heap->large_free_bitmap |= (ZEND_MM_LONG_CONST(1) << index); ++ } else { ++ size_t m; ++ ++ for (m = size << (ZEND_MM_NUM_BUCKETS - index); ; m <<= 1) { ++ zend_mm_free_block_canary *prev = *p; ++ ++ if (ZEND_MM_FREE_BLOCK_SIZE(prev) != size) { ++ p = &prev->child[(m >> (ZEND_MM_NUM_BUCKETS-1)) & 1]; ++ if (!*p) { ++ *p = mm_block; ++ mm_block->parent = p; ++ mm_block->prev_free_block = mm_block->next_free_block = SUHOSIN_MANGLE_PTR(mm_block); ++ break; ++ } ++ } else { ++ zend_mm_free_block_canary *next = SUHOSIN_MANGLE_PTR(prev->next_free_block); ++ ++ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block); ++ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next); ++ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev); ++ mm_block->parent = NULL; ++ break; ++ } ++ } ++ } ++ } else { ++ zend_mm_free_block_canary *prev, *next; ++ ++ index = ZEND_MM_BUCKET_INDEX(size); ++ ++ prev = ZEND_MM_SMALL_FREE_BUCKET(heap, index); ++ if (SUHOSIN_MANGLE_PTR(prev->prev_free_block) == prev) { ++ heap->free_bitmap |= (ZEND_MM_LONG_CONST(1) << index); ++ } ++ next = SUHOSIN_MANGLE_PTR(prev->next_free_block); ++ ++ mm_block->prev_free_block = SUHOSIN_MANGLE_PTR(prev); ++ mm_block->next_free_block = SUHOSIN_MANGLE_PTR(next); ++ prev->next_free_block = next->prev_free_block = SUHOSIN_MANGLE_PTR(mm_block); ++ } ++} ++ ++static void zend_mm_remove_from_free_list(zend_mm_heap_canary *heap, zend_mm_free_block_canary *mm_block) ++{ ++ zend_mm_free_block_canary *prev = SUHOSIN_MANGLE_PTR(mm_block->prev_free_block); ++ zend_mm_free_block_canary *next = SUHOSIN_MANGLE_PTR(mm_block->next_free_block); ++ ++ ZEND_MM_CHECK_MAGIC(mm_block, MEM_BLOCK_FREED); ++ ++ if (EXPECTED(prev == mm_block)) { ++ zend_mm_free_block_canary **rp, **cp; ++ ++#if SUHOSIN_PATCH ++ if (next != mm_block) { ++ zend_suhosin_log(S_MEMORY, "zend_mm_heap corrupted at %p", mm_block); ++ _exit(1); ++ } ++#endif ++#if ZEND_MM_SAFE_UNLINKING ++ if (UNEXPECTED(next != mm_block)) { ++ zend_mm_panic("zend_mm_heap corrupted"); ++ } ++#endif ++ ++ rp = &mm_block->child[mm_block->child[1] != NULL]; ++ prev = *rp; ++ if (EXPECTED(prev == NULL)) { ++ size_t index = ZEND_MM_LARGE_BUCKET_INDEX(ZEND_MM_FREE_BLOCK_SIZE(mm_block)); ++ ++ ZEND_MM_CHECK_TREE(mm_block); ++ *mm_block->parent = NULL; ++ if (mm_block->parent == &heap->large_free_buckets[index]) { ++ heap->large_free_bitmap &= ~(ZEND_MM_LONG_CONST(1) << index); ++ } ++ } else { ++ while (*(cp = &(prev->child[prev->child[1] != NULL])) != NULL) { ++ prev = *cp; ++ rp = cp; ++ } ++ *rp = NULL; ++ ++subst_block: ++ ZEND_MM_CHECK_TREE(mm_block); ++ *mm_block->parent = prev; ++ prev->parent = mm_block->parent; ++ if ((prev->child[0] = mm_block->child[0])) { ++ ZEND_MM_CHECK_TREE(prev->child[0]); ++ prev->child[0]->parent = &prev->child[0]; ++ } ++ if ((prev->child[1] = mm_block->child[1])) { ++ ZEND_MM_CHECK_TREE(prev->child[1]); ++ prev->child[1]->parent = &prev->child[1]; ++ } ++ } ++ } else { ++ ++#if SUHOSIN_PATCH ++ if (SUHOSIN_MANGLE_PTR(prev->next_free_block) != mm_block || SUHOSIN_MANGLE_PTR(next->prev_free_block) != mm_block) { ++ zend_suhosin_log(S_MEMORY, "zend_mm_head corrupted at %p", mm_block); ++ _exit(1); ++ } ++#endif ++ ++#if ZEND_MM_SAFE_UNLINKING ++ if (UNEXPECTED(SUHOSIN_MANGLE_PTR(prev->next_free_block) != mm_block) || UNEXPECTED(SUHOSIN_MANGLE_PTR(next->prev_free_block) != mm_block)) { ++ zend_mm_panic("zend_mm_heap corrupted"); ++ } ++#endif ++ ++ prev->next_free_block = SUHOSIN_MANGLE_PTR(next); ++ next->prev_free_block = SUHOSIN_MANGLE_PTR(prev); ++ ++ if (EXPECTED(ZEND_MM_SMALL_SIZE(ZEND_MM_FREE_BLOCK_SIZE(mm_block)))) { ++ if (EXPECTED(prev == next)) { ++ size_t index = ZEND_MM_BUCKET_INDEX(ZEND_MM_FREE_BLOCK_SIZE(mm_block)); ++ ++ if (EXPECTED(heap->free_buckets[index*2] == heap->free_buckets[index*2+1])) { ++ heap->free_bitmap &= ~(ZEND_MM_LONG_CONST(1) << index); ++ } ++ } ++ } else if (UNEXPECTED(mm_block->parent != NULL)) { ++ goto subst_block; ++ } ++ } ++} ++ ++static void zend_mm_init(zend_mm_heap_canary *heap) ++{ ++ zend_mm_free_block_canary* p; ++ int i; ++ ++ heap->free_bitmap = 0; ++ heap->large_free_bitmap = 0; ++#if ZEND_MM_CACHE ++ heap->cached = 0; ++ memset(heap->cache, 0, sizeof(heap->cache)); ++#endif ++#if ZEND_MM_CACHE_STAT ++ for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) { ++ heap->cache_stat[i].count = 0; ++ } ++#endif ++ p = ZEND_MM_SMALL_FREE_BUCKET(heap, 0); ++ for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) { ++ p->next_free_block = SUHOSIN_MANGLE_PTR(p); ++ p->prev_free_block = SUHOSIN_MANGLE_PTR(p); ++ p = (zend_mm_free_block_canary*)((char*)p + sizeof(zend_mm_free_block_canary*) * 2); ++ heap->large_free_buckets[i] = NULL; ++ } ++ heap->rest_buckets[0] = heap->rest_buckets[1] = SUHOSIN_MANGLE_PTR(ZEND_MM_REST_BUCKET(heap)); ++#if SUHOSIN_PATCH ++ if (SUHOSIN_CONFIG(SUHOSIN_MM_USE_CANARY_PROTECTION)) { ++ zend_canary(&heap->canary_1, sizeof(heap->canary_1)); ++ zend_canary(&heap->canary_2, sizeof(heap->canary_2)); ++ zend_canary(&heap->canary_3, sizeof(heap->canary_3)); ++ } ++#endif ++} ++ ++static void zend_mm_del_segment(zend_mm_heap_canary *heap, zend_mm_segment *segment) ++{ ++ zend_mm_segment **p = &heap->segments_list; ++ ++ while (*p != segment) { ++ p = &(*p)->next_segment; ++ } ++ *p = segment->next_segment; ++ heap->real_size -= segment->size; ++ ZEND_MM_STORAGE_FREE(segment); ++} ++ ++#if ZEND_MM_CACHE ++static void zend_mm_free_cache(zend_mm_heap_canary *heap) ++{ ++ int i; ++ ++ for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) { ++ /* SUHOSIN_MANGLE_PTR should NOT affect NULL pointers */ ++ if (heap->cache[i]) { ++ zend_mm_free_block_canary *mm_block = SUHOSIN_MANGLE_PTR(heap->cache[i]); ++ ++ while (mm_block) { ++ size_t size = ZEND_MM_BLOCK_SIZE(mm_block); ++ zend_mm_free_block_canary *q = SUHOSIN_MANGLE_PTR(mm_block->prev_free_block); ++ zend_mm_block_canary *next_block = ZEND_MM_NEXT_BLOCK(mm_block); ++ ++ heap->cached -= size; ++ ++ if (ZEND_MM_PREV_BLOCK_IS_FREE(mm_block)) { ++ mm_block = (zend_mm_free_block_canary*)ZEND_MM_PREV_BLOCK(mm_block); ++ size += ZEND_MM_FREE_BLOCK_SIZE(mm_block); ++ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) mm_block); ++ } ++ if (ZEND_MM_IS_FREE_BLOCK(next_block)) { ++ size += ZEND_MM_FREE_BLOCK_SIZE(next_block); ++ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) next_block); ++ } ++ ZEND_MM_BLOCK(mm_block, ZEND_MM_FREE_BLOCK, size); ++ ++ if (ZEND_MM_IS_FIRST_BLOCK(mm_block) && ++ ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_NEXT_BLOCK(mm_block))) { ++ zend_mm_del_segment(heap, (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE)); ++ } else { ++ zend_mm_add_to_free_list(heap, (zend_mm_free_block_canary *) mm_block); ++ } ++ ++ mm_block = q; ++ } ++ heap->cache[i] = NULL; ++#if ZEND_MM_CACHE_STAT ++ heap->cache_stat[i].count = 0; ++#endif ++ } ++ } ++} ++#endif ++ ++#if ZEND_MM_HEAP_PROTECTION || ZEND_MM_COOKIES ++static void zend_mm_random(unsigned char *buf, size_t size) /* {{{ */ ++{ ++ size_t i = 0; ++ unsigned char t; ++ ++#ifdef ZEND_WIN32 ++ HCRYPTPROV hCryptProv; ++ int has_context = 0; ++ ++ if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) { ++ /* Could mean that the key container does not exist, let try ++ again by asking for a new one */ ++ if (GetLastError() == NTE_BAD_KEYSET) { ++ if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { ++ has_context = 1; ++ } ++ } ++ } else { ++ has_context = 1; ++ } ++ if (has_context) { ++ do { ++ BOOL ret = CryptGenRandom(hCryptProv, size, buf); ++ CryptReleaseContext(hCryptProv, 0); ++ if (ret) { ++ while (i < size && buf[i] != 0) { ++ i++; ++ } ++ if (i == size) { ++ return; ++ } ++ } ++ } while (0); ++ } ++#elif defined(HAVE_DEV_URANDOM) ++ int fd = open("/dev/urandom", 0); ++ ++ if (fd >= 0) { ++ if (read(fd, buf, size) == size) { ++ while (i < size && buf[i] != 0) { ++ i++; ++ } ++ if (i == size) { ++ close(fd); ++ return; ++ } ++ } ++ close(fd); ++ } ++#endif ++ t = (unsigned char)getpid(); ++ while (i < size) { ++ do { ++ buf[i] = ((unsigned char)rand()) ^ t; ++ } while (buf[i] == 0); ++ t = buf[i++] << 1; ++ } ++} ++/* }}} */ ++#endif ++ ++ ++/* Notes: ++ * - This function may alter the block_sizes values to match platform alignment ++ * - This function does *not* perform sanity checks on the arguments ++ */ ++zend_mm_heap_canary *__zend_mm_startup_canary_ex(const zend_mm_mem_handlers *handlers, size_t block_size, size_t reserve_size, int internal, void *params) ++{ ++ zend_mm_storage *storage; ++ zend_mm_heap_canary *heap; ++ zend_mm_free_block_canary *tmp; ++ ++#if 0 ++ int i; ++ ++ printf("ZEND_MM_ALIGNMENT=%d\n", ZEND_MM_ALIGNMENT); ++ printf("ZEND_MM_ALIGNMENT_LOG2=%d\n", ZEND_MM_ALIGNMENT_LOG2); ++ printf("ZEND_MM_MIN_SIZE=%d\n", ZEND_MM_MIN_SIZE); ++ printf("ZEND_MM_MAX_SMALL_SIZE=%d\n", ZEND_MM_MAX_SMALL_SIZE); ++ printf("ZEND_MM_ALIGNED_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_HEADER_SIZE); ++ printf("ZEND_MM_ALIGNED_FREE_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_FREE_HEADER_SIZE); ++ printf("ZEND_MM_MIN_ALLOC_BLOCK_SIZE=%d\n", ZEND_MM_MIN_ALLOC_BLOCK_SIZE); ++ printf("ZEND_MM_ALIGNED_MIN_HEADER_SIZE=%d\n", ZEND_MM_ALIGNED_MIN_HEADER_SIZE); ++ printf("ZEND_MM_ALIGNED_SEGMENT_SIZE=%d\n", ZEND_MM_ALIGNED_SEGMENT_SIZE); ++ for (i = 0; i < ZEND_MM_MAX_SMALL_SIZE; i++) { ++ printf("%3d%c: %3ld %d %2ld\n", i, (i == ZEND_MM_MIN_SIZE?'*':' '), (long)ZEND_MM_TRUE_SIZE(i), ZEND_MM_SMALL_SIZE(ZEND_MM_TRUE_SIZE(i)), (long)ZEND_MM_BUCKET_INDEX(ZEND_MM_TRUE_SIZE(i))); ++ } ++ exit(0); ++#endif ++ ++#if ZEND_MM_HEAP_PROTECTION ++ if (_mem_block_start_magic == 0) { ++ zend_mm_random((unsigned char*)&_mem_block_start_magic, sizeof(_mem_block_start_magic)); ++ } ++ if (_mem_block_end_magic == 0) { ++ zend_mm_random((unsigned char*)&_mem_block_end_magic, sizeof(_mem_block_end_magic)); ++ } ++#endif ++#if ZEND_MM_COOKIES ++ if (_zend_mm_cookie == 0) { ++ zend_mm_random((unsigned char*)&_zend_mm_cookie, sizeof(_zend_mm_cookie)); ++ } ++#endif ++ ++ /* get the pointer guardian and ensure low 3 bits are 1 */ ++ if (SUHOSIN_POINTER_GUARD == 0) { ++ zend_canary(&SUHOSIN_POINTER_GUARD, sizeof(SUHOSIN_POINTER_GUARD)); ++ SUHOSIN_POINTER_GUARD |= 7; ++ } ++ ++ if (zend_mm_low_bit(block_size) != zend_mm_high_bit(block_size)) { ++ fprintf(stderr, "'block_size' must be a power of two\n"); ++/* See http://support.microsoft.com/kb/190351 */ ++#ifdef PHP_WIN32 ++ fflush(stderr); ++#endif ++ exit(255); ++ } ++ storage = handlers->init(params); ++ if (!storage) { ++ fprintf(stderr, "Cannot initialize zend_mm storage [%s]\n", handlers->name); ++/* See http://support.microsoft.com/kb/190351 */ ++#ifdef PHP_WIN32 ++ fflush(stderr); ++#endif ++ exit(255); ++ } ++ storage->handlers = handlers; ++ ++ heap = malloc(sizeof(struct _zend_mm_heap_canary)); ++ if (heap == NULL) { ++ fprintf(stderr, "Cannot allocate heap for zend_mm storage [%s]\n", handlers->name); ++#ifdef PHP_WIN32 ++ fflush(stderr); ++#endif ++ exit(255); ++ } ++ ++ heap->storage = storage; ++ heap->block_size = block_size; ++ heap->compact_size = 0; ++ heap->segments_list = NULL; ++ zend_mm_init(heap); ++# if ZEND_MM_CACHE_STAT ++ memset(heap->cache_stat, 0, sizeof(heap->cache_stat)); ++# endif ++ ++ heap->use_zend_alloc = 1; ++ heap->real_size = 0; ++ heap->overflow = 0; ++ heap->real_peak = 0; ++ heap->limit = ZEND_MM_LONG_CONST(1)<<(ZEND_MM_NUM_BUCKETS-2); ++ heap->size = 0; ++ heap->peak = 0; ++ heap->internal = internal; ++ heap->reserve = NULL; ++ heap->reserve_size = reserve_size; ++ if (reserve_size > 0) { ++ heap->reserve = _zend_mm_alloc((zend_mm_heap *)heap, reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC); ++ } ++ if (internal) { ++ int i; ++ zend_mm_free_block_canary *p, *q, *orig; ++ zend_mm_heap_canary *mm_heap = _zend_mm_alloc((zend_mm_heap *)heap, sizeof(zend_mm_heap_canary) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC); ++ ++ *mm_heap = *heap; ++ ++ p = ZEND_MM_SMALL_FREE_BUCKET(mm_heap, 0); ++ orig = ZEND_MM_SMALL_FREE_BUCKET(heap, 0); ++ for (i = 0; i < ZEND_MM_NUM_BUCKETS; i++) { ++ q = p; ++ while (SUHOSIN_MANGLE_PTR(q->prev_free_block) != orig) { ++ q = SUHOSIN_MANGLE_PTR(q->prev_free_block); ++ } ++ q->prev_free_block = SUHOSIN_MANGLE_PTR(p); ++ q = p; ++ while (SUHOSIN_MANGLE_PTR(q->next_free_block) != orig) { ++ q = SUHOSIN_MANGLE_PTR(q->next_free_block); ++ } ++ q->next_free_block = SUHOSIN_MANGLE_PTR(p); ++ p = (zend_mm_free_block_canary*)((char*)p + sizeof(zend_mm_free_block_canary*) * 2); ++ orig = (zend_mm_free_block_canary*)((char*)orig + sizeof(zend_mm_free_block_canary*) * 2); ++ if (mm_heap->large_free_buckets[i]) { ++ mm_heap->large_free_buckets[i]->parent = &mm_heap->large_free_buckets[i]; ++ } ++ } ++ mm_heap->rest_buckets[0] = mm_heap->rest_buckets[1] = SUHOSIN_MANGLE_PTR(ZEND_MM_REST_BUCKET(mm_heap)); ++ ++ free(heap); ++ heap = mm_heap; ++ } ++ return heap; ++} ++ ++zend_mm_heap_canary *__zend_mm_startup_canary(void) ++{ ++ int i; ++ size_t seg_size; ++ char *mem_type = getenv("ZEND_MM_MEM_TYPE"); ++ char *tmp; ++ const zend_mm_mem_handlers *handlers; ++ zend_mm_heap_canary *heap; ++ ++ if (mem_type == NULL) { ++ i = 0; ++ } else { ++ for (i = 0; mem_handlers[i].name; i++) { ++ if (strcmp(mem_handlers[i].name, mem_type) == 0) { ++ break; ++ } ++ } ++ if (!mem_handlers[i].name) { ++ fprintf(stderr, "Wrong or unsupported zend_mm storage type '%s'\n", mem_type); ++ fprintf(stderr, " supported types:\n"); ++/* See http://support.microsoft.com/kb/190351 */ ++#ifdef PHP_WIN32 ++ fflush(stderr); ++#endif ++ for (i = 0; mem_handlers[i].name; i++) { ++ fprintf(stderr, " '%s'\n", mem_handlers[i].name); ++ } ++/* See http://support.microsoft.com/kb/190351 */ ++#ifdef PHP_WIN32 ++ fflush(stderr); ++#endif ++ exit(255); ++ } ++ } ++ handlers = &mem_handlers[i]; ++ ++ tmp = getenv("ZEND_MM_SEG_SIZE"); ++ if (tmp) { ++ seg_size = zend_atoi(tmp, 0); ++ if (zend_mm_low_bit(seg_size) != zend_mm_high_bit(seg_size)) { ++ fprintf(stderr, "ZEND_MM_SEG_SIZE must be a power of two\n"); ++/* See http://support.microsoft.com/kb/190351 */ ++#ifdef PHP_WIN32 ++ fflush(stderr); ++#endif ++ exit(255); ++ } else if (seg_size < ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE) { ++ fprintf(stderr, "ZEND_MM_SEG_SIZE is too small\n"); ++/* See http://support.microsoft.com/kb/190351 */ ++#ifdef PHP_WIN32 ++ fflush(stderr); ++#endif ++ exit(255); ++ } ++ } else { ++ seg_size = ZEND_MM_SEG_SIZE; ++ } ++ ++ heap = __zend_mm_startup_canary_ex(handlers, seg_size, ZEND_MM_RESERVE_SIZE, 0, NULL); ++ if (heap) { ++ tmp = getenv("ZEND_MM_COMPACT"); ++ if (tmp) { ++ heap->compact_size = zend_atoi(tmp, 0); ++ } else { ++ heap->compact_size = 2 * 1024 * 1024; ++ } ++ } ++ return heap; ++} ++ ++#if ZEND_DEBUG ++static long zend_mm_find_leaks(zend_mm_segment *segment, zend_mm_block_canary *b) ++{ ++ long leaks = 0; ++ zend_mm_block_canary *p, *q; ++ ++ p = ZEND_MM_NEXT_BLOCK(b); ++ while (1) { ++ if (ZEND_MM_IS_GUARD_BLOCK(p)) { ++ ZEND_MM_CHECK_MAGIC(p, MEM_BLOCK_GUARD); ++ segment = segment->next_segment; ++ if (!segment) { ++ break; ++ } ++ p = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE); ++ continue; ++ } ++ q = ZEND_MM_NEXT_BLOCK(p); ++ if (q <= p || ++ (char*)q > (char*)segment + segment->size || ++ p->info._size != q->info._prev) { ++ zend_mm_panic("zend_mm_heap corrupted"); ++ } ++ if (!ZEND_MM_IS_FREE_BLOCK(p)) { ++ if (p->magic == MEM_BLOCK_VALID) { ++ if (p->debug.filename==b->debug.filename && p->debug.lineno==b->debug.lineno) { ++ ZEND_MM_SET_MAGIC(p, MEM_BLOCK_LEAK); ++ leaks++; ++ } ++#if ZEND_MM_CACHE ++ } else if (p->magic == MEM_BLOCK_CACHED) { ++ /* skip it */ ++#endif ++ } else if (p->magic != MEM_BLOCK_LEAK) { ++ zend_mm_panic("zend_mm_heap corrupted"); ++ } ++ } ++ p = q; ++ } ++ return leaks; ++} ++ ++static void zend_mm_check_leaks(zend_mm_heap_canary *heap TSRMLS_DC) ++{ ++ zend_mm_segment *segment = heap->segments_list; ++ zend_mm_block_canary *p, *q; ++ zend_uint total = 0; ++ ++ if (!segment) { ++ return; ++ } ++ p = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE); ++ while (1) { ++ q = ZEND_MM_NEXT_BLOCK(p); ++ if (q <= p || ++ (char*)q > (char*)segment + segment->size || ++ p->info._size != q->info._prev) { ++ zend_mm_panic("zend_mm_heap corrupted"); ++ } ++ if (!ZEND_MM_IS_FREE_BLOCK(p)) { ++ if (p->magic == MEM_BLOCK_VALID) { ++ long repeated; ++ zend_leak_info leak; ++ ++ ZEND_MM_SET_MAGIC(p, MEM_BLOCK_LEAK); ++ ++ leak.addr = ZEND_MM_DATA_OF(p); ++ leak.size = p->debug.size; ++ leak.filename = p->debug.filename; ++ leak.lineno = p->debug.lineno; ++ leak.orig_filename = p->debug.orig_filename; ++ leak.orig_lineno = p->debug.orig_lineno; ++ ++ zend_message_dispatcher(ZMSG_LOG_SCRIPT_NAME, NULL TSRMLS_CC); ++ zend_message_dispatcher(ZMSG_MEMORY_LEAK_DETECTED, &leak TSRMLS_CC); ++ repeated = zend_mm_find_leaks(segment, p); ++ total += 1 + repeated; ++ if (repeated) { ++ zend_message_dispatcher(ZMSG_MEMORY_LEAK_REPEATED, (void *)(zend_uintptr_t)repeated TSRMLS_CC); ++ } ++#if ZEND_MM_CACHE ++ } else if (p->magic == MEM_BLOCK_CACHED) { ++ /* skip it */ ++#endif ++ } else if (p->magic != MEM_BLOCK_LEAK) { ++ zend_mm_panic("zend_mm_heap corrupted"); ++ } ++ } ++ if (ZEND_MM_IS_GUARD_BLOCK(q)) { ++ segment = segment->next_segment; ++ if (!segment) { ++ break; ++ } ++ q = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE); ++ } ++ p = q; ++ } ++ if (total) { ++ zend_message_dispatcher(ZMSG_MEMORY_LEAKS_GRAND_TOTAL, &total TSRMLS_CC); ++ } ++} ++ ++static int zend_mm_check_ptr(zend_mm_heap_canary *heap, void *ptr, int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ++{ ++ zend_mm_block_canary *p; ++ int no_cache_notice = 0; ++ int had_problems = 0; ++ int valid_beginning = 1; ++ ++ if (silent==2) { ++ silent = 1; ++ no_cache_notice = 1; ++ } else if (silent==3) { ++ silent = 0; ++ no_cache_notice = 1; ++ } ++ if (!silent) { ++ TSRMLS_FETCH(); ++ ++ zend_message_dispatcher(ZMSG_LOG_SCRIPT_NAME, NULL TSRMLS_CC); ++ zend_debug_alloc_output("---------------------------------------\n"); ++ zend_debug_alloc_output("%s(%d) : Block "PTR_FMT" status:\n" ZEND_FILE_LINE_RELAY_CC, ptr); ++ if (__zend_orig_filename) { ++ zend_debug_alloc_output("%s(%d) : Actual location (location was relayed)\n" ZEND_FILE_LINE_ORIG_RELAY_CC); ++ } ++ if (!ptr) { ++ zend_debug_alloc_output("NULL\n"); ++ zend_debug_alloc_output("---------------------------------------\n"); ++ return 0; ++ } ++ } ++ ++ if (!ptr) { ++ if (silent) { ++ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++ } ++ } ++ ++ p = ZEND_MM_HEADER_OF(ptr); ++ ++#ifdef ZTS ++ if (ZEND_MM_BAD_THREAD_ID(p)) { ++ if (!silent) { ++ zend_debug_alloc_output("Invalid pointer: ((thread_id=0x%0.8X) != (expected=0x%0.8X))\n", (long)p->thread_id, (long)tsrm_thread_id()); ++ had_problems = 1; ++ } else { ++ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++ } ++ } ++#endif ++ ++ if (p->info._size != ZEND_MM_NEXT_BLOCK(p)->info._prev) { ++ if (!silent) { ++ zend_debug_alloc_output("Invalid pointer: ((size="PTR_FMT") != (next.prev="PTR_FMT"))\n", p->info._size, ZEND_MM_NEXT_BLOCK(p)->info._prev); ++ had_problems = 1; ++ } else { ++ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++ } ++ } ++ if (p->info._prev != ZEND_MM_GUARD_BLOCK && ++ ZEND_MM_PREV_BLOCK(p)->info._size != p->info._prev) { ++ if (!silent) { ++ zend_debug_alloc_output("Invalid pointer: ((prev="PTR_FMT") != (prev.size="PTR_FMT"))\n", p->info._prev, ZEND_MM_PREV_BLOCK(p)->info._size); ++ had_problems = 1; ++ } else { ++ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++ } ++ } ++ ++ if (had_problems) { ++ zend_debug_alloc_output("---------------------------------------\n"); ++ return 0; ++ } ++ ++ if (!silent) { ++ zend_debug_alloc_output("%10s\t","Beginning: "); ++ } ++ ++ if (!ZEND_MM_IS_USED_BLOCK(p)) { ++ if (!silent) { ++ if (p->magic != MEM_BLOCK_FREED) { ++ zend_debug_alloc_output("Freed (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_FREED); ++ } else { ++ zend_debug_alloc_output("Freed\n"); ++ } ++ had_problems = 1; ++ } else { ++ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++ } ++ } else if (ZEND_MM_IS_GUARD_BLOCK(p)) { ++ if (!silent) { ++ if (p->magic != MEM_BLOCK_FREED) { ++ zend_debug_alloc_output("Guard (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_FREED); ++ } else { ++ zend_debug_alloc_output("Guard\n"); ++ } ++ had_problems = 1; ++ } else { ++ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++ } ++ } else { ++ switch (p->magic) { ++ case MEM_BLOCK_VALID: ++ case MEM_BLOCK_LEAK: ++ if (!silent) { ++ zend_debug_alloc_output("OK (allocated on %s:%d, %d bytes)\n", p->debug.filename, p->debug.lineno, (int)p->debug.size); ++ } ++ break; /* ok */ ++ case MEM_BLOCK_CACHED: ++ if (!no_cache_notice) { ++ if (!silent) { ++ zend_debug_alloc_output("Cached\n"); ++ had_problems = 1; ++ } else { ++ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++ } ++ } ++ case MEM_BLOCK_FREED: ++ if (!silent) { ++ zend_debug_alloc_output("Freed (invalid)\n"); ++ had_problems = 1; ++ } else { ++ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++ } ++ break; ++ case MEM_BLOCK_GUARD: ++ if (!silent) { ++ zend_debug_alloc_output("Guard (invalid)\n"); ++ had_problems = 1; ++ } else { ++ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++ } ++ break; ++ default: ++ if (!silent) { ++ zend_debug_alloc_output("Unknown (magic=0x%0.8X, expected=0x%0.8X)\n", p->magic, MEM_BLOCK_VALID); ++ had_problems = 1; ++ valid_beginning = 0; ++ } else { ++ return zend_mm_check_ptr(heap, ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++ } ++ break; ++ } ++ } ++ ++#if ZEND_MM_HEAP_PROTECTION ++ if (!valid_beginning) { ++ if (!silent) { ++ zend_debug_alloc_output("%10s\t", "Start:"); ++ zend_debug_alloc_output("Unknown\n"); ++ zend_debug_alloc_output("%10s\t", "End:"); ++ zend_debug_alloc_output("Unknown\n"); ++ } ++ } else { ++ char *end_magic = ZEND_MM_END_MAGIC_PTR(p); ++ ++ if (p->debug.start_magic == _mem_block_start_magic) { ++ if (!silent) { ++ zend_debug_alloc_output("%10s\t", "Start:"); ++ zend_debug_alloc_output("OK\n"); ++ } ++ } else { ++ char *overflow_ptr, *magic_ptr=(char *) &_mem_block_start_magic; ++ int overflows=0; ++ int i; ++ ++ if (silent) { ++ return _mem_block_check(ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++ } ++ had_problems = 1; ++ overflow_ptr = (char *) &p->debug.start_magic; ++ i = END_MAGIC_SIZE; ++ while (--i >= 0) { ++ if (overflow_ptr[i]!=magic_ptr[i]) { ++ overflows++; ++ } ++ } ++ zend_debug_alloc_output("%10s\t", "Start:"); ++ zend_debug_alloc_output("Overflown (magic=0x%0.8X instead of 0x%0.8X)\n", p->debug.start_magic, _mem_block_start_magic); ++ zend_debug_alloc_output("%10s\t",""); ++ if (overflows >= END_MAGIC_SIZE) { ++ zend_debug_alloc_output("At least %d bytes overflown\n", END_MAGIC_SIZE); ++ } else { ++ zend_debug_alloc_output("%d byte(s) overflown\n", overflows); ++ } ++ } ++ if (memcmp(end_magic, &_mem_block_end_magic, END_MAGIC_SIZE)==0) { ++ if (!silent) { ++ zend_debug_alloc_output("%10s\t", "End:"); ++ zend_debug_alloc_output("OK\n"); ++ } ++ } else { ++ char *overflow_ptr, *magic_ptr=(char *) &_mem_block_end_magic; ++ int overflows=0; ++ int i; ++ ++ if (silent) { ++ return _mem_block_check(ptr, 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++ } ++ had_problems = 1; ++ overflow_ptr = (char *) end_magic; ++ ++ for (i=0; i < END_MAGIC_SIZE; i++) { ++ if (overflow_ptr[i]!=magic_ptr[i]) { ++ overflows++; ++ } ++ } ++ ++ zend_debug_alloc_output("%10s\t", "End:"); ++ zend_debug_alloc_output("Overflown (magic=0x%0.8X instead of 0x%0.8X)\n", *end_magic, _mem_block_end_magic); ++ zend_debug_alloc_output("%10s\t",""); ++ if (overflows >= END_MAGIC_SIZE) { ++ zend_debug_alloc_output("At least %d bytes overflown\n", END_MAGIC_SIZE); ++ } else { ++ zend_debug_alloc_output("%d byte(s) overflown\n", overflows); ++ } ++ } ++ } ++#endif ++ ++ if (!silent) { ++ zend_debug_alloc_output("---------------------------------------\n"); ++ } ++ return ((!had_problems) ? 1 : 0); ++} ++ ++static int zend_mm_check_heap(zend_mm_heap_canary *heap, int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ++{ ++ zend_mm_segment *segment = heap->segments_list; ++ zend_mm_block_canary *p, *q; ++ int errors = 0; ++ ++ if (!segment) { ++ return 0; ++ } ++ p = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE); ++ while (1) { ++ q = ZEND_MM_NEXT_BLOCK(p); ++ if (q <= p || ++ (char*)q > (char*)segment + segment->size || ++ p->info._size != q->info._prev) { ++ zend_mm_panic("zend_mm_heap corrupted"); ++ } ++ if (!ZEND_MM_IS_FREE_BLOCK(p)) { ++ if (p->magic == MEM_BLOCK_VALID || p->magic == MEM_BLOCK_LEAK) { ++ if (!zend_mm_check_ptr(heap, ZEND_MM_DATA_OF(p), (silent?2:3) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC)) { ++ errors++; ++ } ++#if ZEND_MM_CACHE ++ } else if (p->magic == MEM_BLOCK_CACHED) { ++ /* skip it */ ++#endif ++ } else if (p->magic != MEM_BLOCK_LEAK) { ++ zend_mm_panic("zend_mm_heap corrupted"); ++ } ++ } ++ if (ZEND_MM_IS_GUARD_BLOCK(q)) { ++ segment = segment->next_segment; ++ if (!segment) { ++ return errors; ++ } ++ q = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE); ++ } ++ p = q; ++ } ++} ++#endif ++ ++void __zend_mm_shutdown_canary(zend_mm_heap_canary *heap, int full_shutdown, int silent TSRMLS_DC) ++{ ++ zend_mm_storage *storage; ++ zend_mm_segment *segment; ++ zend_mm_segment *prev; ++ int internal; ++ ++ if (heap->reserve) { ++#if ZEND_DEBUG ++ if (!silent) { ++ _zend_mm_free(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC); ++ } ++#endif ++ heap->reserve = NULL; ++ } ++ ++#if ZEND_MM_CACHE_STAT ++ if (full_shutdown) { ++ FILE *f; ++ ++ f = fopen("zend_mm.log", "w"); ++ if (f) { ++ int i,j; ++ size_t size, true_size, min_size, max_size; ++ int hit = 0, miss = 0; ++ ++ fprintf(f, "\nidx min_size max_size true_size max_len hits misses\n"); ++ size = 0; ++ while (1) { ++ true_size = ZEND_MM_TRUE_SIZE(size); ++ if (ZEND_MM_SMALL_SIZE(true_size)) { ++ min_size = size; ++ i = ZEND_MM_BUCKET_INDEX(true_size); ++ size++; ++ while (1) { ++ true_size = ZEND_MM_TRUE_SIZE(size); ++ if (ZEND_MM_SMALL_SIZE(true_size)) { ++ j = ZEND_MM_BUCKET_INDEX(true_size); ++ if (j > i) { ++ max_size = size-1; ++ break; ++ } ++ } else { ++ max_size = size-1; ++ break; ++ } ++ size++; ++ } ++ hit += heap->cache_stat[i].hit; ++ miss += heap->cache_stat[i].miss; ++ fprintf(f, "%2d %8d %8d %9d %8d %8d %8d\n", i, (int)min_size, (int)max_size, ZEND_MM_TRUE_SIZE(max_size), heap->cache_stat[i].max_count, heap->cache_stat[i].hit, heap->cache_stat[i].miss); ++ } else { ++ break; ++ } ++ } ++ fprintf(f, " %8d %8d\n", hit, miss); ++ fprintf(f, " %8d %8d\n", heap->cache_stat[ZEND_MM_NUM_BUCKETS].hit, heap->cache_stat[ZEND_MM_NUM_BUCKETS].miss); ++ fclose(f); ++ } ++ } ++#endif ++ ++#if ZEND_DEBUG ++ if (!silent) { ++ zend_mm_check_leaks(heap TSRMLS_CC); ++ } ++#endif ++ ++ internal = heap->internal; ++ storage = heap->storage; ++ segment = heap->segments_list; ++ while (segment) { ++ prev = segment; ++ segment = segment->next_segment; ++ ZEND_MM_STORAGE_FREE(prev); ++ } ++ if (full_shutdown) { ++ storage->handlers->dtor(storage); ++ if (!internal) { ++ free(heap); ++ } ++ } else { ++ if (heap->compact_size && ++ heap->real_peak > heap->compact_size) { ++ storage->handlers->compact(storage); ++ } ++ heap->segments_list = NULL; ++ zend_mm_init(heap); ++ heap->real_size = 0; ++ heap->real_peak = 0; ++ heap->size = 0; ++ heap->peak = 0; ++ if (heap->reserve_size) { ++ heap->reserve = _zend_mm_alloc((zend_mm_heap *)heap, heap->reserve_size ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC); ++ } ++ heap->overflow = 0; ++ } ++} ++ ++static void zend_mm_safe_error(zend_mm_heap_canary *heap, ++ const char *format, ++ size_t limit, ++#if ZEND_DEBUG ++ const char *filename, ++ uint lineno, ++#endif ++ size_t size) ++{ ++ if (heap->reserve) { ++ _zend_mm_free_canary_int(heap, heap->reserve ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC); ++ heap->reserve = NULL; ++ } ++ if (heap->overflow == 0) { ++ char *error_filename; ++ uint error_lineno; ++ TSRMLS_FETCH(); ++ if (zend_is_compiling(TSRMLS_C)) { ++ error_filename = zend_get_compiled_filename(TSRMLS_C); ++ error_lineno = zend_get_compiled_lineno(TSRMLS_C); ++ } else if (EG(in_execution)) { ++ error_filename = EG(active_op_array)?EG(active_op_array)->filename:NULL; ++ error_lineno = EG(opline_ptr)?(*EG(opline_ptr))->lineno:0; ++ } else { ++ error_filename = NULL; ++ error_lineno = 0; ++ } ++ if (!error_filename) { ++ error_filename = "Unknown"; ++ } ++ heap->overflow = 1; ++ zend_try { ++ zend_error_noreturn(E_ERROR, ++ format, ++ limit, ++#if ZEND_DEBUG ++ filename, ++ lineno, ++#endif ++ size); ++ } zend_catch { ++ if (heap->overflow == 2) { ++ fprintf(stderr, "\nFatal error: "); ++ fprintf(stderr, ++ format, ++ limit, ++#if ZEND_DEBUG ++ filename, ++ lineno, ++#endif ++ size); ++ fprintf(stderr, " in %s on line %d\n", error_filename, error_lineno); ++ } ++/* See http://support.microsoft.com/kb/190351 */ ++#ifdef PHP_WIN32 ++ fflush(stderr); ++#endif ++ } zend_end_try(); ++ } else { ++ heap->overflow = 2; ++ } ++ zend_bailout(); ++} ++ ++static zend_mm_free_block_canary *zend_mm_search_large_block(zend_mm_heap_canary *heap, size_t true_size) ++{ ++ zend_mm_free_block_canary *best_fit; ++ size_t index = ZEND_MM_LARGE_BUCKET_INDEX(true_size); ++ size_t bitmap = heap->large_free_bitmap >> index; ++ zend_mm_free_block_canary *p; ++ ++ if (bitmap == 0) { ++ return NULL; ++ } ++ ++ if (UNEXPECTED((bitmap & 1) != 0)) { ++ /* Search for best "large" free block */ ++ zend_mm_free_block_canary *rst = NULL; ++ size_t m; ++ size_t best_size = -1; ++ ++ best_fit = NULL; ++ p = heap->large_free_buckets[index]; ++ for (m = true_size << (ZEND_MM_NUM_BUCKETS - index); ; m <<= 1) { ++ if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) { ++ return SUHOSIN_MANGLE_PTR(p->next_free_block); ++ } else if (ZEND_MM_FREE_BLOCK_SIZE(p) >= true_size && ++ ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) { ++ best_size = ZEND_MM_FREE_BLOCK_SIZE(p); ++ best_fit = p; ++ } ++ if ((m & (ZEND_MM_LONG_CONST(1) << (ZEND_MM_NUM_BUCKETS-1))) == 0) { ++ if (p->child[1]) { ++ rst = p->child[1]; ++ } ++ if (p->child[0]) { ++ p = p->child[0]; ++ } else { ++ break; ++ } ++ } else if (p->child[1]) { ++ p = p->child[1]; ++ } else { ++ break; ++ } ++ } ++ ++ for (p = rst; p; p = p->child[p->child[0] != NULL]) { ++ if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) { ++ return SUHOSIN_MANGLE_PTR(p->next_free_block); ++ } else if (ZEND_MM_FREE_BLOCK_SIZE(p) > true_size && ++ ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) { ++ best_size = ZEND_MM_FREE_BLOCK_SIZE(p); ++ best_fit = p; ++ } ++ } ++ ++ if (best_fit) { ++ return SUHOSIN_MANGLE_PTR(best_fit->next_free_block); ++ } ++ bitmap = bitmap >> 1; ++ if (!bitmap) { ++ return NULL; ++ } ++ index++; ++ } ++ ++ /* Search for smallest "large" free block */ ++ best_fit = p = heap->large_free_buckets[index + zend_mm_low_bit(bitmap)]; ++ while ((p = p->child[p->child[0] != NULL])) { ++ if (ZEND_MM_FREE_BLOCK_SIZE(p) < ZEND_MM_FREE_BLOCK_SIZE(best_fit)) { ++ best_fit = p; ++ } ++ } ++ return SUHOSIN_MANGLE_PTR(best_fit->next_free_block); ++} ++ ++void *_zend_mm_alloc_canary_int(zend_mm_heap_canary *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ++{ ++ zend_mm_free_block_canary *best_fit; ++ size_t true_size = ZEND_MM_TRUE_SIZE(size); ++ size_t block_size; ++ size_t remaining_size; ++ size_t segment_size; ++ zend_mm_segment *segment; ++ int keep_rest = 0; ++ ++ if (EXPECTED(ZEND_MM_SMALL_SIZE(true_size))) { ++ size_t index = ZEND_MM_BUCKET_INDEX(true_size); ++ size_t bitmap; ++ ++ if (UNEXPECTED(true_size < size)) { ++ goto out_of_memory; ++ } ++#if ZEND_MM_CACHE ++ if (EXPECTED(heap->cache[index] != NULL)) { ++ /* Get block from cache */ ++#if ZEND_MM_CACHE_STAT ++ heap->cache_stat[index].count--; ++ heap->cache_stat[index].hit++; ++#endif ++ best_fit = SUHOSIN_MANGLE_PTR(heap->cache[index]); ++ heap->cache[index] = best_fit->prev_free_block; ++ heap->cached -= true_size; ++#if SUHOSIN_PATCH ++ SUHOSIN_MM_SET_CANARIES(best_fit); ++ ((zend_mm_block_canary*)best_fit)->info.size = size; ++ SUHOSIN_MM_SET_END_CANARY(best_fit); ++#endif ++ ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED); ++ ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0); ++ return ZEND_MM_DATA_OF(best_fit); ++ } ++#if ZEND_MM_CACHE_STAT ++ heap->cache_stat[index].miss++; ++#endif ++#endif ++ ++ bitmap = heap->free_bitmap >> index; ++ if (bitmap) { ++ /* Found some "small" free block that can be used */ ++ index += zend_mm_low_bit(bitmap); ++ best_fit = SUHOSIN_MANGLE_PTR(heap->free_buckets[index*2]); ++#if ZEND_MM_CACHE_STAT ++ heap->cache_stat[ZEND_MM_NUM_BUCKETS].hit++; ++#endif ++ goto zend_mm_finished_searching_for_block; ++ } ++ } ++ ++#if ZEND_MM_CACHE_STAT ++ heap->cache_stat[ZEND_MM_NUM_BUCKETS].miss++; ++#endif ++ ++ best_fit = zend_mm_search_large_block(heap, true_size); ++ ++ if (!best_fit && heap->real_size >= heap->limit - heap->block_size) { ++ zend_mm_free_block_canary *p = SUHOSIN_MANGLE_PTR(heap->rest_buckets[0]); ++ size_t best_size = -1; ++ ++ while (p != ZEND_MM_REST_BUCKET(heap)) { ++ if (UNEXPECTED(ZEND_MM_FREE_BLOCK_SIZE(p) == true_size)) { ++ best_fit = p; ++ goto zend_mm_finished_searching_for_block; ++ } else if (ZEND_MM_FREE_BLOCK_SIZE(p) > true_size && ++ ZEND_MM_FREE_BLOCK_SIZE(p) < best_size) { ++ best_size = ZEND_MM_FREE_BLOCK_SIZE(p); ++ best_fit = p; ++ } ++ p = SUHOSIN_MANGLE_PTR(p->prev_free_block); ++ } ++ } ++ ++ if (!best_fit) { ++ if (true_size > heap->block_size - (ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE)) { ++ /* Make sure we add a memory block which is big enough, ++ segment must have header "size" and trailer "guard" block */ ++ segment_size = true_size + ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE; ++ segment_size = (segment_size + (heap->block_size-1)) & ~(heap->block_size-1); ++ keep_rest = 1; ++ } else { ++ segment_size = heap->block_size; ++ } ++ ++ HANDLE_BLOCK_INTERRUPTIONS(); ++ ++ if (segment_size < true_size || ++ heap->real_size + segment_size > heap->limit) { ++ /* Memory limit overflow */ ++#if ZEND_MM_CACHE ++ zend_mm_free_cache(heap); ++#endif ++ HANDLE_UNBLOCK_INTERRUPTIONS(); ++#if ZEND_DEBUG ++ zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted at %s:%d (tried to allocate %lu bytes)", heap->limit, __zend_filename, __zend_lineno, size); ++#else ++ zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted (tried to allocate %lu bytes)", heap->limit, size); ++#endif ++ } ++ ++ segment = (zend_mm_segment *) ZEND_MM_STORAGE_ALLOC(segment_size); ++ ++ if (!segment) { ++ /* Storage manager cannot allocate memory */ ++#if ZEND_MM_CACHE ++ zend_mm_free_cache(heap); ++#endif ++ HANDLE_UNBLOCK_INTERRUPTIONS(); ++out_of_memory: ++#if ZEND_DEBUG ++ zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %lu bytes)", heap->real_size, __zend_filename, __zend_lineno, size); ++#else ++ zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %lu bytes)", heap->real_size, size); ++#endif ++ return NULL; ++ } ++ ++ heap->real_size += segment_size; ++ if (heap->real_size > heap->real_peak) { ++ heap->real_peak = heap->real_size; ++ } ++ ++ segment->size = segment_size; ++ segment->next_segment = heap->segments_list; ++ heap->segments_list = segment; ++ ++ best_fit = (zend_mm_free_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE); ++ ZEND_MM_MARK_FIRST_BLOCK(best_fit); ++ ++ block_size = segment_size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_HEADER_SIZE; ++ ++ ZEND_MM_LAST_BLOCK(ZEND_MM_BLOCK_AT(best_fit, block_size)); ++ ++ } else { ++zend_mm_finished_searching_for_block: ++ /* remove from free list */ ++ HANDLE_BLOCK_INTERRUPTIONS(); ++ ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_FREED); ++ ZEND_MM_CHECK_COOKIE(best_fit); ++ ZEND_MM_CHECK_BLOCK_LINKAGE(best_fit); ++ zend_mm_remove_from_free_list(heap, best_fit); ++ ++ block_size = ZEND_MM_FREE_BLOCK_SIZE(best_fit); ++ } ++ ++ remaining_size = block_size - true_size; ++ ++ if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) { ++ true_size = block_size; ++ ZEND_MM_BLOCK(best_fit, ZEND_MM_USED_BLOCK, true_size); ++ } else { ++ zend_mm_free_block_canary *new_free_block; ++ ++ /* prepare new free block */ ++ ZEND_MM_BLOCK(best_fit, ZEND_MM_USED_BLOCK, true_size); ++ new_free_block = (zend_mm_free_block_canary *) ZEND_MM_BLOCK_AT(best_fit, true_size); ++ ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size); ++ ++ /* add the new free block to the free list */ ++ if (EXPECTED(!keep_rest)) { ++ zend_mm_add_to_free_list(heap, new_free_block); ++ } else { ++ zend_mm_add_to_rest_list(heap, new_free_block); ++ } ++ } ++ ++ ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 1); ++ ++#if SUHOSIN_PATCH ++ SUHOSIN_MM_SET_CANARIES(best_fit); ++ ((zend_mm_block_canary*)best_fit)->info.size = size; ++ SUHOSIN_MM_SET_END_CANARY(best_fit); ++#endif ++ ++ heap->size += true_size; ++ if (heap->peak < heap->size) { ++ heap->peak = heap->size; ++ } ++ ++ HANDLE_UNBLOCK_INTERRUPTIONS(); ++ return ZEND_MM_DATA_OF(best_fit); ++} ++ ++ ++void _zend_mm_free_canary_int(zend_mm_heap_canary *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ++{ ++ zend_mm_block_canary *mm_block; ++ zend_mm_block_canary *next_block; ++ size_t size; ++ ++ if (!ZEND_MM_VALID_PTR(p)) { ++ return; ++ } ++ ++ mm_block = ZEND_MM_HEADER_OF(p); ++ size = ZEND_MM_BLOCK_SIZE(mm_block); ++#if SUHOSIN_PATCH ++ SUHOSIN_MM_CHECK_CANARIES(mm_block, "efree()"); ++#endif ++ ZEND_MM_CHECK_PROTECTION(mm_block); ++ ++#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION ++ memset(ZEND_MM_DATA_OF(mm_block), 0x5a, mm_block->debug.size); ++#endif ++#if SUHOSIN_PATCH ++ if (UNEXPECTED(SUHOSIN_CONFIG(SUHOSIN_MM_DESTROY_FREE_MEMORY))) { ++ memset(ZEND_MM_DATA_OF(mm_block), 0x5a, mm_block->info.size); ++ } ++#endif ++#if ZEND_MM_CACHE ++ if (EXPECTED(ZEND_MM_SMALL_SIZE(size)) && EXPECTED(heap->cached < ZEND_MM_CACHE_SIZE)) { ++ size_t index = ZEND_MM_BUCKET_INDEX(size); ++ zend_mm_free_block_canary **cache = &heap->cache[index]; ++ ++ ((zend_mm_free_block_canary*)mm_block)->prev_free_block = *cache; ++ *cache = (zend_mm_free_block_canary*)SUHOSIN_MANGLE_PTR(mm_block); ++ heap->cached += size; ++ ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED); ++#if ZEND_MM_CACHE_STAT ++ if (++heap->cache_stat[index].count > heap->cache_stat[index].max_count) { ++ heap->cache_stat[index].max_count = heap->cache_stat[index].count; ++ } ++#endif ++ return; ++ } ++#endif ++ ++ HANDLE_BLOCK_INTERRUPTIONS(); ++ ++ heap->size -= size; ++ ++ next_block = ZEND_MM_BLOCK_AT(mm_block, size); ++ if (ZEND_MM_IS_FREE_BLOCK(next_block)) { ++ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) next_block); ++ size += ZEND_MM_FREE_BLOCK_SIZE(next_block); ++ } ++ if (ZEND_MM_PREV_BLOCK_IS_FREE(mm_block)) { ++ mm_block = ZEND_MM_PREV_BLOCK(mm_block); ++ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) mm_block); ++ size += ZEND_MM_FREE_BLOCK_SIZE(mm_block); ++ } ++ if (ZEND_MM_IS_FIRST_BLOCK(mm_block) && ++ ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(mm_block, size))) { ++ zend_mm_del_segment(heap, (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE)); ++ } else { ++ ZEND_MM_BLOCK(mm_block, ZEND_MM_FREE_BLOCK, size); ++ zend_mm_add_to_free_list(heap, (zend_mm_free_block_canary *) mm_block); ++ } ++ HANDLE_UNBLOCK_INTERRUPTIONS(); ++} ++ ++void *_zend_mm_realloc_canary_int(zend_mm_heap_canary *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ++{ ++ zend_mm_block_canary *mm_block = ZEND_MM_HEADER_OF(p); ++ zend_mm_block_canary *next_block; ++ size_t true_size; ++ size_t orig_size; ++ void *ptr; ++ ++ if (UNEXPECTED(!p) || !ZEND_MM_VALID_PTR(p)) { ++ return _zend_mm_alloc_canary_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++ } ++ mm_block = ZEND_MM_HEADER_OF(p); ++ true_size = ZEND_MM_TRUE_SIZE(size); ++ orig_size = ZEND_MM_BLOCK_SIZE(mm_block); ++#if SUHOSIN_PATCH ++ SUHOSIN_MM_CHECK_CANARIES(mm_block, "erealloc()"); ++#endif ++ ZEND_MM_CHECK_PROTECTION(mm_block); ++ ++ if (UNEXPECTED(true_size < size)) { ++ goto out_of_memory; ++ } ++ ++ if (true_size <= orig_size) { ++ size_t remaining_size = orig_size - true_size; ++ ++ if (remaining_size >= ZEND_MM_ALIGNED_MIN_HEADER_SIZE) { ++ zend_mm_free_block_canary *new_free_block; ++ ++ HANDLE_BLOCK_INTERRUPTIONS(); ++ next_block = ZEND_MM_BLOCK_AT(mm_block, orig_size); ++ if (ZEND_MM_IS_FREE_BLOCK(next_block)) { ++ remaining_size += ZEND_MM_FREE_BLOCK_SIZE(next_block); ++ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) next_block); ++ } ++ ++ /* prepare new free block */ ++ ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size); ++ new_free_block = (zend_mm_free_block_canary *) ZEND_MM_BLOCK_AT(mm_block, true_size); ++ ++ ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size); ++ ++ /* add the new free block to the free list */ ++ zend_mm_add_to_free_list(heap, new_free_block); ++ heap->size += (true_size - orig_size); ++ HANDLE_UNBLOCK_INTERRUPTIONS(); ++ } ++ ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0); ++#if SUHOSIN_PATCH ++ SUHOSIN_MM_SET_CANARIES(mm_block); ++ ((zend_mm_block_canary*)mm_block)->info.size = size; ++ SUHOSIN_MM_SET_END_CANARY(mm_block); ++#endif ++ return p; ++ } ++ ++#if ZEND_MM_CACHE ++ if (ZEND_MM_SMALL_SIZE(true_size)) { ++ size_t index = ZEND_MM_BUCKET_INDEX(true_size); ++ ++ if (heap->cache[index] != NULL) { ++ zend_mm_free_block_canary *best_fit; ++ zend_mm_free_block_canary **cache; ++ ++#if ZEND_MM_CACHE_STAT ++ heap->cache_stat[index].count--; ++ heap->cache_stat[index].hit++; ++#endif ++ best_fit = SUHOSIN_MANGLE_PTR(heap->cache[index]); ++ heap->cache[index] = best_fit->prev_free_block; ++ ZEND_MM_CHECK_MAGIC(best_fit, MEM_BLOCK_CACHED); ++ ZEND_MM_SET_DEBUG_INFO(best_fit, size, 1, 0); ++#if SUHOSIN_PATCH ++ SUHOSIN_MM_SET_CANARIES(best_fit); ++ ((zend_mm_block_canary*)best_fit)->info.size = size; ++ SUHOSIN_MM_SET_END_CANARY(best_fit); ++#endif ++ ++ ptr = ZEND_MM_DATA_OF(best_fit); ++ ++#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION ++ memcpy(ptr, p, mm_block->debug.size); ++#else ++ memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE - CANARY_SIZE); ++#endif ++ ++ heap->cached -= true_size - orig_size; ++ ++ index = ZEND_MM_BUCKET_INDEX(orig_size); ++ cache = &heap->cache[index]; ++ ++ ((zend_mm_free_block_canary*)mm_block)->prev_free_block = *cache; ++ *cache = (zend_mm_free_block_canary*)SUHOSIN_MANGLE_PTR(mm_block); ++ ZEND_MM_SET_MAGIC(mm_block, MEM_BLOCK_CACHED); ++#if ZEND_MM_CACHE_STAT ++ if (++heap->cache_stat[index].count > heap->cache_stat[index].max_count) { ++ heap->cache_stat[index].max_count = heap->cache_stat[index].count; ++ } ++#endif ++ return ptr; ++ } ++ } ++#endif ++ ++ next_block = ZEND_MM_BLOCK_AT(mm_block, orig_size); ++ ++ if (ZEND_MM_IS_FREE_BLOCK(next_block)) { ++ ZEND_MM_CHECK_COOKIE(next_block); ++ ZEND_MM_CHECK_BLOCK_LINKAGE(next_block); ++ if (orig_size + ZEND_MM_FREE_BLOCK_SIZE(next_block) >= true_size) { ++ size_t block_size = orig_size + ZEND_MM_FREE_BLOCK_SIZE(next_block); ++ size_t remaining_size = block_size - true_size; ++ ++ HANDLE_BLOCK_INTERRUPTIONS(); ++ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) next_block); ++ ++ if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) { ++ true_size = block_size; ++ ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size); ++ } else { ++ zend_mm_free_block_canary *new_free_block; ++ ++ /* prepare new free block */ ++ ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size); ++ new_free_block = (zend_mm_free_block_canary *) ZEND_MM_BLOCK_AT(mm_block, true_size); ++ ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size); ++ ++ /* add the new free block to the free list */ ++ if (ZEND_MM_IS_FIRST_BLOCK(mm_block) && ++ ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(new_free_block, remaining_size))) { ++ zend_mm_add_to_rest_list(heap, new_free_block); ++ } else { ++ zend_mm_add_to_free_list(heap, new_free_block); ++ } ++ } ++ ZEND_MM_SET_DEBUG_INFO(mm_block, size, 0, 0); ++ heap->size = heap->size + true_size - orig_size; ++ if (heap->peak < heap->size) { ++ heap->peak = heap->size; ++ } ++ HANDLE_UNBLOCK_INTERRUPTIONS(); ++#if SUHOSIN_PATCH ++ SUHOSIN_MM_SET_CANARIES(mm_block); ++ ((zend_mm_block_canary*)mm_block)->info.size = size; ++ SUHOSIN_MM_SET_END_CANARY(mm_block); ++#endif ++ return p; ++ } else if (ZEND_MM_IS_FIRST_BLOCK(mm_block) && ++ ZEND_MM_IS_GUARD_BLOCK(ZEND_MM_BLOCK_AT(next_block, ZEND_MM_FREE_BLOCK_SIZE(next_block)))) { ++ HANDLE_BLOCK_INTERRUPTIONS(); ++ zend_mm_remove_from_free_list(heap, (zend_mm_free_block_canary *) next_block); ++ goto realloc_segment; ++ } ++ } else if (ZEND_MM_IS_FIRST_BLOCK(mm_block) && ZEND_MM_IS_GUARD_BLOCK(next_block)) { ++ zend_mm_segment *segment; ++ zend_mm_segment *segment_copy; ++ size_t segment_size; ++ size_t block_size; ++ size_t remaining_size; ++ ++ HANDLE_BLOCK_INTERRUPTIONS(); ++realloc_segment: ++ /* segment size, size of block and size of guard block */ ++ if (true_size > heap->block_size - (ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE)) { ++ segment_size = true_size+ZEND_MM_ALIGNED_SEGMENT_SIZE+ZEND_MM_ALIGNED_HEADER_SIZE; ++ segment_size = (segment_size + (heap->block_size-1)) & ~(heap->block_size-1); ++ } else { ++ segment_size = heap->block_size; ++ } ++ ++ segment_copy = (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE); ++ if (segment_size < true_size || ++ heap->real_size + segment_size - segment_copy->size > heap->limit) { ++ if (ZEND_MM_IS_FREE_BLOCK(next_block)) { ++ zend_mm_add_to_free_list(heap, (zend_mm_free_block_canary *) next_block); ++ } ++#if ZEND_MM_CACHE ++ zend_mm_free_cache(heap); ++#endif ++ HANDLE_UNBLOCK_INTERRUPTIONS(); ++#if ZEND_DEBUG ++ zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted at %s:%d (tried to allocate %ld bytes)", heap->limit, __zend_filename, __zend_lineno, size); ++#else ++ zend_mm_safe_error(heap, "Allowed memory size of %ld bytes exhausted (tried to allocate %ld bytes)", heap->limit, size); ++#endif ++ return NULL; ++ } ++ ++ segment = ZEND_MM_STORAGE_REALLOC(segment_copy, segment_size); ++ if (!segment) { ++#if ZEND_MM_CACHE ++ zend_mm_free_cache(heap); ++#endif ++ HANDLE_UNBLOCK_INTERRUPTIONS(); ++out_of_memory: ++#if ZEND_DEBUG ++ zend_mm_safe_error(heap, "Out of memory (allocated %ld) at %s:%d (tried to allocate %ld bytes)", heap->real_size, __zend_filename, __zend_lineno, size); ++#else ++ zend_mm_safe_error(heap, "Out of memory (allocated %ld) (tried to allocate %ld bytes)", heap->real_size, size); ++#endif ++ return NULL; ++ } ++ heap->real_size += segment_size - segment->size; ++ if (heap->real_size > heap->real_peak) { ++ heap->real_peak = heap->real_size; ++ } ++ ++ segment->size = segment_size; ++ ++ if (segment != segment_copy) { ++ zend_mm_segment **seg = &heap->segments_list; ++ while (*seg != segment_copy) { ++ seg = &(*seg)->next_segment; ++ } ++ *seg = segment; ++ mm_block = (zend_mm_block_canary *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE); ++ ZEND_MM_MARK_FIRST_BLOCK(mm_block); ++ } ++ ++ block_size = segment_size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_HEADER_SIZE; ++ remaining_size = block_size - true_size; ++ ++ /* setup guard block */ ++ ZEND_MM_LAST_BLOCK(ZEND_MM_BLOCK_AT(mm_block, block_size)); ++ ++ if (remaining_size < ZEND_MM_ALIGNED_MIN_HEADER_SIZE) { ++ true_size = block_size; ++ ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size); ++ } else { ++ zend_mm_free_block_canary *new_free_block; ++ ++ /* prepare new free block */ ++ ZEND_MM_BLOCK(mm_block, ZEND_MM_USED_BLOCK, true_size); ++ new_free_block = (zend_mm_free_block_canary *) ZEND_MM_BLOCK_AT(mm_block, true_size); ++ ZEND_MM_BLOCK(new_free_block, ZEND_MM_FREE_BLOCK, remaining_size); ++ ++ /* add the new free block to the free list */ ++ zend_mm_add_to_rest_list(heap, new_free_block); ++ } ++ ++ ZEND_MM_SET_DEBUG_INFO(mm_block, size, 1, 1); ++ ++ heap->size = heap->size + true_size - orig_size; ++ if (heap->peak < heap->size) { ++ heap->peak = heap->size; ++ } ++ ++ HANDLE_UNBLOCK_INTERRUPTIONS(); ++#if SUHOSIN_PATCH ++ SUHOSIN_MM_SET_CANARIES(mm_block); ++ ((zend_mm_block_canary*)mm_block)->info.size = size; ++ SUHOSIN_MM_SET_END_CANARY(mm_block); ++#endif ++ return ZEND_MM_DATA_OF(mm_block); ++ } ++ ++ ptr = _zend_mm_alloc_canary_int(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION ++ memcpy(ptr, p, mm_block->debug.size); ++#else ++ memcpy(ptr, p, orig_size - ZEND_MM_ALIGNED_HEADER_SIZE - CANARY_SIZE); ++#endif ++ _zend_mm_free_canary_int(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); ++ return ptr; ++} ++ ++ZEND_API size_t _zend_mm_block_size_canary(zend_mm_heap_canary *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ++{ ++ zend_mm_block_canary *mm_block; ++ ++ if (!ZEND_MM_VALID_PTR(p)) { ++ return 0; ++ } ++ mm_block = ZEND_MM_HEADER_OF(p); ++ ZEND_MM_CHECK_PROTECTION(mm_block); ++#if ZEND_DEBUG || ZEND_MM_HEAP_PROTECTION ++ return mm_block->debug.size; ++#else ++ return ZEND_MM_BLOCK_SIZE(mm_block); ++#endif ++} ++ ++#if defined(__GNUC__) && defined(i386) ++ ++static inline size_t safe_address(size_t nmemb, size_t size, size_t offset) ++{ ++ size_t res = nmemb; ++ unsigned long overflow = 0; ++ ++ __asm__ ("mull %3\n\taddl %4,%0\n\tadcl %1,%1" ++ : "=&a"(res), "=&d" (overflow) ++ : "%0"(res), ++ "rm"(size), ++ "rm"(offset)); ++ ++ if (UNEXPECTED(overflow)) { ++ zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset); ++ return 0; ++ } ++ return res; ++} ++ ++#elif defined(__GNUC__) && defined(__x86_64__) ++ ++static inline size_t safe_address(size_t nmemb, size_t size, size_t offset) ++{ ++ size_t res = nmemb; ++ unsigned long overflow = 0; ++ ++ __asm__ ("mulq %3\n\taddq %4,%0\n\tadcq %1,%1" ++ : "=&a"(res), "=&d" (overflow) ++ : "%0"(res), ++ "rm"(size), ++ "rm"(offset)); ++ ++ if (UNEXPECTED(overflow)) { ++ zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset); ++ return 0; ++ } ++ return res; ++} ++ ++#elif SIZEOF_SIZE_T == 4 && defined(HAVE_ZEND_LONG64) ++ ++static inline size_t safe_address(size_t nmemb, size_t size, size_t offset) ++{ ++ zend_ulong64 res = (zend_ulong64)nmemb * (zend_ulong64)size + (zend_ulong64)offset; ++ ++ if (UNEXPECTED(res > (zend_ulong64)0xFFFFFFFFL)) { ++ zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset); ++ return 0; ++ } ++ return (size_t) res; ++} ++ ++#else ++ ++static inline size_t safe_address(size_t nmemb, size_t size, size_t offset) ++{ ++ size_t res = nmemb * size + offset; ++ double _d = (double)nmemb * (double)size + (double)offset; ++ double _delta = (double)res - _d; ++ ++ if (UNEXPECTED((_d + _delta ) != _d)) { ++ zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset); ++ return 0; ++ } ++ return res; ++} ++#endif ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * indent-tabs-mode: t ++ * End: ++ */ ++ +diff -Nura php-5.3.9/Zend/zend_canary.c suhosin-patch-5.3.9-0.9.10/Zend/zend_canary.c +--- php-5.3.9/Zend/zend_canary.c 1970-01-01 01:00:00.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/Zend/zend_canary.c 2012-01-11 19:29:07.000000000 +0100 +@@ -0,0 +1,66 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | Suhosin-Patch for PHP | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 2004-2009 Stefan Esser | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.txt. | ++ | If you did not receive a copy of the PHP license and are unable to | ++ | obtain it through the world-wide-web, please send a note to | ++ | license@php.net so we can mail you a copy immediately. | ++ +----------------------------------------------------------------------+ ++ | Author: Stefan Esser | ++ +----------------------------------------------------------------------+ ++ */ ++/* $Id: zend_canary.c,v 1.1 2004/11/26 12:45:41 ionic Exp $ */ ++ ++#include "zend.h" ++ ++#include ++#include ++ ++ ++#if SUHOSIN_PATCH ++ ++static size_t last_canary = 0x73625123; ++ ++/* will be replaced later with more compatible method */ ++ZEND_API void zend_canary(void *buf, int len) ++{ ++ time_t t; ++ size_t canary; ++ int fd; ++ ++#ifndef PHP_WIN32 ++ fd = open("/dev/urandom", 0); ++ if (fd != -1) { ++ int r = read(fd, buf, len); ++ close(fd); ++ if (r == len) { ++ return; ++ } ++ } ++#endif ++ /* not good but we never want to do this */ ++ time(&t); ++ canary = *(unsigned int *)&t + getpid() << 16 + last_canary; ++ last_canary ^= (canary << 5) | (canary >> (32-5)); ++ /* When we ensure full win32 compatibility in next version ++ we will replace this with the random number code from zend_alloc.c */ ++ memcpy(buf, &canary, len); ++} ++ ++#endif ++ ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * End: ++ * vim600: sw=4 ts=4 fdm=marker ++ * vim<600: sw=4 ts=4 ++ */ +diff -Nura php-5.3.9/Zend/zend_compile.c suhosin-patch-5.3.9-0.9.10/Zend/zend_compile.c +--- php-5.3.9/Zend/zend_compile.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/Zend/zend_compile.c 2012-01-11 19:29:07.000000000 +0100 +@@ -73,6 +73,11 @@ + } + /* }}} */ + ++#if SUHOSIN_PATCH ++void *suhosin_zend_destroy_property_info_internal = zend_destroy_property_info_internal; ++void *suhosin_zend_destroy_property_info = zend_destroy_property_info; ++#endif ++ + static void build_runtime_defined_function_key(zval *result, const char *name, int name_length TSRMLS_DC) /* {{{ */ + { + char char_pos_buf[32]; +diff -Nura php-5.3.9/Zend/zend_compile.h suhosin-patch-5.3.9-0.9.10/Zend/zend_compile.h +--- php-5.3.9/Zend/zend_compile.h 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/Zend/zend_compile.h 2012-01-11 19:29:07.000000000 +0100 +@@ -607,6 +607,11 @@ + ZEND_API int zend_auto_global_disable_jit(const char *varname, zend_uint varname_length TSRMLS_DC); + ZEND_API size_t zend_dirname(char *path, size_t len); + ++#if SUHOSIN_PATCH ++extern void *suhosin_zend_destroy_property_info_internal; ++extern void *suhosin_zend_destroy_property_info; ++#endif ++ + int zendlex(znode *zendlval TSRMLS_DC); + + /* BEGIN: OPCODES */ +diff -Nura php-5.3.9/Zend/zend_constants.c suhosin-patch-5.3.9-0.9.10/Zend/zend_constants.c +--- php-5.3.9/Zend/zend_constants.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/Zend/zend_constants.c 2012-01-11 19:29:07.000000000 +0100 +@@ -113,6 +113,76 @@ + + REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS); + ++#if SUHOSIN_PATCH ++ REGISTER_MAIN_LONG_CONSTANT("S_MEMORY", S_MEMORY, CONST_PERSISTENT | CONST_CS); ++ REGISTER_MAIN_LONG_CONSTANT("S_VARS", S_VARS, CONST_PERSISTENT | CONST_CS); ++ REGISTER_MAIN_LONG_CONSTANT("S_FILES", S_FILES, CONST_PERSISTENT | CONST_CS); ++ REGISTER_MAIN_LONG_CONSTANT("S_INCLUDE", S_INCLUDE, CONST_PERSISTENT | CONST_CS); ++ REGISTER_MAIN_LONG_CONSTANT("S_SQL", S_SQL, CONST_PERSISTENT | CONST_CS); ++ REGISTER_MAIN_LONG_CONSTANT("S_EXECUTOR", S_EXECUTOR, CONST_PERSISTENT | CONST_CS); ++ REGISTER_MAIN_LONG_CONSTANT("S_MAIL", S_MAIL, CONST_PERSISTENT | CONST_CS); ++ REGISTER_MAIN_LONG_CONSTANT("S_SESSION", S_SESSION, CONST_PERSISTENT | CONST_CS); ++ REGISTER_MAIN_LONG_CONSTANT("S_MISC", S_MISC, CONST_PERSISTENT | CONST_CS); ++ REGISTER_MAIN_LONG_CONSTANT("S_INTERNAL", S_INTERNAL, CONST_PERSISTENT | CONST_CS); ++ REGISTER_MAIN_LONG_CONSTANT("S_ALL", S_ALL, CONST_PERSISTENT | CONST_CS); ++ ++ /* error levels */ ++ REGISTER_MAIN_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */ ++ REGISTER_MAIN_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */ ++ REGISTER_MAIN_LONG_CONSTANT("LOG_CRIT", LOG_CRIT, CONST_CS | CONST_PERSISTENT); /* critical conditions */ ++ REGISTER_MAIN_LONG_CONSTANT("LOG_ERR", LOG_ERR, CONST_CS | CONST_PERSISTENT); ++ REGISTER_MAIN_LONG_CONSTANT("LOG_WARNING", LOG_WARNING, CONST_CS | CONST_PERSISTENT); ++ REGISTER_MAIN_LONG_CONSTANT("LOG_NOTICE", LOG_NOTICE, CONST_CS | CONST_PERSISTENT); ++ REGISTER_MAIN_LONG_CONSTANT("LOG_INFO", LOG_INFO, CONST_CS | CONST_PERSISTENT); ++ REGISTER_MAIN_LONG_CONSTANT("LOG_DEBUG", LOG_DEBUG, CONST_CS | CONST_PERSISTENT); ++ /* facility: type of program logging the message */ ++ REGISTER_MAIN_LONG_CONSTANT("LOG_KERN", LOG_KERN, CONST_CS | CONST_PERSISTENT); ++ REGISTER_MAIN_LONG_CONSTANT("LOG_USER", LOG_USER, CONST_CS | CONST_PERSISTENT); /* generic user level */ ++ REGISTER_MAIN_LONG_CONSTANT("LOG_MAIL", LOG_MAIL, CONST_CS | CONST_PERSISTENT); /* log to email */ ++ REGISTER_MAIN_LONG_CONSTANT("LOG_DAEMON", LOG_DAEMON, CONST_CS | CONST_PERSISTENT); /* other system daemons */ ++ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTH", LOG_AUTH, CONST_CS | CONST_PERSISTENT); ++ REGISTER_MAIN_LONG_CONSTANT("LOG_SYSLOG", LOG_SYSLOG, CONST_CS | CONST_PERSISTENT); ++ REGISTER_MAIN_LONG_CONSTANT("LOG_LPR", LOG_LPR, CONST_CS | CONST_PERSISTENT); ++#ifdef LOG_NEWS ++ /* No LOG_NEWS on HP-UX */ ++ REGISTER_MAIN_LONG_CONSTANT("LOG_NEWS", LOG_NEWS, CONST_CS | CONST_PERSISTENT); /* usenet new */ ++#endif ++#ifdef LOG_UUCP ++ /* No LOG_UUCP on HP-UX */ ++ REGISTER_MAIN_LONG_CONSTANT("LOG_UUCP", LOG_UUCP, CONST_CS | CONST_PERSISTENT); ++#endif ++#ifdef LOG_CRON ++ /* apparently some systems don't have this one */ ++ REGISTER_MAIN_LONG_CONSTANT("LOG_CRON", LOG_CRON, CONST_CS | CONST_PERSISTENT); ++#endif ++#ifdef LOG_AUTHPRIV ++ /* AIX doesn't have LOG_AUTHPRIV */ ++ REGISTER_MAIN_LONG_CONSTANT("LOG_AUTHPRIV", LOG_AUTHPRIV, CONST_CS | CONST_PERSISTENT); ++#endif ++#ifndef PHP_WIN32 ++ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL0", LOG_LOCAL0, CONST_CS | CONST_PERSISTENT); ++ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL1", LOG_LOCAL1, CONST_CS | CONST_PERSISTENT); ++ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL2", LOG_LOCAL2, CONST_CS | CONST_PERSISTENT); ++ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL3", LOG_LOCAL3, CONST_CS | CONST_PERSISTENT); ++ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL4", LOG_LOCAL4, CONST_CS | CONST_PERSISTENT); ++ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL5", LOG_LOCAL5, CONST_CS | CONST_PERSISTENT); ++ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL6", LOG_LOCAL6, CONST_CS | CONST_PERSISTENT); ++ REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL7", LOG_LOCAL7, CONST_CS | CONST_PERSISTENT); ++#endif ++ /* options */ ++ REGISTER_MAIN_LONG_CONSTANT("LOG_PID", LOG_PID, CONST_CS | CONST_PERSISTENT); ++ REGISTER_MAIN_LONG_CONSTANT("LOG_CONS", LOG_CONS, CONST_CS | CONST_PERSISTENT); ++ REGISTER_MAIN_LONG_CONSTANT("LOG_ODELAY", LOG_ODELAY, CONST_CS | CONST_PERSISTENT); ++ REGISTER_MAIN_LONG_CONSTANT("LOG_NDELAY", LOG_NDELAY, CONST_CS | CONST_PERSISTENT); ++#ifdef LOG_NOWAIT ++ REGISTER_MAIN_LONG_CONSTANT("LOG_NOWAIT", LOG_NOWAIT, CONST_CS | CONST_PERSISTENT); ++#endif ++#ifdef LOG_PERROR ++ /* AIX doesn't have LOG_PERROR */ ++ REGISTER_MAIN_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/ ++#endif ++#endif ++ + REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_PROVIDE_OBJECT", DEBUG_BACKTRACE_PROVIDE_OBJECT, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_IGNORE_ARGS", DEBUG_BACKTRACE_IGNORE_ARGS, CONST_PERSISTENT | CONST_CS); + /* true/false constants */ +diff -Nura php-5.3.9/Zend/zend_errors.h suhosin-patch-5.3.9-0.9.10/Zend/zend_errors.h +--- php-5.3.9/Zend/zend_errors.h 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/Zend/zend_errors.h 2012-01-11 19:29:07.000000000 +0100 +@@ -41,6 +41,20 @@ + #define E_ALL (E_ERROR | E_WARNING | E_PARSE | E_NOTICE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE | E_RECOVERABLE_ERROR | E_DEPRECATED | E_USER_DEPRECATED) + #define E_CORE (E_CORE_ERROR | E_CORE_WARNING) + ++#if SUHOSIN_PATCH ++#define S_MEMORY (1<<0L) ++#define S_MISC (1<<1L) ++#define S_VARS (1<<2L) ++#define S_FILES (1<<3L) ++#define S_INCLUDE (1<<4L) ++#define S_SQL (1<<5L) ++#define S_EXECUTOR (1<<6L) ++#define S_MAIL (1<<7L) ++#define S_SESSION (1<<8L) ++#define S_INTERNAL (1<<29L) ++#define S_ALL (S_MEMORY | S_VARS | S_INCLUDE | S_FILES | S_MAIL | S_SESSION | S_MISC | S_SQL | S_EXECUTOR) ++#endif ++ + #endif /* ZEND_ERRORS_H */ + + /* +diff -Nura php-5.3.9/Zend/zend_hash.c suhosin-patch-5.3.9-0.9.10/Zend/zend_hash.c +--- php-5.3.9/Zend/zend_hash.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/Zend/zend_hash.c 2012-01-11 19:29:07.000000000 +0100 +@@ -20,6 +20,7 @@ + /* $Id: zend_hash.c 321634 2012-01-01 13:15:04Z felipe $ */ + + #include "zend.h" ++#include "zend_compile.h" + + #define CONNECT_TO_BUCKET_DLLIST(element, list_head) \ + (element)->pNext = (list_head); \ +@@ -136,6 +137,199 @@ + } + + ++#if SUHOSIN_PATCH ++#ifdef ZTS ++static MUTEX_T zend_hash_dprot_mx_reader; ++static MUTEX_T zend_hash_dprot_mx_writer; ++static unsigned int zend_hash_dprot_reader; ++#endif ++static unsigned int zend_hash_dprot_counter; ++static unsigned int zend_hash_dprot_curmax; ++static dtor_func_t *zend_hash_dprot_table = NULL; ++ ++static void zend_hash_dprot_begin_read() ++{ ++#ifdef ZTS ++ tsrm_mutex_lock(zend_hash_dprot_mx_reader); ++ if ((++(zend_hash_dprot_reader)) == 1) { ++ tsrm_mutex_lock(zend_hash_dprot_mx_writer); ++ } ++ tsrm_mutex_unlock(zend_hash_dprot_mx_reader); ++#endif ++} ++ ++static void zend_hash_dprot_end_read() ++{ ++#ifdef ZTS ++ tsrm_mutex_lock(zend_hash_dprot_mx_reader); ++ if ((--(zend_hash_dprot_reader)) == 0) { ++ tsrm_mutex_unlock(zend_hash_dprot_mx_writer); ++ } ++ tsrm_mutex_unlock(zend_hash_dprot_mx_reader); ++#endif ++} ++ ++static void zend_hash_dprot_begin_write() ++{ ++#ifdef ZTS ++ tsrm_mutex_lock(zend_hash_dprot_mx_writer); ++#endif ++} ++ ++static void zend_hash_dprot_end_write() ++{ ++#ifdef ZTS ++ tsrm_mutex_unlock(zend_hash_dprot_mx_writer); ++#endif ++} ++ ++/*ZEND_API void zend_hash_dprot_dtor() ++{ ++#ifdef ZTS ++ tsrm_mutex_free(zend_hash_dprot_mx_reader); ++ tsrm_mutex_free(zend_hash_dprot_mx_writer); ++#endif ++ free(zend_hash_dprot_table); ++}*/ ++ ++static void zend_hash_add_destructor(dtor_func_t pDestructor) ++{ ++ int left, right, mid; ++ zend_bool found = 0; ++ unsigned long value; ++ ++ if (pDestructor == NULL || pDestructor == ZVAL_PTR_DTOR || pDestructor == ZVAL_INTERNAL_PTR_DTOR ++ || pDestructor == ZEND_FUNCTION_DTOR || pDestructor == ZEND_CLASS_DTOR) { ++ return; ++ } ++ ++ if (zend_hash_dprot_table == NULL) { ++#ifdef ZTS ++ zend_hash_dprot_mx_reader = tsrm_mutex_alloc(); ++ zend_hash_dprot_mx_writer = tsrm_mutex_alloc(); ++ zend_hash_dprot_reader = 0; ++#endif ++ zend_hash_dprot_counter = 0; ++ zend_hash_dprot_curmax = 256; ++ zend_hash_dprot_table = (dtor_func_t *) malloc(256 * sizeof(dtor_func_t)); ++ } ++ ++ zend_hash_dprot_begin_write(); ++ ++ if (zend_hash_dprot_counter == 0) { ++ zend_hash_dprot_counter++; ++ zend_hash_dprot_table[0] = pDestructor; ++ } else { ++ value = (unsigned long) pDestructor; ++ left = 0; ++ right = zend_hash_dprot_counter-1; ++ mid = 0; ++ ++ while (left < right) { ++ mid = (right - left) >> 1; ++ mid += left; ++ if ((unsigned long)zend_hash_dprot_table[mid] == value) { ++ found = 1; ++ break; ++ } ++ if (value < (unsigned long)zend_hash_dprot_table[mid]) { ++ right = mid-1; ++ } else { ++ left = mid+1; ++ } ++ } ++ if ((unsigned long)zend_hash_dprot_table[left] == value) { ++ found = 1; ++ } ++ ++ if (!found) { ++ ++ if (zend_hash_dprot_counter >= zend_hash_dprot_curmax) { ++ zend_hash_dprot_curmax += 256; ++ zend_hash_dprot_table = (dtor_func_t *) realloc(zend_hash_dprot_table, zend_hash_dprot_curmax * sizeof(dtor_func_t)); ++ } ++ ++ if ((unsigned long)zend_hash_dprot_table[left] < value) { ++ memmove(zend_hash_dprot_table+left+2, zend_hash_dprot_table+left+1, (zend_hash_dprot_counter-left-1)*sizeof(dtor_func_t)); ++ zend_hash_dprot_table[left+1] = pDestructor; ++ } else { ++ memmove(zend_hash_dprot_table+left+1, zend_hash_dprot_table+left, (zend_hash_dprot_counter-left)*sizeof(dtor_func_t)); ++ zend_hash_dprot_table[left] = pDestructor; ++ } ++ ++ zend_hash_dprot_counter++; ++ } ++ } ++ ++ zend_hash_dprot_end_write(); ++} ++ ++static void zend_hash_check_destructor(dtor_func_t pDestructor) ++{ ++ unsigned long value; ++ ++ if (pDestructor == NULL || pDestructor == ZVAL_PTR_DTOR || pDestructor == ZVAL_INTERNAL_PTR_DTOR ++#ifdef ZEND_ENGINE_2 ++ || pDestructor == suhosin_zend_destroy_property_info_internal || pDestructor == suhosin_zend_destroy_property_info ++#endif ++ || pDestructor == ZEND_FUNCTION_DTOR || pDestructor == ZEND_CLASS_DTOR) { ++ return; ++ } ++ ++ zend_hash_dprot_begin_read(); ++ ++ if (zend_hash_dprot_counter > 0) { ++ int left, right, mid; ++ zend_bool found = 0; ++ ++ value = (unsigned long) pDestructor; ++ left = 0; ++ right = zend_hash_dprot_counter-1; ++ ++ while (left < right) { ++ mid = (right - left) >> 1; ++ mid += left; ++ if ((unsigned long)zend_hash_dprot_table[mid] == value) { ++ found = 1; ++ break; ++ } ++ if (value < (unsigned long)zend_hash_dprot_table[mid]) { ++ right = mid-1; ++ } else { ++ left = mid+1; ++ } ++ } ++ if ((unsigned long)zend_hash_dprot_table[left] == value) { ++ found = 1; ++ } ++ ++ if (!found) { ++ zend_hash_dprot_end_read(); ++ ++ zend_suhosin_log(S_MEMORY, "possible memory corruption detected - unknown Hashtable destructor"); ++ if (SUHOSIN_CONFIG(SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR) == 0) { ++ _exit(1); ++ } ++ return; ++ } ++ ++ } else { ++ zend_hash_dprot_end_read(); ++ ++ zend_suhosin_log(S_MEMORY, "possible memory corruption detected - unknown Hashtable destructor"); ++ if (SUHOSIN_CONFIG(SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR) == 0) { ++ _exit(1); ++ } ++ return; ++ } ++ ++ zend_hash_dprot_end_read(); ++} ++ ++#else ++#define zend_hash_add_destructor(pDestructor) do {} while(0) ++#define zend_hash_check_destructor(pDestructor) do {} while(0) ++#endif + + ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC) + { +@@ -156,6 +350,7 @@ + + ht->nTableMask = ht->nTableSize - 1; + ht->pDestructor = pDestructor; ++ zend_hash_add_destructor(pDestructor); + ht->arBuckets = NULL; + ht->pListHead = NULL; + ht->pListTail = NULL; +@@ -233,6 +428,7 @@ + return FAILURE; + } + #endif ++ zend_hash_check_destructor(ht->pDestructor); + if (ht->pDestructor) { + ht->pDestructor(p->pData); + } +@@ -298,6 +494,7 @@ + return FAILURE; + } + #endif ++ zend_hash_check_destructor(ht->pDestructor); + if (ht->pDestructor) { + ht->pDestructor(p->pData); + } +@@ -373,6 +570,7 @@ + return FAILURE; + } + #endif ++ zend_hash_check_destructor(ht->pDestructor); + if (ht->pDestructor) { + ht->pDestructor(p->pData); + } +@@ -496,6 +694,7 @@ + if (ht->pInternalPointer == p) { + ht->pInternalPointer = p->pListNext; + } ++ zend_hash_check_destructor(ht->pDestructor); + if (ht->pDestructor) { + ht->pDestructor(p->pData); + } +@@ -522,6 +721,7 @@ + SET_INCONSISTENT(HT_IS_DESTROYING); + + p = ht->pListHead; ++ zend_hash_check_destructor(ht->pDestructor); + while (p != NULL) { + q = p; + p = p->pListNext; +@@ -554,6 +754,7 @@ + ht->nNextFreeElement = 0; + ht->pInternalPointer = NULL; + ++ zend_hash_check_destructor(ht->pDestructor); + while (p != NULL) { + q = p; + p = p->pListNext; +@@ -608,6 +809,7 @@ + ht->nNumOfElements--; + HANDLE_UNBLOCK_INTERRUPTIONS(); + ++ zend_hash_check_destructor(ht->pDestructor); + if (ht->pDestructor) { + ht->pDestructor(p->pData); + } +@@ -628,6 +830,7 @@ + IS_CONSISTENT(ht); + + p = ht->pListHead; ++ zend_hash_check_destructor(ht->pDestructor); + while (p != NULL) { + p = zend_hash_apply_deleter(ht, p); + } +@@ -1180,6 +1383,7 @@ + + IS_CONSISTENT(ht); + ++ zend_hash_check_destructor(ht->pDestructor); + if (p) { + if (key_type == HASH_KEY_IS_LONG) { + str_length = 0; +diff -Nura php-5.3.9/Zend/zend_llist.c suhosin-patch-5.3.9-0.9.10/Zend/zend_llist.c +--- php-5.3.9/Zend/zend_llist.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/Zend/zend_llist.c 2012-01-11 19:29:07.000000000 +0100 +@@ -23,6 +23,194 @@ + #include "zend_llist.h" + #include "zend_qsort.h" + ++#if SUHOSIN_PATCH ++#ifdef ZTS ++static MUTEX_T zend_llist_dprot_mx_reader; ++static MUTEX_T zend_llist_dprot_mx_writer; ++static unsigned int zend_llist_dprot_reader; ++#endif ++static unsigned int zend_llist_dprot_counter; ++static unsigned int zend_llist_dprot_curmax; ++static llist_dtor_func_t *zend_llist_dprot_table = NULL; ++ ++static void zend_llist_dprot_begin_read() ++{ ++#ifdef ZTS ++ tsrm_mutex_lock(zend_llist_dprot_mx_reader); ++ if ((++(zend_llist_dprot_reader)) == 1) { ++ tsrm_mutex_lock(zend_llist_dprot_mx_writer); ++ } ++ tsrm_mutex_unlock(zend_llist_dprot_mx_reader); ++#endif ++} ++ ++static void zend_llist_dprot_end_read() ++{ ++#ifdef ZTS ++ tsrm_mutex_lock(zend_llist_dprot_mx_reader); ++ if ((--(zend_llist_dprot_reader)) == 0) { ++ tsrm_mutex_unlock(zend_llist_dprot_mx_writer); ++ } ++ tsrm_mutex_unlock(zend_llist_dprot_mx_reader); ++#endif ++} ++ ++static void zend_llist_dprot_begin_write() ++{ ++#ifdef ZTS ++ tsrm_mutex_lock(zend_llist_dprot_mx_writer); ++#endif ++} ++ ++static void zend_llist_dprot_end_write() ++{ ++#ifdef ZTS ++ tsrm_mutex_unlock(zend_llist_dprot_mx_writer); ++#endif ++} ++ ++/*ZEND_API void zend_llist_dprot_dtor() ++{ ++#ifdef ZTS ++ tsrm_mutex_free(zend_llist_dprot_mx_reader); ++ tsrm_mutex_free(zend_llist_dprot_mx_writer); ++#endif ++ free(zend_llist_dprot_table); ++}*/ ++ ++static void zend_llist_add_destructor(llist_dtor_func_t pDestructor) ++{ ++ int left, right, mid; ++ zend_bool found = 0; ++ unsigned long value; ++ ++ if (pDestructor == NULL || pDestructor == ZVAL_PTR_DTOR) { ++ return; ++ } ++ ++ if (zend_llist_dprot_table == NULL) { ++#ifdef ZTS ++ zend_llist_dprot_mx_reader = tsrm_mutex_alloc(); ++ zend_llist_dprot_mx_writer = tsrm_mutex_alloc(); ++ zend_llist_dprot_reader = 0; ++#endif ++ zend_llist_dprot_counter = 0; ++ zend_llist_dprot_curmax = 256; ++ zend_llist_dprot_table = (llist_dtor_func_t *) malloc(256 * sizeof(llist_dtor_func_t)); ++ } ++ ++ zend_llist_dprot_begin_write(); ++ ++ if (zend_llist_dprot_counter == 0) { ++ zend_llist_dprot_counter++; ++ zend_llist_dprot_table[0] = pDestructor; ++ } else { ++ value = (unsigned long) pDestructor; ++ left = 0; ++ right = zend_llist_dprot_counter-1; ++ mid = 0; ++ ++ while (left < right) { ++ mid = (right - left) >> 1; ++ mid += left; ++ if ((unsigned long)zend_llist_dprot_table[mid] == value) { ++ found = 1; ++ break; ++ } ++ if (value < (unsigned long)zend_llist_dprot_table[mid]) { ++ right = mid-1; ++ } else { ++ left = mid+1; ++ } ++ } ++ if ((unsigned long)zend_llist_dprot_table[left] == value) { ++ found = 1; ++ } ++ ++ if (!found) { ++ ++ if (zend_llist_dprot_counter >= zend_llist_dprot_curmax) { ++ zend_llist_dprot_curmax += 256; ++ zend_llist_dprot_table = (llist_dtor_func_t *) realloc(zend_llist_dprot_table, zend_llist_dprot_curmax * sizeof(llist_dtor_func_t)); ++ } ++ ++ if ((unsigned long)zend_llist_dprot_table[left] < value) { ++ memmove(zend_llist_dprot_table+left+2, zend_llist_dprot_table+left+1, (zend_llist_dprot_counter-left-1)*sizeof(llist_dtor_func_t)); ++ zend_llist_dprot_table[left+1] = pDestructor; ++ } else { ++ memmove(zend_llist_dprot_table+left+1, zend_llist_dprot_table+left, (zend_llist_dprot_counter-left)*sizeof(llist_dtor_func_t)); ++ zend_llist_dprot_table[left] = pDestructor; ++ } ++ ++ zend_llist_dprot_counter++; ++ } ++ } ++ ++ zend_llist_dprot_end_write(); ++} ++ ++static void zend_llist_check_destructor(llist_dtor_func_t pDestructor) ++{ ++ unsigned long value; ++ ++ if (pDestructor == NULL || pDestructor == ZVAL_PTR_DTOR) { ++ return; ++ } ++ ++ zend_llist_dprot_begin_read(); ++ ++ if (zend_llist_dprot_counter > 0) { ++ int left, right, mid; ++ zend_bool found = 0; ++ ++ value = (unsigned long) pDestructor; ++ left = 0; ++ right = zend_llist_dprot_counter-1; ++ ++ while (left < right) { ++ mid = (right - left) >> 1; ++ mid += left; ++ if ((unsigned long)zend_llist_dprot_table[mid] == value) { ++ found = 1; ++ break; ++ } ++ if (value < (unsigned long)zend_llist_dprot_table[mid]) { ++ right = mid-1; ++ } else { ++ left = mid+1; ++ } ++ } ++ if ((unsigned long)zend_llist_dprot_table[left] == value) { ++ found = 1; ++ } ++ ++ if (!found) { ++ zend_llist_dprot_end_read(); ++ ++ zend_suhosin_log(S_MEMORY, "possible memory corruption detected - unknown llist destructor"); ++ if (SUHOSIN_CONFIG(SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR) == 0) { ++ _exit(1); ++ } ++ return; ++ } ++ ++ } else { ++ zend_llist_dprot_end_read(); ++ ++ zend_suhosin_log(S_MEMORY, "possible memory corruption detected - unknown llist destructor"); ++ if (SUHOSIN_CONFIG(SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR) == 0) { ++ _exit(1); ++ } ++ return; ++ } ++ ++ zend_llist_dprot_end_read(); ++} ++#else ++#define zend_llist_add_destructor(pDestructor) do {} while(0) ++#define zend_llist_check_destructor(pDestructor) do {} while(0) ++#endif ++ + ZEND_API void zend_llist_init(zend_llist *l, size_t size, llist_dtor_func_t dtor, unsigned char persistent) + { + l->head = NULL; +@@ -30,6 +218,7 @@ + l->count = 0; + l->size = size; + l->dtor = dtor; ++ zend_llist_add_destructor(dtor); + l->persistent = persistent; + } + +@@ -81,6 +270,7 @@ + } else {\ + (l)->tail = (current)->prev;\ + }\ ++ zend_llist_check_destructor((l)->dtor); \ + if ((l)->dtor) {\ + (l)->dtor((current)->data);\ + }\ +@@ -108,6 +298,7 @@ + { + zend_llist_element *current=l->head, *next; + ++ zend_llist_check_destructor(l->dtor); + while (current) { + next = current->next; + if (l->dtor) { +@@ -133,6 +324,7 @@ + zend_llist_element *old_tail; + void *data; + ++ zend_llist_check_destructor((l)->dtor); + if ((old_tail = l->tail)) { + if (old_tail->prev) { + old_tail->prev->next = NULL; +diff -Nura php-5.3.9/Zend/zend_operators.c suhosin-patch-5.3.9-0.9.10/Zend/zend_operators.c +--- php-5.3.9/Zend/zend_operators.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/Zend/zend_operators.c 2012-01-11 19:29:07.000000000 +0100 +@@ -153,9 +153,14 @@ + case IS_STRING: + { + char *strval; ++ int strl; + + strval = Z_STRVAL_P(op); +- if ((Z_TYPE_P(op)=is_numeric_string(strval, Z_STRLEN_P(op), &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) { ++ strl = Z_STRLEN_P(op); ++#if SUHOSIN_PATCH ++ Z_STRLEN_P(op) = 0; ++#endif ++ if ((Z_TYPE_P(op)=is_numeric_string(strval, strl, &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) { + ZVAL_LONG(op, 0); + } + STR_FREE(strval); +@@ -187,7 +192,8 @@ + } else { \ + switch (Z_TYPE_P(op)) { \ + case IS_STRING: \ +- { \ ++ { \ ++ Z_STRLEN(holder) = 0; \ + if ((Z_TYPE(holder)=is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), 1)) == 0) { \ + ZVAL_LONG(&(holder), 0); \ + } \ +@@ -229,6 +235,7 @@ + Z_LVAL(holder) = zend_dval_to_lval(Z_DVAL_P(op)); \ + break; \ + case IS_STRING: \ ++ Z_STRLEN(holder) = 0; \ + Z_LVAL(holder) = strtol(Z_STRVAL_P(op), NULL, 10); \ + break; \ + case IS_ARRAY: \ +@@ -271,6 +278,7 @@ + Z_LVAL(holder) = (Z_DVAL_P(op) ? 1 : 0); \ + break; \ + case IS_STRING: \ ++ Z_STRLEN(holder) = 0; \ + if (Z_STRLEN_P(op) == 0 \ + || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) { \ + Z_LVAL(holder) = 0; \ +@@ -356,6 +364,9 @@ + { + char *strval = Z_STRVAL_P(op); + ++#if SUHOSIN_PATCH ++ Z_STRLEN_P(op) = 0; ++#endif + Z_LVAL_P(op) = strtol(strval, NULL, base); + STR_FREE(strval); + } +@@ -416,6 +427,9 @@ + { + char *strval = Z_STRVAL_P(op); + ++#if SUHOSIN_PATCH ++ Z_STRLEN_P(op) = 0; ++#endif + Z_DVAL_P(op) = zend_strtod(strval, NULL); + STR_FREE(strval); + } +@@ -502,8 +516,14 @@ + + if (Z_STRLEN_P(op) == 0 + || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) { ++#if SUHOSIN_PATCH ++ Z_STRLEN_P(op) = 0; ++#endif + Z_LVAL_P(op) = 0; + } else { ++#if SUHOSIN_PATCH ++ Z_STRLEN_P(op) = 0; ++#endif + Z_LVAL_P(op) = 1; + } + STR_FREE(strval); +@@ -617,6 +637,9 @@ + *entry = *op; + INIT_PZVAL(entry); + ++#if SUHOSIN_PATCH ++ Z_STRLEN_P(op) = 0; ++#endif + switch (type) { + case IS_ARRAY: + ALLOC_HASHTABLE(Z_ARRVAL_P(op)); +diff -Nura php-5.3.9/Zend/zend_variables.c suhosin-patch-5.3.9-0.9.10/Zend/zend_variables.c +--- php-5.3.9/Zend/zend_variables.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/Zend/zend_variables.c 2012-01-11 19:29:07.000000000 +0100 +@@ -34,6 +34,9 @@ + case IS_CONSTANT: + CHECK_ZVAL_STRING_REL(zvalue); + STR_FREE_REL(zvalue->value.str.val); ++#if SUHOSIN_PATCH ++ zvalue->value.str.len = 0; ++#endif + break; + case IS_ARRAY: + case IS_CONSTANT_ARRAY: { +@@ -78,6 +81,9 @@ + case IS_CONSTANT: + CHECK_ZVAL_STRING_REL(zvalue); + free(zvalue->value.str.val); ++#if SUHOSIN_PATCH ++ zvalue->value.str.len = 0; ++#endif + break; + case IS_ARRAY: + case IS_CONSTANT_ARRAY: +diff -Nura php-5.3.9/configure.in suhosin-patch-5.3.9-0.9.10/configure.in +--- php-5.3.9/configure.in 2012-01-10 12:21:57.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/configure.in 2012-01-11 19:29:07.000000000 +0100 +@@ -289,6 +289,7 @@ + sinclude(TSRM/threads.m4) + sinclude(TSRM/tsrm.m4) + ++sinclude(main/suhosin_patch.m4) + + divert(2) + +@@ -1406,7 +1407,7 @@ + php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \ + strlcat.c mergesort.c reentrancy.c php_variables.c php_ticks.c \ + network.c php_open_temporary_file.c php_logos.c \ +- output.c getopt.c) ++ output.c getopt.c suhosin_patch.c ) + + PHP_ADD_SOURCES(main/streams, streams.c cast.c memory.c filter.c \ + plain_wrapper.c userspace.c transports.c xp_socket.c mmap.c \ +@@ -1434,7 +1435,7 @@ + zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \ + zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \ + zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_gc.c \ +- zend_closures.c zend_float.c) ++ zend_closures.c zend_float.c zend_canary.c zend_alloc_canary.c ) + + if test -r "$abs_srcdir/Zend/zend_objects.c"; then + PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_default_classes.c) +diff -Nura php-5.3.9/ext/standard/dl.c suhosin-patch-5.3.9-0.9.10/ext/standard/dl.c +--- php-5.3.9/ext/standard/dl.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/ext/standard/dl.c 2012-01-11 19:29:07.000000000 +0100 +@@ -254,6 +254,23 @@ + return FAILURE; + } + } ++ ++#if SUHOSIN_PATCH ++ if (strncmp("suhosin", module_entry->name, sizeof("suhosin")-1) == 0) { ++ void *log_func; ++ /* sucessfully loaded suhosin extension, now check for logging function replacement */ ++ log_func = (void *) DL_FETCH_SYMBOL(handle, "suhosin_log"); ++ if (log_func == NULL) { ++ log_func = (void *) DL_FETCH_SYMBOL(handle, "_suhosin_log"); ++ } ++ if (log_func != NULL) { ++ zend_suhosin_log = log_func; ++ } else { ++ zend_suhosin_log(S_MISC, "could not replace logging function"); ++ } ++ } ++#endif ++ + return SUCCESS; + } + /* }}} */ +diff -Nura php-5.3.9/ext/standard/info.c suhosin-patch-5.3.9-0.9.10/ext/standard/info.c +--- php-5.3.9/ext/standard/info.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/ext/standard/info.c 2012-01-11 22:54:58.000000000 +0100 +@@ -878,6 +878,33 @@ + + php_info_print_table_end(); + ++ /* Suhosin Patch */ ++ php_info_print_box_start(0); ++ if (expose_php && !sapi_module.phpinfo_as_text) { ++ PUTS("\"Suhosin\n"); ++ } ++ PUTS("This server is protected with the Suhosin Patch "); ++ if (sapi_module.phpinfo_as_text) { ++ PUTS(SUHOSIN_PATCH_VERSION); ++ } else { ++ zend_html_puts(SUHOSIN_PATCH_VERSION, strlen(SUHOSIN_PATCH_VERSION) TSRMLS_CC); ++ } ++ PUTS(!sapi_module.phpinfo_as_text?"
":"\n"); ++ if (sapi_module.phpinfo_as_text) { ++ PUTS("Copyright (c) 2006-2007 Hardened-PHP Project\n"); ++ PUTS("Copyright (c) 2007-2012 SektionEins GmbH\n"); ++ } else { ++ PUTS("Copyright (c) 2006-2007 Hardened-PHP Project\n"); ++ PUTS("Copyright (c) 2007-2012 SektionEins GmbH\n"); ++ } ++ php_info_print_box_end(); ++ + /* Zend Engine */ + php_info_print_box_start(0); + if (expose_php && !sapi_module.phpinfo_as_text) { +diff -Nura php-5.3.9/ext/standard/syslog.c suhosin-patch-5.3.9-0.9.10/ext/standard/syslog.c +--- php-5.3.9/ext/standard/syslog.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/ext/standard/syslog.c 2012-01-11 19:29:07.000000000 +0100 +@@ -42,6 +42,7 @@ + */ + PHP_MINIT_FUNCTION(syslog) + { ++#if !SUHOSIN_PATCH + /* error levels */ + REGISTER_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */ + REGISTER_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */ +@@ -97,6 +98,7 @@ + /* AIX doesn't have LOG_PERROR */ + REGISTER_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/ + #endif ++#endif + BG(syslog_device)=NULL; + + return SUCCESS; +diff -Nura php-5.3.9/main/fopen_wrappers.c suhosin-patch-5.3.9-0.9.10/main/fopen_wrappers.c +--- php-5.3.9/main/fopen_wrappers.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/main/fopen_wrappers.c 2012-01-11 19:29:07.000000000 +0100 +@@ -85,13 +85,8 @@ + PHPAPI ZEND_INI_MH(OnUpdateBaseDir) + { + char **p, *pathbuf, *ptr, *end; +-#ifndef ZTS +- char *base = (char *) mh_arg2; +-#else +- char *base = (char *) ts_resource(*((int *) mh_arg2)); +-#endif + +- p = (char **) (base + (size_t) mh_arg1); ++ p = &PG(open_basedir); + + if (stage == PHP_INI_STAGE_STARTUP || stage == PHP_INI_STAGE_SHUTDOWN || stage == PHP_INI_STAGE_ACTIVATE || stage == PHP_INI_STAGE_DEACTIVATE) { + /* We're in a PHP_INI_SYSTEM context, no restrictions */ +diff -Nura php-5.3.9/main/main.c suhosin-patch-5.3.9-0.9.10/main/main.c +--- php-5.3.9/main/main.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/main/main.c 2012-01-11 19:29:07.000000000 +0100 +@@ -91,6 +91,9 @@ + + #include "SAPI.h" + #include "rfc1867.h" ++#if SUHOSIN_PATCH ++#include "suhosin_globals.h" ++#endif + + #if HAVE_MMAP + # if HAVE_UNISTD_H +@@ -504,7 +507,7 @@ + STD_PHP_INI_ENTRY("extension_dir", PHP_EXTENSION_DIR, PHP_INI_SYSTEM, OnUpdateStringUnempty, extension_dir, php_core_globals, core_globals) + STD_PHP_INI_ENTRY("include_path", PHP_INCLUDE_PATH, PHP_INI_ALL, OnUpdateStringUnempty, include_path, php_core_globals, core_globals) + PHP_INI_ENTRY("max_execution_time", "30", PHP_INI_ALL, OnUpdateTimeout) +- STD_PHP_INI_ENTRY("open_basedir", NULL, PHP_INI_ALL, OnUpdateBaseDir, open_basedir, php_core_globals, core_globals) ++ PHP_INI_ENTRY("open_basedir", NULL, PHP_INI_ALL, OnUpdateBaseDir) + STD_PHP_INI_ENTRY("safe_mode_exec_dir", PHP_SAFE_MODE_EXEC_DIR, PHP_INI_SYSTEM, OnUpdateString, safe_mode_exec_dir, php_core_globals, core_globals) + + STD_PHP_INI_BOOLEAN("file_uploads", "1", PHP_INI_SYSTEM, OnUpdateBool, file_uploads, php_core_globals, core_globals) +@@ -1810,6 +1813,10 @@ + } + #endif + ++#if SUHOSIN_PATCH ++PHPAPI void suhosin_startup(); ++#endif ++ + /* {{{ php_module_startup + */ + int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint num_additional_modules) +@@ -1858,6 +1865,10 @@ + php_win32_init_rng_lock(); + #endif + ++#if SUHOSIN_PATCH ++ suhosin_startup(); ++#endif ++ + module_shutdown = 0; + module_startup = 1; + sapi_initialize_empty_request(TSRMLS_C); +@@ -1980,7 +1991,11 @@ + REGISTER_MAIN_STRINGL_CONSTANT("PHP_CONFIG_FILE_SCAN_DIR", PHP_CONFIG_FILE_SCAN_DIR, sizeof(PHP_CONFIG_FILE_SCAN_DIR)-1, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_STRINGL_CONSTANT("PHP_SHLIB_SUFFIX", PHP_SHLIB_SUFFIX, sizeof(PHP_SHLIB_SUFFIX)-1, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_STRINGL_CONSTANT("PHP_EOL", PHP_EOL, sizeof(PHP_EOL)-1, CONST_PERSISTENT | CONST_CS); +- REGISTER_MAIN_LONG_CONSTANT("PHP_MAXPATHLEN", MAXPATHLEN, CONST_PERSISTENT | CONST_CS); ++#if SUHOSIN_PATCH ++ REGISTER_MAIN_LONG_CONSTANT("SUHOSIN_PATCH", 1, CONST_PERSISTENT | CONST_CS); ++ REGISTER_MAIN_STRINGL_CONSTANT("SUHOSIN_PATCH_VERSION", SUHOSIN_PATCH_VERSION, sizeof(SUHOSIN_PATCH_VERSION)-1, CONST_PERSISTENT | CONST_CS); ++#endif ++ REGISTER_MAIN_LONG_CONSTANT("PHP_MAXPATHLEN", MAXPATHLEN, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_LONG_CONSTANT("PHP_INT_MAX", LONG_MAX, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_LONG_CONSTANT("PHP_INT_SIZE", sizeof(long), CONST_PERSISTENT | CONST_CS); + #ifdef ZEND_MULTIBYTE +diff -Nura php-5.3.9/main/php.h suhosin-patch-5.3.9-0.9.10/main/php.h +--- php-5.3.9/main/php.h 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/main/php.h 2012-01-11 19:29:07.000000000 +0100 +@@ -454,6 +454,10 @@ + #endif + #endif /* !XtOffsetOf */ + ++#if SUHOSIN_PATCH ++#include "suhosin_patch.h" ++#endif ++ + #endif + + /* +diff -Nura php-5.3.9/main/php_config.h.in suhosin-patch-5.3.9-0.9.10/main/php_config.h.in +--- php-5.3.9/main/php_config.h.in 2012-01-10 14:37:07.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/main/php_config.h.in 2012-01-11 19:29:07.000000000 +0100 +@@ -405,6 +405,9 @@ + /* Define to 1 if you have the `alphasort' function. */ + #undef HAVE_ALPHASORT + ++/* Suhosin-Patch for PHP */ ++#undef SUHOSIN_PATCH ++ + /* Whether you have AOLserver */ + #undef HAVE_AOLSERVER + +--- php-5.3.21/main/php_logos.c~ 2013-01-22 23:40:21.000000000 +0200 ++++ php-5.3.21/main/php_logos.c 2013-01-22 23:41:14.071814355 +0200 +@@ -50,6 +50,10 @@ + return zend_hash_del(&phpinfo_logo_hash, logo_string, strlen(logo_string)); + } + ++#if SUHOSIN_PATCH ++#include "suhosin_logo.h" ++#endif ++ + int php_init_info_logos(void) + { + if(zend_hash_init(&phpinfo_logo_hash, 0, NULL, NULL, 1)==FAILURE) +@@ -64,6 +64,10 @@ + php_register_info_logo(ZEND_LOGO_GUID , "image/gif", zend_logo , sizeof(zend_logo)); + php_register_info_logo(PLD_LOGO_GUID , "image/png", pld_logo , sizeof(pld_logo)); + ++#if SUHOSIN_PATCH ++ php_register_info_logo(SUHOSIN_LOGO_GUID, "image/jpeg", suhosin_logo , sizeof(suhosin_logo)); ++#endif ++ + return SUCCESS; + } + +diff -Nura php-5.3.9/main/snprintf.c suhosin-patch-5.3.9-0.9.10/main/snprintf.c +--- php-5.3.9/main/snprintf.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/main/snprintf.c 2012-01-11 19:29:07.000000000 +0100 +@@ -782,6 +782,10 @@ + */ + switch (*fmt) { + case 'Z': ++#if SUHOSIN_PATCH ++ zend_suhosin_log(S_MISC, "'Z' specifier within format string"); ++ goto skip_output; ++#else + zvp = (zval*) va_arg(ap, zval*); + zend_make_printable_zval(zvp, &zcopy, &free_zcopy); + if (free_zcopy) { +@@ -792,6 +796,7 @@ + if (adjust_precision && precision < s_len) { + s_len = precision; + } ++#endif + break; + case 'u': + switch(modifier) { +@@ -1093,7 +1098,11 @@ + + + case 'n': ++#if SUHOSIN_PATCH ++ zend_suhosin_log(S_MISC, "'n' specifier within format string"); ++#else + *(va_arg(ap, int *)) = cc; ++#endif + goto skip_output; + + /* +diff -Nura php-5.3.9/main/spprintf.c suhosin-patch-5.3.9-0.9.10/main/spprintf.c +--- php-5.3.9/main/spprintf.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/main/spprintf.c 2012-01-11 19:29:08.000000000 +0100 +@@ -390,6 +390,10 @@ + */ + switch (*fmt) { + case 'Z': ++#if SUHOSIN_PATCH ++ zend_suhosin_log(S_MISC, "'Z' specifier within format string"); ++ goto skip_output; ++#else + zvp = (zval*) va_arg(ap, zval*); + zend_make_printable_zval(zvp, &zcopy, &free_zcopy); + if (free_zcopy) { +@@ -400,6 +404,7 @@ + if (adjust_precision && precision < s_len) { + s_len = precision; + } ++#endif + break; + case 'u': + switch(modifier) { +@@ -700,7 +705,11 @@ + + + case 'n': ++#if SUHOSIN_PATCH ++ zend_suhosin_log(S_MISC, "'n' specifier within format string"); ++#else + *(va_arg(ap, int *)) = xbuf->len; ++#endif + goto skip_output; + + /* +diff -Nura php-5.3.9/main/suhosin_globals.h suhosin-patch-5.3.9-0.9.10/main/suhosin_globals.h +--- php-5.3.9/main/suhosin_globals.h 1970-01-01 01:00:00.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/main/suhosin_globals.h 2012-01-11 19:29:08.000000000 +0100 +@@ -0,0 +1,61 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | Suhosin-Patch for PHP | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 2004-2009 Stefan Esser | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.txt. | ++ | If you did not receive a copy of the PHP license and are unable to | ++ | obtain it through the world-wide-web, please send a note to | ++ | license@php.net so we can mail you a copy immediately. | ++ +----------------------------------------------------------------------+ ++ | Author: Stefan Esser | ++ +----------------------------------------------------------------------+ ++ */ ++ ++#ifndef SUHOSIN_GLOBALS_H ++#define SUHOSIN_GLOBALS_H ++ ++typedef struct _suhosin_patch_globals suhosin_patch_globals_struct; ++ ++#ifdef ZTS ++# define SPG(v) TSRMG(suhosin_patch_globals_id, suhosin_patch_globals_struct *, v) ++extern int suhosin_patch_globals_id; ++#else ++# define SPG(v) (suhosin_patch_globals.v) ++extern struct _suhosin_patch_globals suhosin_patch_globals; ++#endif ++ ++ ++struct _suhosin_patch_globals { ++ /* logging */ ++ int log_syslog; ++ int log_syslog_facility; ++ int log_syslog_priority; ++ int log_sapi; ++ int log_script; ++ int log_phpscript; ++ char *log_scriptname; ++ char *log_phpscriptname; ++ zend_bool log_phpscript_is_safe; ++ zend_bool log_use_x_forwarded_for; ++ ++ /* memory manager canary protection */ ++ unsigned int canary_1; ++ unsigned int canary_2; ++ unsigned int canary_3; ++ unsigned int dummy; ++}; ++ ++ ++#endif /* SUHOSIN_GLOBALS_H */ ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * End: ++ */ +diff -Nura php-5.3.9/main/suhosin_logo.h suhosin-patch-5.3.9-0.9.10/main/suhosin_logo.h +--- php-5.3.9/main/suhosin_logo.h 1970-01-01 01:00:00.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/main/suhosin_logo.h 2012-01-11 19:29:08.000000000 +0100 +@@ -0,0 +1,178 @@ ++static unsigned char suhosin_logo[] = ++ "\xff\xd8\xff\xe0\x00\x10\x4a\x46\x49\x46\x00\x01\x01\x01\x00\x48" ++ "\x00\x48\x00\x00\xff\xe1\x00\x16\x45\x78\x69\x66\x00\x00\x4d\x4d" ++ "\x00\x2a\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\xff\xdb\x00\x43" ++ "\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" ++ "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" ++ "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" ++ "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" ++ "\x01\xff\xc0\x00\x0b\x08\x00\x27\x00\x71\x01\x01\x22\x00\xff\xc4" ++ "\x00\x1e\x00\x00\x02\x02\x02\x03\x01\x01\x00\x00\x00\x00\x00\x00" ++ "\x00\x00\x00\x00\x09\x06\x08\x05\x07\x02\x03\x0a\x01\x04\xff\xc4" ++ "\x00\x32\x10\x00\x01\x04\x03\x00\x02\x00\x05\x01\x05\x09\x01\x00" ++ "\x00\x00\x00\x05\x02\x03\x04\x06\x01\x07\x08\x00\x09\x11\x12\x13" ++ "\x14\x21\x15\x0a\x16\x31\x56\x96\x17\x18\x19\x23\x32\x41\x58\x98" ++ "\xd4\xd6\xff\xda\x00\x08\x01\x01\x00\x00\x3f\x00\xf4\xc1\xe1\xe5" ++ "\x69\xe9\x3e\xb9\xd1\x7c\x8a\x2e\x9d\x66\xe8\x3b\x29\x4d\x7f\x46" ++ "\xba\x58\x55\x54\x8d\xb1\x5f\xaa\xd9\x8d\x51\x2b\xb6\x27\x5a\x69" ++ "\xd1\x43\xaf\x16\x1a\xf0\xb2\xb1\xe9\x6d\x9f\xc2\xa4\x36\x18\xb5" ++ "\x85\x10\x41\xbe\xfc\x09\xac\x49\x29\x11\xd4\x32\x97\xec\x08\x13" ++ "\xc1\x2d\x20\xc3\x59\xeb\x26\x05\xd8\x6b\x76\x31\x43\x8f\x57\xcf" ++ "\x84\x9f\x14\xa8\x53\x81\x0b\xc3\x64\x80\xa3\x02\x0a\x41\x75\xf8" ++ "\x44\x85\x93\x81\x22\x3c\xd8\x13\xe1\xbe\xf4\x59\x91\x1f\x6a\x44" ++ "\x77\x5c\x69\xc4\x2f\x39\x5f\x0f\x2a\x8d\xeb\xba\xf8\xc3\x56\x6c" ++ "\x3b\x36\xa7\xda\xbd\x4d\xa1\xb5\x4e\xc6\xa7\xa4\x3a\xec\x15\x2d" ++ "\xa5\xb3\xea\x5a\xdc\xac\x46\xac\x01\x60\xd8\x43\xc8\x8e\x8b\xb1" ++ "\x40\x4c\x95\x8b\x34\x41\x28\x52\x91\x28\x43\xd3\xa3\xb6\xa7\x55" ++ "\x15\xe7\x5a\x96\xcb\xf1\xda\xe5\x55\xee\xfe\x1e\xbd\xd9\x41\xd3" ++ "\x28\xfd\x97\xca\x57\x2b\x85\x9c\xa4\x30\x95\xaa\xa5\x57\xa2\x35" ++ "\x15\x86\xcb\x61\x34\x41\xe4\xc7\x80\x20\x18\x21\x17\x09\x85\x0b" ++ "\x14\x9d\x21\x68\x62\x1c\x08\x11\x64\x4b\x92\xf2\xd2\xd3\x2d\x2d" ++ "\x6a\xc2\x73\x6b\x3c\x3c\x8b\x9e\xbc\x52\xaa\xa4\xab\x81\x6c\xf6" ++ "\xfa\xbd\x70\xc5\xc6\x7b\xc2\xaa\x22\x4f\x58\x04\x87\x25\x6a\x27" ++ "\x1d\xa4\x3d\x20\x75\x72\x01\x09\x71\xe5\x1c\x9e\xc3\x2e\x36\xf3" ++ "\xd0\xc6\x35\x2a\x43\x4d\x2d\x0e\x2d\xb4\xa1\x49\xce\x65\x1e\x52" ++ "\x9e\xa1\xf6\x09\xcc\xdc\x63\x66\xa8\x01\xe9\x3b\x0d\xd7\x5a\x85" ++ "\xbb\xc5\x65\xc0\x7b\x2e\x46\xa9\xd9\x56\x1d\x4c\x92\x72\x26\x4e" ++ "\x86\xd5\x68\xae\xc4\xaa\x55\xce\xd7\x83\x59\xb3\x81\xee\xce\x74" ++ "\x39\x39\x31\x9f\x8a\x25\xe8\xa5\xa5\xe5\x81\xf2\x11\x23\xcb\xa1" ++ "\x1e\x43\x12\xe3\xb1\x2a\x2b\xcd\xc8\x8d\x25\x96\xa4\x47\x7d\x95" ++ "\xa5\xc6\x9f\x61\xe4\x25\xc6\x5e\x69\xc4\xe7\x29\x5b\x6e\xb6\xa4" ++ "\xad\x0b\x4e\x72\x95\x25\x58\x56\x33\x9c\x67\xce\xef\x0f\x17\xbf" ++ "\x4c\x7b\x2d\xe6\xfe\x76\x35\x27\x5a\x07\x97\x67\xe8\xae\x8d\x71" ++ "\x0f\xb2\x13\x99\xb9\xbc\x14\xad\xb3\xb7\xe6\x11\x6f\xe0\xda\x58" ++ "\xb1\x08\xac\xa6\x6c\x2d\x7f\x05\xb7\x56\xd2\xe6\xcf\xbb\x4d\x0c" ++ "\xe3\x50\xb2\xec\x91\xf0\x4a\xb8\xd6\x22\xb8\xa7\xf6\x67\xaf\xcf" ++ "\x63\x7e\xd7\xe7\x42\xd8\xbd\xc3\x71\xa1\xf2\x7e\x9b\xa8\x97\x83" ++ "\x6e\xd1\xdc\x4b\x06\x11\x2d\xae\x26\x61\x98\x72\x10\xf4\x42\x5d" ++ "\x20\x4a\xa3\x73\xd7\xf2\xcd\x3c\x48\x32\xe4\x03\x9f\x80\x37\x08" ++ "\x36\x11\xd0\xcb\x97\x6c\x08\xed\x6d\x33\x24\xa2\x1b\xb4\x77\xdf" ++ "\x61\x5d\x5f\xc1\x43\xc2\x82\xeb\x0f\x5d\x84\x08\x68\xaa\xa4\x01" ++ "\xe1\x19\xdf\xbc\x31\x65\xfe\xd1\xf5\x7d\x7a\xb2\x2a\x33\x50\x21" ++ "\x2a\x56\x9d\xb1\x81\xab\xdb\x35\x78\x30\x83\xd9\x89\x1d\x31\xac" ++ "\x96\x14\x07\x61\xbc\x20\x68\x42\x85\x33\x19\xac\xbe\xdb\x34\x56" ++ "\xf1\xd5\xfd\x29\xa9\x28\xdb\xcb\x4c\x5a\x23\xdc\xf5\x96\xc5\x10" ++ "\xa3\x35\x5b\x14\x68\xd3\x61\x62\x64\x76\x26\xcb\x17\x3e\x34\x98" ++ "\x04\xa3\xc4\x20\x38\x90\x92\xe3\xc8\x07\x2c\x36\x74\x66\x26\x0e" ++ "\x29\x02\x64\x29\x2d\x21\xe6\x16\x9c\x6b\xce\xa3\x89\xd9\x4f\xd3" ++ "\xc4\xbd\xc5\x87\x79\x9c\x65\xf6\x39\x45\x60\xe8\xce\x9e\xab\x6d" ++ "\x13\x15\x22\xe1\x5e\x4b\x38\x42\xc4\x1e\xd5\x76\xe0\xc5\xeb\x85" ++ "\x07\x2d\x0f\xb8\xb6\xa6\xd6\x6d\x71\x0d\xa2\x43\x4c\x25\xea\xfa" ++ "\xa1\xae\x4c\xe4\x7d\xbd\x76\xa9\xfb\x06\xc2\x83\x42\xeb\xad\xe7" ++ "\xe9\x5f\x68\x6f\xba\xfb\x2f\x07\xce\xb8\x13\xc1\x9b\xeb\xb0\x76" ++ "\x45\x57\x28\x7b\xea\xbe\x0f\xf4\x30\x7b\xa0\xed\xe4\x22\x93\x21" ++ "\xfc\xbc\xe0\xb9\x75\xc1\x4f\xfc\xef\xb6\xfa\xa1\xfc\x64\xa1\x4a" ++ "\x82\xc7\x33\xad\x75\xed\x82\xbd\x3d\xdb\xf7\xa8\xbe\x5e\xbb\x36" ++ "\x62\x04\x9a\x2e\xc5\xd9\x9e\x9c\x3a\x0b\x98\x0b\x57\xac\xf1\x24" ++ "\x62\x58\x83\x15\x5b\xa6\xf2\xda\x34\x70\x03\xce\x0f\x93\x1b\x12" ++ "\xc7\xce\x54\x87\x33\x15\xd6\x53\x25\x1f\x2a\x90\x87\x12\xe3\x78" ++ "\xef\x55\x77\x4d\x4a\xd8\x7e\xef\xd2\xfd\xd1\xaf\x3a\xaf\x55\xdb" ++ "\x6a\x2d\x3d\x42\xac\x51\x79\xee\x91\xab\xe1\x05\x2d\x3c\x80\xa2" ++ "\x43\xad\x22\x2e\xd5\x33\x13\xa4\x9e\x00\xe0\x04\x10\x84\xc8\xf2" ++ "\x19\x30\x92\x1f\xaa\xc3\x28\xc9\x76\x30\x3f\xe9\x10\x61\x5e\x79" ++ "\xd5\xf7\xdf\xd0\x54\xdb\xae\xb6\xae\xfa\xe8\xa3\x57\xe0\x6c\x2d" ++ "\xf7\xbd\x49\xd6\x6e\x76\x79\xcc\x54\x0c\x5f\xff\x00\xbb\x06\x98" ++ "\xa6\x9e\x89\x61\xb4\x6f\xc3\xe3\x6a\xc2\x4f\x59\x03\xc9\x80\x2c" ++ "\x59\x24\x44\x70\x38\xd5\x96\x6a\x9e\x8b\x81\x64\xe5\xbc\xa0\x3c" ++ "\x33\xaf\x17\x9d\xff\x00\x71\x1a\xd1\x3a\x80\x66\xb3\xd9\x31\x77" ++ "\x0d\x12\xbd\xae\x29\xb5\x6a\xd6\xcf\x8d\x68\x87\x75\xcd\xe8\x65" ++ "\x5a\xbe\x3c\x04\x7b\x34\xdb\x54\x19\xa4\x63\x9c\x2a\x5d\x23\xbe" ++ "\xf4\xb1\x1c\x4d\x90\xec\x92\x2f\x49\x71\xf7\x14\xf2\x97\x9f\x15" ++ "\x57\xed\x13\x21\x2a\xf5\x33\xd1\x2a\x52\x52\xac\xb7\x62\xd1\xcb" ++ "\x46\x73\x8c\x67\x28\x56\x77\x86\xbf\x6f\x2a\x4e\x73\xfe\x95\x65" ++ "\x0b\x5a\x3e\x38\xfc\xfc\xaa\x56\x3f\x86\x73\xe3\xb9\x4a\x52\x84" ++ "\xa5\x08\x4e\x12\x94\x27\x09\x4a\x53\x8c\x61\x29\x4a\x71\xf0\x4a" ++ "\x53\x8c\x7e\x31\x8c\x63\x18\xc6\x31\x8f\xc6\x31\xf8\xc7\x9f\x7c" ++ "\xd5\xbb\xae\x5e\xe2\x1f\xab\x6e\x24\x34\x00\x8a\x25\x83\x70\x40" ++ "\x1c\xcc\xda\x45\x7f\x66\x4e\x30\x2e\x94\x7e\x74\x49\xf0\xe4\x4e" ++ "\x06\x5c\xa8\x2f\x89\x21\x2e\x98\x0e\xd9\x21\xc2\x0b\x21\x0f\xc4" ++ "\x16\x6e\x48\xd9\xe4\xe3\x4a\x19\x1e\x64\x67\x54\xff\x00\x3a\x6d" ++ "\x4f\x62\xb5\x00\x4a\xaa\x51\xfd\x2d\xe8\x0e\x6c\xaf\xc6\x7d\x6d" ++ "\xc8\x88\xc7\x67\xea\x8a\x58\x02\x73\xe3\x65\x4d\xc9\x24\xc0\x3d" ++ "\x57\xa3\x2e\x53\x16\x99\x4f\xe5\xe7\x19\x97\x3e\x3b\xcf\xc9\x4b" ++ "\x99\x7f\x33\x25\xa5\xdf\xba\x77\x2b\xd3\x3e\xc2\x7b\x8b\x94\x07" ++ "\xe9\x52\x5b\x43\x87\x34\x14\x86\x37\xcf\x41\x6b\x8e\x6a\xa5\x22" ++ "\xab\xdb\x96\xa2\xcf\x46\xd8\x9b\x45\x93\xef\xd6\xdf\x3e\x99\x9c" ++ "\x7e\x29\x10\x6b\x6c\xa2\xb8\x43\x05\x09\x44\x70\x8c\xb8\xaa\x54" ++ "\x7c\x30\x36\x5e\x1c\x5e\x5b\x9f\x6c\x0d\x81\xee\xa0\x93\x8d\x67" ++ "\x55\xf3\x87\xaf\xaa\x6b\x58\xf9\xbe\xb2\x36\x07\x42\x6e\xbd\x96" ++ "\xe3\x9f\x1f\x8f\xc9\xf4\x9d\xae\x6a\x7d\x4c\x96\xbe\x5f\xc7\xcd" ++ "\xf3\xb2\xf7\xcd\xf0\xcf\xc3\xe4\xf8\xfe\x37\x4f\x1c\x4d\xf6\x40" ++ "\xf1\x6b\x7c\x4e\xe0\xa6\x71\xad\x56\xa7\x1c\x5c\x15\x6b\xfc\xf3" ++ "\x01\x5d\xac\xf1\x75\x9a\x72\x6b\xaa\x28\xc5\x88\x6d\xfb\x33\x85" ++ "\xe0\x4e\x61\xab\xeb\x31\x2c\x71\x08\x73\x11\x3b\xfc\xb5\xc0\x96" ++ "\xcc\x87\x24\x44\xb5\x9b\x9e\xb3\x71\xba\xe9\xed\xb1\x4e\xd7\x76" ++ "\x6c\xd2\xb6\x05\xb7\x5a\xde\xeb\x34\x5b\x96\x16\xfb\x59\xa9\x5c" ++ "\x4f\x55\xca\x8a\xac\x59\xb0\xe4\x54\x39\x25\xbc\x81\x37\x2a\x09" ++ "\x5f\x9e\x3b\x6b\x7d\x1f\x69\xf3\x34\x85\x39\x84\xa7\x28\x0b\xd3" ++ "\xfd\xfb\x4b\x7a\xea\xe7\xd2\x3c\xd3\xda\x15\x68\xbc\x73\xd3\x22" ++ "\x6f\xd7\x72\x5b\x2b\x66\xee\xa8\x0d\x54\xe8\x5b\xf9\x92\x96\x92" ++ "\x93\xea\x97\x4a\xc7\x43\x10\x46\x35\xc5\xc0\x60\x8a\xe4\xc1\xb5" ++ "\x36\xc6\xae\xed\xf7\x70\xa5\x86\x99\x3d\x91\xf8\xfd\x4e\x53\xeb" ++ "\xbb\xbd\x6d\xec\x8f\xd7\x89\x3d\x31\x7f\xd7\x78\xba\x50\xbb\x74" ++ "\x9d\xf6\xac\x4e\xb9\x03\x9c\x79\xd5\xe1\xbd\x17\x68\xd9\x13\x0b" ++ "\x45\x75\x88\x00\x1d\x1f\xae\x73\x6a\x1d\x5c\x6e\x44\x9f\xa6\xfa" ++ "\x4e\xd8\x25\x8b\xc0\xbc\xb2\x99\xe3\x17\x24\xb3\x23\xe2\x48\x8b" ++ "\xfa\x22\xe7\x7e\x8f\xe6\x3f\x5f\x55\x0d\x75\xd3\x51\x0b\xd7\xed" ++ "\xd3\x6f\x97\x3b\x85\x42\x80\x7e\x5f\xdc\x1b\xd6\xba\xee\xc4\x80" ++ "\xce\x06\xa9\x15\x8c\x97\x5f\x40\x69\xb2\x4d\xc5\xb2\x5c\x1e\x01" ++ "\x87\x7e\xe0\x36\x6d\x78\x80\x4e\x3c\x02\xec\x90\x1d\x11\x81\x74" ++ "\xa5\x8b\xa4\xa0\x56\x06\xd5\x79\x72\x85\x57\x3b\xb2\x2e\xae\x90" ++ "\x18\x8d\x91\xb2\x0e\x44\x19\xaa\xb4\xcc\x08\xed\x46\xfa\xd7\x2b" ++ "\x78\x58\x72\x5d\xbb\x5e\x49\xe7\xee\xf3\x8a\x9d\x22\xa4\x19\xc8" ++ "\xe7\x08\xc3\x90\x9b\x35\x9a\xa4\x25\x8c\x4b\x9b\xa7\xf8\xbf\x81" ++ "\xf5\xdf\x22\x66\xf1\x7e\x9f\x66\x3d\xbb\xfa\x73\x73\x4d\xfd\x67" ++ "\x7b\xf4\xce\xc3\x62\x2e\x6f\xbb\x0c\xa2\xdc\x69\xfc\x8a\x17\x0e" ++ "\x3a\x9e\x83\x46\xd7\xe3\x5e\x65\x86\xc0\x51\x00\xbb\x91\xe3\xe1" ++ "\xc1\x16\xc4\xe9\x65\x5c\x14\x3e\x44\x6a\x6b\xd1\x1e\xb0\x36\xdd" ++ "\x0b\x7d\x8a\xeb\xaf\x58\x5b\x64\x3f\x38\xed\x52\x76\xe8\x46\xf7" ++ "\x86\x84\xb3\x93\xb1\x0b\xe5\xfd\xfd\x0d\xe9\x6d\xe4\xf1\x1b\x1d" ++ "\x56\xb4\x34\xe4\x6a\xf5\xa4\x9c\x2c\xc9\x64\x94\xc1\xf5\x79\x6d" ++ "\x12\x96\xf3\x47\xc5\x48\xa8\xdb\xd8\x95\x64\x29\xcf\xf6\x88\xf1" ++ "\x95\x7a\x98\xe8\xbc\x27\x19\xce\x73\x61\xd1\xb8\xc6\x31\x8c\xe7" ++ "\x39\xce\x77\x9e\xbc\xc6\x31\x8c\x63\xf3\x9c\xe7\x39\xc6\x31\x8f" ++ "\xf7\xce\x7e\x1e\x3b\x7f\x0f\x0f\x0f\x13\x57\xb9\x0a\xe1\x0b\x64" ++ "\x5f\x58\x40\xc6\xc7\x7a\x4b\xf2\x3d\xbc\x71\xf4\xa7\xd2\xca\x14" ++ "\xe2\x98\x1a\x30\x1e\xe0\x26\x5a\x6a\xf0\x9c\x67\x38\x66\x00\xb8" ++ "\x72\xe6\xbe\xac\xfe\x12\xd3\x0b\x56\x73\x8c\x63\xc7\x2b\xe1\xe2" ++ "\xe8\xdd\x7b\xff\x00\xd8\xe5\x23\x6c\xce\xa8\x69\xcf\x5e\x3a\xef" ++ "\x77\xea\xe5\xab\x0e\x82\xdb\xd9\xed\x7a\x9e\xb8\x6d\x51\x32\xdb" ++ "\x79\xc3\x36\x9a\x2d\xa3\x50\x39\x65\x0a\x63\x0e\xe5\xd4\x39\x12" ++ "\xbf\x8b\x98\xa4\xa1\x2d\xad\xb3\xcf\x65\x6a\x43\x78\xb3\x3b\x07" ++ "\xd8\xd5\xea\xae\x76\xad\x6f\xf5\xff\x00\xca\x93\xab\x96\xb0\x64" ++ "\xeb\xd6\x4a\xd5\x87\xba\xec\x24\x60\x97\x06\x76\x03\xe3\x4c\x07" ++ "\x29\x11\x8e\x34\x25\x02\x64\x29\xf0\x25\x48\x85\x3a\x33\x8b\x7a" ++ "\x3c\x86\x1e\x75\xa5\x61\xc6\x97\x9f\x8d\x25\xf5\xc9\xcd\xde\xc9" ++ "\x7d\x77\xf2\xc8\x7e\x70\xaf\x73\x5f\x2d\xec\xa2\x51\x2d\x96\xfb" ++ "\x89\xad\x80\x57\xb2\x36\x1d\x7d\x83\x45\xac\xf3\xdb\xcc\x6c\x31" ++ "\x4f\xcf\x30\x58\xd0\x12\x28\x90\x50\x42\x86\xfb\x48\x16\x3c\xc5" ++ "\x9c\xf8\xe7\xcc\x29\x88\xb3\x4a\x4b\x4e\x6c\xbc\xdb\xc7\xbb\xe9" ++ "\xb6\xa0\x8b\x11\xa1\x7d\x73\xd7\xe9\xbf\x7e\xc2\x6c\x10\x8d\xee" ++ "\x9d\xef\x63\x3a\xe0\xf5\xbe\x8c\x3e\xa1\xc7\xc5\xd1\x00\x44\x1e" ++ "\xf3\x51\xf2\xe2\xb0\xe3\xb5\x13\x7f\x32\xf1\x8c\xa6\x22\xfe\x1f" ++ "\x49\x4d\xbb\xcf\x3a\x5d\xed\x4c\xd2\xfc\x85\xed\x23\xd6\xc7\x50" ++ "\xb6\x5b\x3a\x16\x83\xb8\x6f\xfd\x32\x3f\xaa\x36\x34\xbb\xf5\x96" ++ "\xa9\xab\xcf\x9f\x8f\xac\xc3\xca\xd5\x8b\xd8\x48\x9e\x79\xaa\x30" ++ "\x87\xca\x58\x4d\x59\x96\xb9\x4f\xc5\x1b\x1c\xd2\xda\x5b\xe6\x57" ++ "\x29\xa1\x28\x7a\x2b\x5b\xff\x00\x12\x2f\x5e\x3f\xf3\xbb\x8e\x7f" ++ "\xec\xc6\x98\xff\x00\xed\x3c\xa6\xdd\xa9\xdc\x7e\xa0\xf7\xd6\x99" ++ "\x31\xa2\xf7\xaf\x6b\xe9\x82\x74\x4b\x3d\x8f\x5e\x58\x0b\x33\xab" ++ "\xef\xc3\xaf\x84\x64\xb9\xae\xb6\x25\x5f\x62\x8f\x1c\xe3\xf4\x51" ++ "\xb7\x96\xe3\x0e\x30\x42\xa9\x18\x39\xbf\x9e\x2a\x1f\x74\x19\x02" ++ "\x2d\x43\x93\x06\x63\xb1\xa7\x47\x6a\xfa\x9b\x6c\xeb\xbd\xe9\xae" ++ "\x6a\x7b\x6f\x53\x5a\x60\x5d\xb5\xcd\xe8\x67\xeb\x35\x3b\x48\xc6" ++ "\xa6\xb3\x04\xc8\xdf\xb8\x7e\x26\x64\xb0\xc9\x18\xb0\xa7\x33\xf2" ++ "\x4a\x8b\x22\x3b\x8d\x4b\x89\x1d\xf6\x9d\x65\xc4\x38\xd2\x54\x9c" ++ "\xe3\xcd\x89\xe1\xe1\xe6\x3e\x70\x81\x45\x1d\x18\xf9\x31\x83\xc8" ++ "\xbe\x14\x82\x4b\x87\x7a\x74\x28\xd2\xdd\x12\x55\x30\xe6\x0e\x49" ++ "\x31\x8e\x48\x69\xc5\xc0\x20\x91\xe4\x48\x41\x4c\xd8\xb9\x6a\x4e" ++ "\x21\xce\x99\x1b\x0e\xfd\x09\x4f\xa1\x79\x0f\x0f\x0f\x0f\x0f\x0f" ++ "\x0f\x3f\x3c\xb8\x71\x27\xc7\x72\x24\xe8\xb1\xa6\xc5\x7b\x18\xc3" ++ "\xb1\xa5\xb0\xd4\x98\xee\xe3\x19\xc6\x71\x87\x19\x79\x2b\x6d\x78" ++ "\xc6\x71\x8c\xe3\x0a\x4e\x71\x8c\xe3\x19\xfe\x38\xf2\x3b\xfb\x8b" ++ "\x48\xfe\x4e\xaa\xff\x00\x4f\x08\xff\x00\xc7\xe1\xfb\x8b\x48\xfe" ++ "\x4e\xaa\xff\x00\x4f\x08\xff\x00\xc7\xe4\x95\x86\x18\x8a\xcb\x31" ++ "\xa3\x32\xd4\x78\xf1\xdb\x43\x2c\x47\x61\xb4\x32\xcb\x2c\xb4\x9c" ++ "\x21\xb6\x99\x69\xbc\x25\xb6\xdb\x6d\x18\xc2\x10\xda\x12\x94\xa1" ++ "\x38\xc2\x53\x8c\x63\x18\xc7\x9d\xbe\x7f\xff\xd9" ++ ; +diff -Nura php-5.3.9/main/suhosin_patch.c suhosin-patch-5.3.9-0.9.10/main/suhosin_patch.c +--- php-5.3.9/main/suhosin_patch.c 1970-01-01 01:00:00.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/main/suhosin_patch.c 2012-01-11 19:29:08.000000000 +0100 +@@ -0,0 +1,470 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | Suhosin Patch for PHP | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 2004-2010 Stefan Esser | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.txt. | ++ | If you did not receive a copy of the PHP license and are unable to | ++ | obtain it through the world-wide-web, please send a note to | ++ | license@php.net so we can mail you a copy immediately. | ++ +----------------------------------------------------------------------+ ++ | Author: Stefan Esser | ++ +----------------------------------------------------------------------+ ++ */ ++/* $Id: suhosin_patch.c,v 1.2 2004/11/21 09:38:52 ionic Exp $ */ ++ ++#include "php.h" ++ ++#include ++#include ++#include ++ ++#if HAVE_UNISTD_H ++#include ++#endif ++#include "SAPI.h" ++#include "php_globals.h" ++ ++#if SUHOSIN_PATCH ++ ++#ifdef HAVE_SYS_SOCKET_H ++#include ++#endif ++ ++#if defined(PHP_WIN32) || defined(__riscos__) || defined(NETWARE) ++#undef AF_UNIX ++#endif ++ ++#if defined(AF_UNIX) ++#include ++#endif ++ ++#define SYSLOG_PATH "/dev/log" ++ ++#ifdef PHP_WIN32 ++static HANDLE log_source = 0; ++#endif ++ ++#include "snprintf.h" ++ ++#include "suhosin_patch.h" ++ ++#ifdef ZTS ++#include "suhosin_globals.h" ++int suhosin_patch_globals_id; ++#else ++struct _suhosin_patch_globals suhosin_patch_globals; ++#endif ++ ++static char *suhosin_config = NULL; ++ ++static zend_intptr_t SUHOSIN_POINTER_GUARD = 0; ++ ++static void php_security_log(int loglevel, char *fmt, ...); ++ ++static void suhosin_patch_globals_ctor(suhosin_patch_globals_struct *suhosin_patch_globals TSRMLS_DC) ++{ ++ memset(suhosin_patch_globals, 0, sizeof(*suhosin_patch_globals)); ++} ++ ++ZEND_API char suhosin_get_config(int element) ++{ ++ return ((char *)SUHOSIN_MANGLE_PTR(suhosin_config))[element]; ++} ++ ++static void suhosin_set_config(int element, char value) ++{ ++ ((char *)SUHOSIN_MANGLE_PTR(suhosin_config))[element] = value; ++} ++ ++static void suhosin_read_configuration_from_environment() ++{ ++ char *tmp; ++ ++ /* check if canary protection should be activated or not */ ++ tmp = getenv("SUHOSIN_MM_USE_CANARY_PROTECTION"); ++ /* default to activated */ ++ suhosin_set_config(SUHOSIN_MM_USE_CANARY_PROTECTION, 1); ++ if (tmp) { ++ int flag = zend_atoi(tmp, 0); ++ suhosin_set_config(SUHOSIN_MM_USE_CANARY_PROTECTION, flag); ++ } ++ ++ /* check if free memory should be overwritten with 0xFF or not */ ++ tmp = getenv("SUHOSIN_MM_DESTROY_FREE_MEMORY"); ++ /* default to deactivated */ ++ suhosin_set_config(SUHOSIN_MM_DESTROY_FREE_MEMORY, 0); ++ if (tmp) { ++ int flag = zend_atoi(tmp, 0); ++ suhosin_set_config(SUHOSIN_MM_DESTROY_FREE_MEMORY, flag); ++ } ++ ++ /* check if canary violations should be ignored */ ++ tmp = getenv("SUHOSIN_MM_IGNORE_CANARY_VIOLATION"); ++ /* default to NOT ignore */ ++ suhosin_set_config(SUHOSIN_MM_IGNORE_CANARY_VIOLATION, 0); ++ if (tmp) { ++ int flag = zend_atoi(tmp, 0); ++ suhosin_set_config(SUHOSIN_MM_IGNORE_CANARY_VIOLATION, flag); ++ } ++ ++ /* check if invalid hashtable destructors should be ignored */ ++ tmp = getenv("SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR"); ++ /* default to NOT ignore */ ++ suhosin_set_config(SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR, 0); ++ if (tmp) { ++ int flag = zend_atoi(tmp, 0); ++ suhosin_set_config(SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR, flag); ++ } ++ ++ /* check if invalid linkedlist destructors should be ignored */ ++ tmp = getenv("SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR"); ++ /* default to NOT ignore */ ++ suhosin_set_config(SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR, 0); ++ if (tmp) { ++ int flag = zend_atoi(tmp, 0); ++ suhosin_set_config(SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR, flag); ++ } ++ ++ suhosin_set_config(SUHOSIN_CONFIG_SET, 1); ++} ++ ++static void suhosin_write_protect_configuration() ++{ ++ /* check return value of mprotect() to ensure memory is read only now */ ++ if (mprotect(SUHOSIN_MANGLE_PTR(suhosin_config), sysconf(_SC_PAGESIZE), PROT_READ) != 0) { ++ perror("suhosin"); ++ _exit(1); ++ } ++} ++ ++PHPAPI void suhosin_startup() ++{ ++#ifdef ZTS ++ ts_allocate_id(&suhosin_patch_globals_id, sizeof(suhosin_patch_globals_struct), (ts_allocate_ctor) suhosin_patch_globals_ctor, NULL); ++#else ++ suhosin_patch_globals_ctor(&suhosin_patch_globals TSRMLS_CC); ++#endif ++ zend_suhosin_log = php_security_log; ++ ++ /* get the pointer guardian and ensure low 3 bits are 1 */ ++ if (SUHOSIN_POINTER_GUARD == 0) { ++ zend_canary(&SUHOSIN_POINTER_GUARD, sizeof(SUHOSIN_POINTER_GUARD)); ++ SUHOSIN_POINTER_GUARD |= 7; ++ } ++ ++ if (!suhosin_config) { ++#ifndef MAP_ANONYMOUS ++#define MAP_ANONYMOUS MAP_ANON ++#endif ++ suhosin_config = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); ++ if (suhosin_config == MAP_FAILED) { ++ perror("suhosin"); ++ _exit(1); ++ } ++ suhosin_config = SUHOSIN_MANGLE_PTR(suhosin_config); ++ } ++ if (!SUHOSIN_CONFIG(SUHOSIN_CONFIG_SET)) { ++ suhosin_read_configuration_from_environment(); ++ suhosin_write_protect_configuration(); ++ } ++} ++ ++static char *loglevel2string(int loglevel) ++{ ++ switch (loglevel) { ++ case S_FILES: ++ return "FILES"; ++ case S_INCLUDE: ++ return "INCLUDE"; ++ case S_MEMORY: ++ return "MEMORY"; ++ case S_MISC: ++ return "MISC"; ++ case S_SESSION: ++ return "SESSION"; ++ case S_SQL: ++ return "SQL"; ++ case S_EXECUTOR: ++ return "EXECUTOR"; ++ case S_VARS: ++ return "VARS"; ++ default: ++ return "UNKNOWN"; ++ } ++} ++ ++static void php_security_log(int loglevel, char *fmt, ...) ++{ ++ int s, r, i=0; ++#if defined(AF_UNIX) ++ struct sockaddr_un saun; ++#endif ++#ifdef PHP_WIN32 ++ LPTSTR strs[2]; ++ unsigned short etype; ++ DWORD evid; ++#endif ++ char buf[4096+64]; ++ char error[4096+100]; ++ char *ip_address; ++ char *fname; ++ char *alertstring; ++ int lineno; ++ va_list ap; ++ TSRMLS_FETCH(); ++ ++ /*SDEBUG("(suhosin_log) loglevel: %d log_syslog: %u - log_sapi: %u - log_script: %u", loglevel, SPG(log_syslog), SPG(log_sapi), SPG(log_script));*/ ++ ++ if (SPG(log_use_x_forwarded_for)) { ++ ip_address = sapi_getenv("HTTP_X_FORWARDED_FOR", 20 TSRMLS_CC); ++ if (ip_address == NULL) { ++ ip_address = "X-FORWARDED-FOR not set"; ++ } ++ } else { ++ ip_address = sapi_getenv("REMOTE_ADDR", 11 TSRMLS_CC); ++ if (ip_address == NULL) { ++ ip_address = "REMOTE_ADDR not set"; ++ } ++ } ++ ++ ++ va_start(ap, fmt); ++ ap_php_vsnprintf(error, sizeof(error), fmt, ap); ++ va_end(ap); ++ while (error[i]) { ++ if (error[i] < 32) error[i] = '.'; ++ i++; ++ } ++ ++/* if (SPG(simulation)) { ++ alertstring = "ALERT-SIMULATION"; ++ } else { */ ++ alertstring = "ALERT"; ++/* }*/ ++ ++ if (zend_is_executing(TSRMLS_C)) { ++ if (EG(current_execute_data)) { ++ lineno = EG(current_execute_data)->opline->lineno; ++ fname = EG(current_execute_data)->op_array->filename; ++ } else { ++ lineno = zend_get_executed_lineno(TSRMLS_C); ++ fname = zend_get_executed_filename(TSRMLS_C); ++ } ++ ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s', line %u)", alertstring, error, ip_address, fname, lineno); ++ } else { ++ fname = sapi_getenv("SCRIPT_FILENAME", 15 TSRMLS_CC); ++ if (fname==NULL) { ++ fname = "unknown"; ++ } ++ ap_php_snprintf(buf, sizeof(buf), "%s - %s (attacker '%s', file '%s')", alertstring, error, ip_address, fname); ++ } ++ ++ /* Syslog-Logging disabled? */ ++ if (((SPG(log_syslog)|S_INTERNAL) & loglevel)==0) { ++ goto log_sapi; ++ } ++ ++#if defined(AF_UNIX) ++ ap_php_snprintf(error, sizeof(error), "<%u>suhosin[%u]: %s\n", (unsigned int)(SPG(log_syslog_facility)|SPG(log_syslog_priority)),getpid(),buf); ++ ++ s = socket(AF_UNIX, SOCK_DGRAM, 0); ++ if (s == -1) { ++ goto log_sapi; ++ } ++ ++ memset(&saun, 0, sizeof(saun)); ++ saun.sun_family = AF_UNIX; ++ strcpy(saun.sun_path, SYSLOG_PATH); ++ /*saun.sun_len = sizeof(saun);*/ ++ ++ r = connect(s, (struct sockaddr *)&saun, sizeof(saun)); ++ if (r) { ++ close(s); ++ s = socket(AF_UNIX, SOCK_STREAM, 0); ++ if (s == -1) { ++ goto log_sapi; ++ } ++ ++ memset(&saun, 0, sizeof(saun)); ++ saun.sun_family = AF_UNIX; ++ strcpy(saun.sun_path, SYSLOG_PATH); ++ /*saun.sun_len = sizeof(saun);*/ ++ ++ r = connect(s, (struct sockaddr *)&saun, sizeof(saun)); ++ if (r) { ++ close(s); ++ goto log_sapi; ++ } ++ } ++ send(s, error, strlen(error), 0); ++ ++ close(s); ++#endif ++#ifdef PHP_WIN32 ++ ap_php_snprintf(error, sizeof(error), "suhosin[%u]: %s", getpid(),buf); ++ ++ switch (SPG(log_syslog_priority)) { /* translate UNIX type into NT type */ ++ case 1: /*LOG_ALERT:*/ ++ etype = EVENTLOG_ERROR_TYPE; ++ break; ++ case 6: /*LOG_INFO:*/ ++ etype = EVENTLOG_INFORMATION_TYPE; ++ break; ++ default: ++ etype = EVENTLOG_WARNING_TYPE; ++ } ++ evid = loglevel; ++ strs[0] = error; ++ /* report the event */ ++ if (log_source == NULL) { ++ log_source = RegisterEventSource(NULL, "Suhosin-Patch-" SUHOSIN_PATCH_VERSION); ++ } ++ ReportEvent(log_source, etype, (unsigned short) SPG(log_syslog_priority), evid, NULL, 1, 0, strs, NULL); ++ ++#endif ++log_sapi: ++ /* SAPI Logging activated? */ ++ /*SDEBUG("(suhosin_log) log_syslog: %u - log_sapi: %u - log_script: %u - log_phpscript: %u", SPG(log_syslog), SPG(log_sapi), SPG(log_script), SPG(log_phpscript));*/ ++ if (((SPG(log_sapi)|S_INTERNAL) & loglevel)!=0) { ++ sapi_module.log_message(buf); ++ } ++ ++/*log_script:*/ ++ /* script logging activaed? */ ++ if (((SPG(log_script) & loglevel)!=0) && SPG(log_scriptname)!=NULL) { ++ char cmd[8192], *cmdpos, *bufpos; ++ FILE *in; ++ int space; ++ ++ ap_php_snprintf(cmd, sizeof(cmd), "%s %s \'", SPG(log_scriptname), loglevel2string(loglevel)); ++ space = sizeof(cmd) - strlen(cmd); ++ cmdpos = cmd + strlen(cmd); ++ bufpos = buf; ++ if (space <= 1) return; ++ while (space > 2 && *bufpos) { ++ if (*bufpos == '\'') { ++ if (space<=5) break; ++ *cmdpos++ = '\''; ++ *cmdpos++ = '\\'; ++ *cmdpos++ = '\''; ++ *cmdpos++ = '\''; ++ bufpos++; ++ space-=4; ++ } else { ++ *cmdpos++ = *bufpos++; ++ space--; ++ } ++ } ++ *cmdpos++ = '\''; ++ *cmdpos = 0; ++ ++ if ((in=VCWD_POPEN(cmd, "r"))==NULL) { ++ php_security_log(S_INTERNAL, "Unable to execute logging shell script: %s", SPG(log_scriptname)); ++ return; ++ } ++ /* read and forget the result */ ++ while (1) { ++ int readbytes = fread(cmd, 1, sizeof(cmd), in); ++ if (readbytes<=0) { ++ break; ++ } ++ } ++ pclose(in); ++ } ++/*log_phpscript:*/ ++ if ((SPG(log_phpscript) & loglevel)!=0 && EG(in_execution) && SPG(log_phpscriptname) && SPG(log_phpscriptname)[0]) { ++ zend_file_handle file_handle; ++ zend_op_array *new_op_array; ++ zval *result = NULL; ++ ++ /*long orig_execution_depth = SPG(execution_depth);*/ ++ zend_bool orig_safe_mode = PG(safe_mode); ++ char *orig_basedir = PG(open_basedir); ++ ++ char *phpscript = SPG(log_phpscriptname); ++/*SDEBUG("scriptname %s", SPG(log_phpscriptname));`*/ ++#ifdef ZEND_ENGINE_2 ++ if (zend_stream_open(phpscript, &file_handle TSRMLS_CC) == SUCCESS) { ++#else ++ if (zend_open(phpscript, &file_handle) == SUCCESS && ZEND_IS_VALID_FILE_HANDLE(&file_handle)) { ++ file_handle.filename = phpscript; ++ file_handle.free_filename = 0; ++#endif ++ if (!file_handle.opened_path) { ++ file_handle.opened_path = estrndup(phpscript, strlen(phpscript)); ++ } ++ new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC); ++ zend_destroy_file_handle(&file_handle TSRMLS_CC); ++ if (new_op_array) { ++ HashTable *active_symbol_table = EG(active_symbol_table); ++ zval *zerror, *zerror_class; ++ ++ if (active_symbol_table == NULL) { ++ active_symbol_table = &EG(symbol_table); ++ } ++ EG(return_value_ptr_ptr) = &result; ++ EG(active_op_array) = new_op_array; ++ ++ MAKE_STD_ZVAL(zerror); ++ MAKE_STD_ZVAL(zerror_class); ++ ZVAL_STRING(zerror, buf, 1); ++ ZVAL_LONG(zerror_class, loglevel); ++ ++ zend_hash_update(active_symbol_table, "SUHOSIN_ERROR", sizeof("SUHOSIN_ERROR"), (void **)&zerror, sizeof(zval *), NULL); ++ zend_hash_update(active_symbol_table, "SUHOSIN_ERRORCLASS", sizeof("SUHOSIN_ERRORCLASS"), (void **)&zerror_class, sizeof(zval *), NULL); ++ ++ /*SPG(execution_depth) = 0;*/ ++ if (SPG(log_phpscript_is_safe)) { ++ PG(safe_mode) = 0; ++ PG(open_basedir) = NULL; ++ } ++ ++ zend_execute(new_op_array TSRMLS_CC); ++ ++ /*SPG(execution_depth) = orig_execution_depth;*/ ++ PG(safe_mode) = orig_safe_mode; ++ PG(open_basedir) = orig_basedir; ++ ++#ifdef ZEND_ENGINE_2 ++ destroy_op_array(new_op_array TSRMLS_CC); ++#else ++ destroy_op_array(new_op_array); ++#endif ++ efree(new_op_array); ++#ifdef ZEND_ENGINE_2 ++ if (!EG(exception)) ++#endif ++ { ++ if (EG(return_value_ptr_ptr)) { ++ zval_ptr_dtor(EG(return_value_ptr_ptr)); ++ EG(return_value_ptr_ptr) = NULL; ++ } ++ } ++ } else { ++ php_security_log(S_INTERNAL, "Unable to execute logging PHP script: %s", SPG(log_phpscriptname)); ++ return; ++ } ++ } else { ++ php_security_log(S_INTERNAL, "Unable to execute logging PHP script: %s", SPG(log_phpscriptname)); ++ return; ++ } ++ } ++ ++} ++ ++ ++#endif ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * End: ++ * vim600: sw=4 ts=4 fdm=marker ++ * vim<600: sw=4 ts=4 ++ */ +diff -Nura php-5.3.9/main/suhosin_patch.h suhosin-patch-5.3.9-0.9.10/main/suhosin_patch.h +--- php-5.3.9/main/suhosin_patch.h 1970-01-01 01:00:00.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/main/suhosin_patch.h 2012-01-11 19:29:08.000000000 +0100 +@@ -0,0 +1,59 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | Suhosin Patch for PHP | ++ +----------------------------------------------------------------------+ ++ | Copyright (c) 2004-2010 Stefan Esser | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 2.02 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available at through the world-wide-web at | ++ | http://www.php.net/license/2_02.txt. | ++ | If you did not receive a copy of the PHP license and are unable to | ++ | obtain it through the world-wide-web, please send a note to | ++ | license@php.net so we can mail you a copy immediately. | ++ +----------------------------------------------------------------------+ ++ | Author: Stefan Esser | ++ +----------------------------------------------------------------------+ ++ */ ++ ++#ifndef SUHOSIN_PATCH_H ++#define SUHOSIN_PATCH_H ++ ++#if SUHOSIN_PATCH ++ ++#include "zend.h" ++ ++#define SUHOSIN_PATCH_VERSION "0.9.10" ++ ++#define SUHOSIN_LOGO_GUID "SUHO8567F54-D428-14d2-A769-00DA302A5F18" ++ ++#define SUHOSIN_CONFIG(idx) (suhosin_get_config(idx)) ++ ++#define SUHOSIN_MM_USE_CANARY_PROTECTION 0 ++#define SUHOSIN_MM_DESTROY_FREE_MEMORY 1 ++#define SUHOSIN_MM_IGNORE_CANARY_VIOLATION 2 ++#define SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR 3 ++#define SUHOSIN_LL_IGNORE_INVALID_DESTRUCTOR 4 ++ ++#define SUHOSIN_CONFIG_SET 100 ++ ++#include ++#include ++#include ++ ++#if defined(DARWIN) ++#include ++#endif ++ ++#define SUHOSIN_MANGLE_PTR(ptr) (ptr==NULL?NULL:((void *)((zend_intptr_t)(ptr)^SUHOSIN_POINTER_GUARD))) ++ ++#endif ++ ++#endif /* SUHOSIN_PATCH_H */ ++ ++/* ++ * Local variables: ++ * tab-width: 4 ++ * c-basic-offset: 4 ++ * End: ++ */ +diff -Nura php-5.3.9/main/suhosin_patch.m4 suhosin-patch-5.3.9-0.9.10/main/suhosin_patch.m4 +--- php-5.3.9/main/suhosin_patch.m4 1970-01-01 01:00:00.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/main/suhosin_patch.m4 2012-01-11 19:29:08.000000000 +0100 +@@ -0,0 +1,8 @@ ++dnl ++dnl $Id: suhosin_patch.m4,v 1.1 2004/11/14 13:24:24 ionic Exp $ ++dnl ++dnl This file contains Suhosin Patch for PHP specific autoconf functions. ++dnl ++ ++AC_DEFINE(SUHOSIN_PATCH, 1, [Suhosin Patch]) ++ +diff -Nura php-5.3.9/sapi/apache/mod_php5.c suhosin-patch-5.3.9-0.9.10/sapi/apache/mod_php5.c +--- php-5.3.9/sapi/apache/mod_php5.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/sapi/apache/mod_php5.c 2012-01-11 19:29:08.000000000 +0100 +@@ -969,7 +969,11 @@ + { + TSRMLS_FETCH(); + if (PG(expose_php)) { ++#if SUHOSIN_PATCH ++ ap_add_version_component("PHP/" PHP_VERSION " with Suhosin-Patch"); ++#else + ap_add_version_component("PHP/" PHP_VERSION); ++#endif + } + } + #endif +diff -Nura php-5.3.9/sapi/apache2filter/sapi_apache2.c suhosin-patch-5.3.9-0.9.10/sapi/apache2filter/sapi_apache2.c +--- php-5.3.9/sapi/apache2filter/sapi_apache2.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/sapi/apache2filter/sapi_apache2.c 2012-01-11 19:29:08.000000000 +0100 +@@ -583,7 +583,11 @@ + { + TSRMLS_FETCH(); + if (PG(expose_php)) { ++#if SUHOSIN_PATCH ++ ap_add_version_component(p, "PHP/" PHP_VERSION " with Suhosin-Patch"); ++#else + ap_add_version_component(p, "PHP/" PHP_VERSION); ++#endif + } + } + +diff -Nura php-5.3.9/sapi/apache2handler/sapi_apache2.c suhosin-patch-5.3.9-0.9.10/sapi/apache2handler/sapi_apache2.c +--- php-5.3.9/sapi/apache2handler/sapi_apache2.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/sapi/apache2handler/sapi_apache2.c 2012-01-11 19:29:08.000000000 +0100 +@@ -407,7 +407,11 @@ + { + TSRMLS_FETCH(); + if (PG(expose_php)) { ++#if SUHOSIN_PATCH ++ ap_add_version_component(p, "PHP/" PHP_VERSION " with Suhosin-Patch"); ++#else + ap_add_version_component(p, "PHP/" PHP_VERSION); ++#endif + } + } + +diff -Nura php-5.3.9/sapi/apache_hooks/mod_php5.c suhosin-patch-5.3.9-0.9.10/sapi/apache_hooks/mod_php5.c +--- php-5.3.9/sapi/apache_hooks/mod_php5.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/sapi/apache_hooks/mod_php5.c 2012-01-11 19:29:08.000000000 +0100 +@@ -1256,7 +1256,11 @@ + { + TSRMLS_FETCH(); + if (PG(expose_php)) { ++#if SUHOSIN_PATCH ++ ap_add_version_component("PHP/" PHP_VERSION " with Suhosin-Patch"); ++#else + ap_add_version_component("PHP/" PHP_VERSION); ++#endif + } + } + #endif +diff -Nura php-5.3.9/sapi/cgi/cgi_main.c suhosin-patch-5.3.9-0.9.10/sapi/cgi/cgi_main.c +--- php-5.3.9/sapi/cgi/cgi_main.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/sapi/cgi/cgi_main.c 2012-01-11 19:36:52.000000000 +0100 +@@ -1932,11 +1932,19 @@ + SG(headers_sent) = 1; + SG(request_info).no_headers = 1; + } ++#if SUHOSIN_PATCH ++#if ZEND_DEBUG ++ php_printf("PHP %s with Suhosin-Patch (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2013 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++#else ++ php_printf("PHP %s with Suhosin-Patch (%s) (built: %s %s)\nCopyright (c) 1997-2013 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++#endif ++#else + #if ZEND_DEBUG + php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2013 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); + #else + php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2013 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); + #endif ++#endif + php_request_shutdown((void *) 0); + fcgi_shutdown(); + exit_status = 0; +diff -Nura php-5.3.9/sapi/cli/php_cli.c suhosin-patch-5.3.9-0.9.10/sapi/cli/php_cli.c +--- php-5.3.9/sapi/cli/php_cli.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/sapi/cli/php_cli.c 2012-01-11 19:35:06.000000000 +0100 +@@ -826,7 +826,11 @@ + } + + request_started = 1; +- php_printf("PHP %s (%s) (built: %s %s) %s\nCopyright (c) 1997-2013 The PHP Group\n%s", ++ php_printf("PHP %s " ++#if SUHOSIN_PATCH ++ "with Suhosin-Patch " ++#endif ++ "(%s) (built: %s %s) %s\nCopyright (c) 1997-2013 The PHP Group\n%s", + PHP_VERSION, sapi_module.name, __DATE__, __TIME__, + #if ZEND_DEBUG && defined(HAVE_GCOV) + "(DEBUG GCOV)", +diff -Nura php-5.3.9/sapi/litespeed/lsapi_main.c suhosin-patch-5.3.9-0.9.10/sapi/litespeed/lsapi_main.c +--- php-5.3.9/sapi/litespeed/lsapi_main.c 2011-12-31 19:15:06.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/sapi/litespeed/lsapi_main.c 2012-01-11 19:29:08.000000000 +0100 +@@ -718,11 +718,19 @@ + break; + case 'v': + if (php_request_startup(TSRMLS_C) != FAILURE) { ++#if SUHOSIN_PATCH ++ #if ZEND_DEBUG ++ php_printf("PHP %s with Suhosin-Patch (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2013 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++ #else ++ php_printf("PHP %s with Suhosin-Patch (%s) (built: %s %s)\nCopyright (c) 1997-2013 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++ #endif ++#else + #if ZEND_DEBUG + php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2013 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); + #else + php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2013 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); + #endif ++#endif + #ifdef PHP_OUTPUT_NEWAPI + php_output_end_all(TSRMLS_C); + #else +diff -Nura php-5.3.9/sapi/milter/php_milter.c suhosin-patch-5.3.9-0.9.10/sapi/milter/php_milter.c +--- php-5.3.9/sapi/milter/php_milter.c 2012-01-01 14:15:04.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/sapi/milter/php_milter.c 2012-01-11 19:33:42.000000000 +0100 +@@ -1111,7 +1111,11 @@ + } + SG(headers_sent) = 1; + SG(request_info).no_headers = 1; ++#if SUHOSIN_PATCH ++ php_printf("PHP %s with Suhosin-Patch (%s) (built: %s %s)\nCopyright (c) 1997-2013 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++#else + php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2013 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); ++#endif + php_end_ob_buffers(1 TSRMLS_CC); + exit(1); + break; +diff -Nura php-5.3.9/win32/build/config.w32 suhosin-patch-5.3.9-0.9.10/win32/build/config.w32 +--- php-5.3.9/win32/build/config.w32 2011-03-28 12:55:34.000000000 +0200 ++++ suhosin-patch-5.3.9-0.9.10/win32/build/config.w32 2012-01-11 19:29:08.000000000 +0100 +@@ -328,7 +328,7 @@ + zend_stream.c zend_iterators.c zend_interfaces.c zend_objects.c \ + zend_object_handlers.c zend_objects_API.c \ + zend_default_classes.c zend_execute.c zend_strtod.c zend_gc.c zend_closures.c \ +- zend_float.c"); ++ zend_float.c zend_canary.c zend_alloc_canary.c"); + + if (VCVERS == 1200) { + AC_DEFINE('ZEND_DVAL_TO_LVAL_CAST_OK', 1); +@@ -385,6 +385,7 @@ + + AC_DEFINE('HAVE_USLEEP', 1); + AC_DEFINE('HAVE_STRCOLL', 1); ++AC_DEFINE('SUHOSIN_PATCH', 1); + + /* For snapshot builders, where can we find the additional + * files that make up the snapshot template? */ +diff -Nura php-5.3.9/win32/build/config.w32.h.in suhosin-patch-5.3.9-0.9.10/win32/build/config.w32.h.in +--- php-5.3.9/win32/build/config.w32.h.in 2010-11-26 19:25:13.000000000 +0100 ++++ suhosin-patch-5.3.9-0.9.10/win32/build/config.w32.h.in 2012-01-11 19:29:08.000000000 +0100 +@@ -152,6 +152,9 @@ + /* Win32 supports strcoll */ + #define HAVE_STRCOLL 1 + ++/* Suhosin Patch support */ ++#define SUHOSIN_PATCH 1 ++ + /* Win32 supports socketpair by the emulation in win32/sockets.c */ + #define HAVE_SOCKETPAIR 1 + #define HAVE_SOCKLEN_T 1 diff --git a/system-libzip.patch b/system-libzip.patch new file mode 100644 index 0000000..1353191 --- /dev/null +++ b/system-libzip.patch @@ -0,0 +1,130 @@ + +https://bugzilla.redhat.com/show_bug.cgi?id=551513 +https://bugs.php.net/bug.php?id=39388 +http://spot.fedorapeople.org/php-5.3.6-libzip.patch +pld fixes: link with -lzip when using system lib, -lz otherwise + +--- php-5.3.8/ext/zip/config.m4~ 2008-08-08 12:47:15.000000000 +0300 ++++ php-5.3.8/ext/zip/config.m4 2011-09-27 01:18:53.258197363 +0300 +@@ -13,8 +13,72 @@ + PHP_ARG_WITH(pcre-dir, pcre install prefix, + [ --with-pcre-dir ZIP: pcre install prefix], no, no) + ++PHP_ARG_WITH(libzip, libzip, ++[ --with-libzip[=DIR] ZIP: use libzip], no, no) ++ + if test "$PHP_ZIP" != "no"; then ++ dnl This is PECL build, check if bundled PCRE library is used ++ old_CPPFLAGS=$CPPFLAGS ++ CPPFLAGS=$INCLUDES ++ AC_EGREP_CPP(yes,[ ++#include
++#if defined(HAVE_BUNDLED_PCRE) && !defined(COMPILE_DL_PCRE) ++yes ++#endif ++ ],[ ++ PHP_PCRE_REGEX=yes ++ ],[ ++ AC_EGREP_CPP(yes,[ ++#include
++#if defined(HAVE_PCRE) && !defined(COMPILE_DL_PCRE) ++yes ++#endif ++ ],[ ++ PHP_PCRE_REGEX=pecl ++ ],[ ++ PHP_PCRE_REGEX=no ++ ]) ++ ]) ++ CPPFLAGS=$old_CPPFLAGS ++ ++ if test "$PHP_LIBZIP" != "no"; then ++ dnl system libzip, depends on libzip ++ if test -r $PHP_LIBZIP/include/zip.h; then ++ LIBZIP_DIR=$PHP_LIBZIP ++ else ++ AC_MSG_CHECKING(for libzip in default path) ++ for i in /usr/local /usr; do ++ if test -r $i/include/zip.h; then ++ LIBZIP_DIR=$i ++ AC_MSG_RESULT(found in $i) ++ break ++ fi ++ done ++ fi ++ ++ if test -z "$LIBZIP_DIR"; then ++ AC_MSG_RESULT(not found) ++ AC_MSG_ERROR(Please reinstall the libzip distribution) ++ fi + ++ dnl Could not think of a simple way to check libzip for overwrite support ++ PHP_CHECK_LIBRARY(zip, zip_open, ++ [ ++ PHP_ADD_INCLUDE($LIBZIP_DIR/include) ++ PHP_ADD_LIBRARY_WITH_PATH(zip, $LIBZIP_DIR/$PHP_LIBDIR, ZIP_SHARED_LIBADD) ++ AC_DEFINE(HAVE_LIBZIP,1,[ ]) ++ ], [ ++ AC_MSG_ERROR(could not find usable libzip) ++ ], [ ++ -L$LIBZIP_DIR/$PHP_LIBDIR ++ ]) ++ ++ AC_DEFINE(HAVE_ZIP,1,[ ]) ++ PHP_NEW_EXTENSION(zip, php_zip.c zip_stream.c, $ext_shared) ++ PHP_SUBST(ZIP_SHARED_LIBADD) ++ else ++ ++ dnl bundled libzip, depends on zlib + if test "$PHP_ZLIB_DIR" != "no" && test "$PHP_ZLIB_DIR" != "yes"; then + if test -f "$PHP_ZLIB_DIR/include/zlib/zlib.h"; then + PHP_ZLIB_DIR="$PHP_ZLIB_DIR" +@@ -47,31 +111,7 @@ + PHP_ADD_INCLUDE($PHP_ZLIB_INCDIR) + fi + +- dnl This is PECL build, check if bundled PCRE library is used +- old_CPPFLAGS=$CPPFLAGS +- CPPFLAGS=$INCLUDES +- AC_EGREP_CPP(yes,[ +-#include
+-#if defined(HAVE_BUNDLED_PCRE) && !defined(COMPILE_DL_PCRE) +-yes +-#endif +- ],[ +- PHP_PCRE_REGEX=yes +- ],[ +- AC_EGREP_CPP(yes,[ +-#include
+-#if defined(HAVE_PCRE) && !defined(COMPILE_DL_PCRE) +-yes +-#endif +- ],[ +- PHP_PCRE_REGEX=pecl +- ],[ +- PHP_PCRE_REGEX=no +- ]) +- ]) +- CPPFLAGS=$old_CPPFLAGS +- +- PHP_ZIP_SOURCES="$PHP_ZIP_SOURCES lib/zip_add.c lib/zip_error.c lib/zip_fclose.c \ ++ PHP_ZIP_SOURCES="$PHP_ZIP_SOURCES lib/zip_add.c lib/zip_error.c lib/zip_fclose.c \ + lib/zip_fread.c lib/zip_open.c lib/zip_source_filep.c \ + lib/zip_strerror.c lib/zip_close.c lib/zip_error_get.c \ + lib/zip_file_error_get.c lib/zip_free.c lib/zip_rename.c \ +@@ -91,10 +131,11 @@ + lib/zip_unchange_archive.c lib/zip_memdup.c lib/zip_stat_init.c lib/zip_add_dir.c \ + lib/zip_error_clear.c lib/zip_file_error_clear.c" + +- AC_DEFINE(HAVE_ZIP,1,[ ]) +- PHP_NEW_EXTENSION(zip, php_zip.c zip_stream.c $PHP_ZIP_SOURCES, $ext_shared) +- PHP_ADD_BUILD_DIR($ext_builddir/lib, 1) +- PHP_SUBST(ZIP_SHARED_LIBADD) ++ AC_DEFINE(HAVE_ZIP,1,[ ]) ++ PHP_NEW_EXTENSION(zip, php_zip.c zip_stream.c $PHP_ZIP_SOURCES, $ext_shared) ++ PHP_ADD_BUILD_DIR($ext_builddir/lib, 1) ++ PHP_SUBST(ZIP_SHARED_LIBADD) ++ fi + + dnl so we always include the known-good working hack. + PHP_ADD_MAKEFILE_FRAGMENT