mirror of
https://github.com/php/php-src.git
synced 2026-04-29 03:03:26 +02:00
Revert "Update versions for PHP 8.0.21"
This reverts commit 6eedacdf15.
This commit is contained in:
@@ -1,2 +0,0 @@
|
||||
Apache 2.0 Handler
|
||||
Ian Holsman, Justin Erenkrantz (based on Apache 2.0 Filter code)
|
||||
@@ -1,239 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 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: Sascha Schumann <sascha@schumann.cx> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
|
||||
|
||||
#include "php.h"
|
||||
#ifdef strcasecmp
|
||||
# undef strcasecmp
|
||||
#endif
|
||||
#ifdef strncasecmp
|
||||
# undef strncasecmp
|
||||
#endif
|
||||
#include "php_ini.h"
|
||||
#include "php_apache.h"
|
||||
|
||||
#include "apr_strings.h"
|
||||
#include "ap_config.h"
|
||||
#include "util_filter.h"
|
||||
#include "httpd.h"
|
||||
#include "http_config.h"
|
||||
#include "http_request.h"
|
||||
#include "http_core.h"
|
||||
#include "http_protocol.h"
|
||||
#include "http_log.h"
|
||||
#include "http_main.h"
|
||||
#include "util_script.h"
|
||||
#include "http_core.h"
|
||||
|
||||
#ifdef PHP_AP_DEBUG
|
||||
#define phpapdebug(a) fprintf a
|
||||
#else
|
||||
#define phpapdebug(a)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
HashTable config;
|
||||
} php_conf_rec;
|
||||
|
||||
typedef struct {
|
||||
char *value;
|
||||
size_t value_len;
|
||||
char status;
|
||||
char htaccess;
|
||||
} php_dir_entry;
|
||||
|
||||
static const char *real_value_hnd(cmd_parms *cmd, void *dummy, const char *name, const char *value, int status)
|
||||
{
|
||||
php_conf_rec *d = dummy;
|
||||
php_dir_entry e;
|
||||
|
||||
phpapdebug((stderr, "Getting %s=%s for %p (%d)\n", name, value, dummy, zend_hash_num_elements(&d->config)));
|
||||
|
||||
if (!strncasecmp(value, "none", sizeof("none"))) {
|
||||
value = "";
|
||||
}
|
||||
|
||||
e.value = apr_pstrdup(cmd->pool, value);
|
||||
e.value_len = strlen(value);
|
||||
e.status = status;
|
||||
e.htaccess = ((cmd->override & (RSRC_CONF|ACCESS_CONF)) == 0);
|
||||
|
||||
zend_hash_str_update_mem(&d->config, (char *) name, strlen(name), &e, sizeof(e));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *php_apache_value_handler(cmd_parms *cmd, void *dummy, const char *name, const char *value)
|
||||
{
|
||||
return real_value_hnd(cmd, dummy, name, value, PHP_INI_PERDIR);
|
||||
}
|
||||
|
||||
static const char *php_apache_admin_value_handler(cmd_parms *cmd, void *dummy, const char *name, const char *value)
|
||||
{
|
||||
return real_value_hnd(cmd, dummy, name, value, PHP_INI_SYSTEM);
|
||||
}
|
||||
|
||||
static const char *real_flag_hnd(cmd_parms *cmd, void *dummy, const char *arg1, const char *arg2, int status)
|
||||
{
|
||||
char bool_val[2];
|
||||
|
||||
if (!strcasecmp(arg2, "On") || (arg2[0] == '1' && arg2[1] == '\0')) {
|
||||
bool_val[0] = '1';
|
||||
} else {
|
||||
bool_val[0] = '0';
|
||||
}
|
||||
bool_val[1] = 0;
|
||||
|
||||
return real_value_hnd(cmd, dummy, arg1, bool_val, status);
|
||||
}
|
||||
|
||||
static const char *php_apache_flag_handler(cmd_parms *cmd, void *dummy, const char *name, const char *value)
|
||||
{
|
||||
return real_flag_hnd(cmd, dummy, name, value, PHP_INI_PERDIR);
|
||||
}
|
||||
|
||||
static const char *php_apache_admin_flag_handler(cmd_parms *cmd, void *dummy, const char *name, const char *value)
|
||||
{
|
||||
return real_flag_hnd(cmd, dummy, name, value, PHP_INI_SYSTEM);
|
||||
}
|
||||
|
||||
static const char *php_apache_phpini_set(cmd_parms *cmd, void *mconfig, const char *arg)
|
||||
{
|
||||
if (apache2_php_ini_path_override) {
|
||||
return "Only first PHPINIDir directive honored per configuration tree - subsequent ones ignored";
|
||||
}
|
||||
apache2_php_ini_path_override = ap_server_root_relative(cmd->pool, arg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static zend_bool should_overwrite_per_dir_entry(HashTable *target_ht, zval *zv, zend_hash_key *hash_key, void *pData)
|
||||
{
|
||||
php_dir_entry *new_per_dir_entry = Z_PTR_P(zv);
|
||||
php_dir_entry *orig_per_dir_entry;
|
||||
|
||||
if ((orig_per_dir_entry = zend_hash_find_ptr(target_ht, hash_key->key)) == NULL) {
|
||||
return 1; /* does not exist in dest, copy from source */
|
||||
}
|
||||
|
||||
if (new_per_dir_entry->status >= orig_per_dir_entry->status) {
|
||||
/* use new entry */
|
||||
phpapdebug((stderr, "ADDING/OVERWRITING %s (%d vs. %d)\n", ZSTR_VAL(hash_key->key), new_per_dir_entry->status, orig_per_dir_entry->status));
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void config_entry_ctor(zval *zv)
|
||||
{
|
||||
php_dir_entry *pe = (php_dir_entry*)Z_PTR_P(zv);
|
||||
php_dir_entry *npe = malloc(sizeof(php_dir_entry));
|
||||
|
||||
memcpy(npe, pe, sizeof(php_dir_entry));
|
||||
ZVAL_PTR(zv, npe);
|
||||
}
|
||||
|
||||
void *merge_php_config(apr_pool_t *p, void *base_conf, void *new_conf)
|
||||
{
|
||||
php_conf_rec *d = base_conf, *e = new_conf, *n = NULL;
|
||||
#ifdef ZTS
|
||||
zend_string *str;
|
||||
zval *data;
|
||||
#endif
|
||||
|
||||
n = create_php_config(p, "merge_php_config");
|
||||
/* copy old config */
|
||||
#ifdef ZTS
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL(&d->config, str, data) {
|
||||
zend_string *key;
|
||||
zval *new_entry;
|
||||
|
||||
/* Avoid sharing the non interned string among threads. */
|
||||
key = zend_string_dup(str, 1);
|
||||
|
||||
new_entry = zend_hash_add(&n->config, key, data);
|
||||
|
||||
config_entry_ctor(new_entry);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
#else
|
||||
zend_hash_copy(&n->config, &d->config, config_entry_ctor);
|
||||
#endif
|
||||
/* merge new config */
|
||||
phpapdebug((stderr, "Merge dir (%p)+(%p)=(%p)\n", base_conf, new_conf, n));
|
||||
zend_hash_merge_ex(&n->config, &e->config, config_entry_ctor, should_overwrite_per_dir_entry, NULL);
|
||||
return n;
|
||||
}
|
||||
|
||||
char *get_php_config(void *conf, char *name, size_t name_len)
|
||||
{
|
||||
php_conf_rec *d = conf;
|
||||
php_dir_entry *pe;
|
||||
|
||||
if ((pe = zend_hash_str_find_ptr(&d->config, name, name_len)) != NULL) {
|
||||
return pe->value;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void apply_config(void *dummy)
|
||||
{
|
||||
php_conf_rec *d = dummy;
|
||||
zend_string *str;
|
||||
php_dir_entry *data;
|
||||
|
||||
ZEND_HASH_FOREACH_STR_KEY_PTR(&d->config, str, data) {
|
||||
phpapdebug((stderr, "APPLYING (%s)(%s)\n", ZSTR_VAL(str), data->value));
|
||||
if (zend_alter_ini_entry_chars(str, data->value, data->value_len, data->status, data->htaccess?PHP_INI_STAGE_HTACCESS:PHP_INI_STAGE_ACTIVATE) == FAILURE) {
|
||||
phpapdebug((stderr, "..FAILED\n"));
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
|
||||
const command_rec php_dir_cmds[] =
|
||||
{
|
||||
AP_INIT_TAKE2("php_value", php_apache_value_handler, NULL, OR_OPTIONS, "PHP Value Modifier"),
|
||||
AP_INIT_TAKE2("php_flag", php_apache_flag_handler, NULL, OR_OPTIONS, "PHP Flag Modifier"),
|
||||
AP_INIT_TAKE2("php_admin_value", php_apache_admin_value_handler, NULL, ACCESS_CONF|RSRC_CONF, "PHP Value Modifier (Admin)"),
|
||||
AP_INIT_TAKE2("php_admin_flag", php_apache_admin_flag_handler, NULL, ACCESS_CONF|RSRC_CONF, "PHP Flag Modifier (Admin)"),
|
||||
AP_INIT_TAKE1("PHPINIDir", php_apache_phpini_set, NULL, RSRC_CONF, "Directory containing the php.ini file"),
|
||||
{NULL}
|
||||
};
|
||||
|
||||
static apr_status_t destroy_php_config(void *data)
|
||||
{
|
||||
php_conf_rec *d = data;
|
||||
|
||||
phpapdebug((stderr, "Destroying config %p\n", data));
|
||||
zend_hash_destroy(&d->config);
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
static void config_entry_dtor(zval *zv)
|
||||
{
|
||||
free((php_dir_entry*)Z_PTR_P(zv));
|
||||
}
|
||||
|
||||
void *create_php_config(apr_pool_t *p, char *dummy)
|
||||
{
|
||||
php_conf_rec *newx = (php_conf_rec *) apr_pcalloc(p, sizeof(*newx));
|
||||
|
||||
phpapdebug((stderr, "Creating new config (%p) for %s\n", newx, dummy));
|
||||
zend_hash_init(&newx->config, 0, NULL, config_entry_dtor, 1);
|
||||
apr_pool_cleanup_register(p, newx, destroy_php_config, apr_pool_cleanup_null);
|
||||
return (void *) newx;
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
PHP_ARG_WITH([apxs2],,
|
||||
[AS_HELP_STRING([[--with-apxs2[=FILE]]],
|
||||
[Build shared Apache 2 handler module. FILE is the optional pathname to
|
||||
the Apache apxs tool [apxs]])],
|
||||
[no],
|
||||
[no])
|
||||
|
||||
AC_MSG_CHECKING([for Apache 2 handler module support via DSO through APXS])
|
||||
|
||||
if test "$PHP_APXS2" != "no"; then
|
||||
if test "$PHP_APXS2" = "yes"; then
|
||||
APXS=apxs
|
||||
$APXS -q CFLAGS >/dev/null 2>&1
|
||||
if test "$?" != "0" && test -x /usr/sbin/apxs; then
|
||||
APXS=/usr/sbin/apxs
|
||||
fi
|
||||
else
|
||||
PHP_EXPAND_PATH($PHP_APXS2, APXS)
|
||||
fi
|
||||
|
||||
$APXS -q CFLAGS >/dev/null 2>&1
|
||||
if test "$?" != "0"; then
|
||||
AC_MSG_RESULT()
|
||||
AC_MSG_RESULT()
|
||||
AC_MSG_RESULT([Sorry, I cannot run apxs. Possible reasons follow:])
|
||||
AC_MSG_RESULT()
|
||||
AC_MSG_RESULT([1. Perl is not installed])
|
||||
AC_MSG_RESULT([2. apxs was not found. Try to pass the path using --with-apxs2=/path/to/apxs])
|
||||
AC_MSG_RESULT([3. Apache was not built using --enable-so (the apxs usage page is displayed)])
|
||||
AC_MSG_RESULT()
|
||||
AC_MSG_RESULT([The output of $APXS follows:])
|
||||
$APXS -q CFLAGS
|
||||
AC_MSG_ERROR([Aborting])
|
||||
fi
|
||||
|
||||
APXS_INCLUDEDIR=`$APXS -q INCLUDEDIR`
|
||||
APXS_BINDIR=`$APXS -q BINDIR`
|
||||
APXS_HTTPD=`$APXS -q SBINDIR`/`$APXS -q TARGET`
|
||||
APXS_CFLAGS=`$APXS -q CFLAGS`
|
||||
APU_BINDIR=`$APXS -q APU_BINDIR`
|
||||
APR_BINDIR=`$APXS -q APR_BINDIR`
|
||||
|
||||
dnl Pick up ap[ru]-N-config if using httpd >=2.1
|
||||
APR_CONFIG=`$APXS -q APR_CONFIG 2>/dev/null ||
|
||||
echo $APR_BINDIR/apr-config`
|
||||
APU_CONFIG=`$APXS -q APU_CONFIG 2>/dev/null ||
|
||||
echo $APU_BINDIR/apu-config`
|
||||
|
||||
APR_CFLAGS="`$APR_CONFIG --cppflags --includes`"
|
||||
APU_CFLAGS="`$APU_CONFIG --includes`"
|
||||
|
||||
for flag in $APXS_CFLAGS; do
|
||||
case $flag in
|
||||
-D*) APACHE_CPPFLAGS="$APACHE_CPPFLAGS $flag";;
|
||||
esac
|
||||
done
|
||||
|
||||
APACHE_CFLAGS="$APACHE_CPPFLAGS -I$APXS_INCLUDEDIR $APR_CFLAGS $APU_CFLAGS -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"
|
||||
|
||||
dnl Test that we're trying to configure with apache 2.x
|
||||
PHP_AP_EXTRACT_VERSION($APXS_HTTPD)
|
||||
if test "$APACHE_VERSION" -lt 2000044; then
|
||||
AC_MSG_ERROR([Please note that Apache version >= 2.0.44 is required])
|
||||
fi
|
||||
|
||||
APXS_LIBEXECDIR='$(INSTALL_ROOT)'`$APXS -q LIBEXECDIR`
|
||||
if test -z `$APXS -q SYSCONFDIR`; then
|
||||
INSTALL_IT="\$(mkinstalldirs) '$APXS_LIBEXECDIR' && \
|
||||
$APXS -S LIBEXECDIR='$APXS_LIBEXECDIR' \
|
||||
-i -n php"
|
||||
else
|
||||
APXS_SYSCONFDIR='$(INSTALL_ROOT)'`$APXS -q SYSCONFDIR`
|
||||
INSTALL_IT="\$(mkinstalldirs) '$APXS_LIBEXECDIR' && \
|
||||
\$(mkinstalldirs) '$APXS_SYSCONFDIR' && \
|
||||
$APXS -S LIBEXECDIR='$APXS_LIBEXECDIR' \
|
||||
-S SYSCONFDIR='$APXS_SYSCONFDIR' \
|
||||
-i -a -n php"
|
||||
fi
|
||||
|
||||
LIBPHP_CFLAGS="-shared"
|
||||
PHP_SUBST(LIBPHP_CFLAGS)
|
||||
|
||||
case $host_alias in
|
||||
*aix*)
|
||||
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-brtl -Wl,-bI:$APXS_LIBEXECDIR/httpd.exp"
|
||||
PHP_SELECT_SAPI(apache2handler, shared, mod_php.c sapi_apache2.c apache_config.c php_functions.c, $APACHE_CFLAGS)
|
||||
INSTALL_IT="$INSTALL_IT $SAPI_LIBTOOL"
|
||||
;;
|
||||
*darwin*)
|
||||
dnl When using bundles on Darwin, we must resolve all symbols. However, the
|
||||
dnl linker does not recursively look at the bundle loader and pull in its
|
||||
dnl dependencies. Therefore, we must pull in the APR and APR-util libraries.
|
||||
if test -x "$APR_CONFIG"; then
|
||||
MH_BUNDLE_FLAGS="`$APR_CONFIG --ldflags --link-ld --libs`"
|
||||
fi
|
||||
if test -x "$APU_CONFIG"; then
|
||||
MH_BUNDLE_FLAGS="`$APU_CONFIG --ldflags --link-ld --libs` $MH_BUNDLE_FLAGS"
|
||||
fi
|
||||
MH_BUNDLE_FLAGS="-bundle -bundle_loader $APXS_HTTPD $MH_BUNDLE_FLAGS"
|
||||
PHP_SUBST(MH_BUNDLE_FLAGS)
|
||||
PHP_SELECT_SAPI(apache2handler, bundle, mod_php.c sapi_apache2.c apache_config.c php_functions.c, $APACHE_CFLAGS)
|
||||
SAPI_SHARED=libs/libphp.so
|
||||
INSTALL_IT="$INSTALL_IT $SAPI_SHARED"
|
||||
;;
|
||||
*)
|
||||
PHP_SELECT_SAPI(apache2handler, shared, mod_php.c sapi_apache2.c apache_config.c php_functions.c, $APACHE_CFLAGS)
|
||||
INSTALL_IT="$INSTALL_IT $SAPI_LIBTOOL"
|
||||
;;
|
||||
esac
|
||||
|
||||
if test "$APACHE_VERSION" -lt 2004001; then
|
||||
APXS_MPM=`$APXS -q MPM_NAME`
|
||||
if test "$APXS_MPM" != "prefork" && test "$APXS_MPM" != "peruser" && test "$APXS_MPM" != "itk"; then
|
||||
PHP_BUILD_THREAD_SAFE
|
||||
fi
|
||||
else
|
||||
APACHE_THREADED_MPM=`$APXS_HTTPD -V 2>/dev/null | grep 'threaded:.*yes'`
|
||||
if test -n "$APACHE_THREADED_MPM"; then
|
||||
PHP_BUILD_THREAD_SAFE
|
||||
fi
|
||||
fi
|
||||
AC_MSG_RESULT(yes)
|
||||
PHP_SUBST(APXS)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
@@ -1,56 +0,0 @@
|
||||
// vim:ft=javascript
|
||||
|
||||
ARG_ENABLE('apache2handler', 'Build Apache 2.x handler', 'no');
|
||||
|
||||
if (PHP_APACHE2HANDLER != "no") {
|
||||
if (PHP_ZTS == "no") {
|
||||
WARNING("Apache 2.0 module requires an --enable-zts build of PHP on windows");
|
||||
} else if (CHECK_HEADER_ADD_INCLUDE("httpd.h", "CFLAGS_APACHE2HANDLER", PHP_PHP_BUILD + "\\include\\apache2") &&
|
||||
CHECK_LIB("libhttpd.lib", "apache2handler", PHP_PHP_BUILD + "\\lib\\apache2") &&
|
||||
CHECK_LIB("libapr.lib", "apache2handler", PHP_PHP_BUILD + "\\lib\\apache2") &&
|
||||
CHECK_LIB("libaprutil.lib", "apache2handler", PHP_PHP_BUILD + "\\lib\\apache2")
|
||||
) {
|
||||
SAPI('apache2handler', 'mod_php.c sapi_apache2.c apache_config.c php_functions.c',
|
||||
'php' + PHP_VERSION + 'apache2.dll',
|
||||
'/D PHP_APACHE2_EXPORTS /I win32 /DZEND_ENABLE_STATIC_TSRMLS_CACHE=1');
|
||||
} else {
|
||||
WARNING("Could not find apache2 libraries/headers");
|
||||
}
|
||||
}
|
||||
|
||||
ARG_ENABLE('apache2-2handler', 'Build Apache 2.2.x handler', 'no');
|
||||
|
||||
if (PHP_APACHE2_2HANDLER != "no") {
|
||||
if (PHP_ZTS == "no") {
|
||||
WARNING("Apache 2.2 module requires an --enable-zts build of PHP on windows");
|
||||
} else if (CHECK_HEADER_ADD_INCLUDE("httpd.h", "CFLAGS_APACHE2_2HANDLER", PHP_PHP_BUILD + "\\include\\apache2_2") &&
|
||||
CHECK_LIB("libhttpd.lib", "apache2_2handler", PHP_PHP_BUILD + "\\lib\\apache2_2") &&
|
||||
CHECK_LIB("libapr-1.lib", "apache2_2handler", PHP_PHP_BUILD + "\\lib\\apache2_2") &&
|
||||
CHECK_LIB("libaprutil-1.lib", "apache2_2handler", PHP_PHP_BUILD + "\\lib\\apache2_2")
|
||||
) {
|
||||
SAPI('apache2_2handler', 'mod_php.c sapi_apache2.c apache_config.c php_functions.c',
|
||||
'php' + PHP_VERSION + 'apache2_2.dll',
|
||||
'/D PHP_APACHE2_EXPORTS /I win32 /DZEND_ENABLE_STATIC_TSRMLS_CACHE=1',
|
||||
'sapi\\apache2_2handler');
|
||||
} else {
|
||||
WARNING("Could not find apache2.2 libraries/headers");
|
||||
}
|
||||
}
|
||||
|
||||
ARG_ENABLE('apache2-4handler', 'Build Apache 2.4.x handler', 'no');
|
||||
if (PHP_APACHE2_4HANDLER != "no") {
|
||||
if (PHP_ZTS == "no") {
|
||||
WARNING("Apache 2.4 module requires an --enable-zts build of PHP on windows");
|
||||
} else if (CHECK_HEADER_ADD_INCLUDE("httpd.h", "CFLAGS_APACHE2_4HANDLER", PHP_PHP_BUILD + "\\include\\apache2_4") &&
|
||||
CHECK_LIB("libhttpd.lib", "apache2_4handler", PHP_PHP_BUILD + "\\lib\\apache2_4") &&
|
||||
CHECK_LIB("libapr-1.lib", "apache2_4handler", PHP_PHP_BUILD + "\\lib\\apache2_4") &&
|
||||
CHECK_LIB("libaprutil-1.lib", "apache2_4handler", PHP_PHP_BUILD + "\\lib\\apache2_4")
|
||||
) {
|
||||
SAPI('apache2_4handler', 'mod_php.c sapi_apache2.c apache_config.c php_functions.c',
|
||||
'php' + PHP_VERSION + 'apache2_4.dll',
|
||||
'/D PHP_APACHE2_EXPORTS /I win32 /DZEND_ENABLE_STATIC_TSRMLS_CACHE=1',
|
||||
'sapi\\apache2handler');
|
||||
} else {
|
||||
WARNING("Could not find apache 2.4 libraries/headers");
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 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: Sascha Schumann <sascha@schumann.cx> |
|
||||
| Parts based on Apache 1.3 SAPI module by |
|
||||
| Rasmus Lerdorf and Zeev Suraski |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
|
||||
|
||||
#include "php.h"
|
||||
#ifdef strcasecmp
|
||||
# undef strcasecmp
|
||||
#endif
|
||||
#ifdef strncasecmp
|
||||
# undef strncasecmp
|
||||
#endif
|
||||
#include "php_apache.h"
|
||||
|
||||
AP_MODULE_DECLARE_DATA module php_module = {
|
||||
STANDARD20_MODULE_STUFF,
|
||||
create_php_config, /* create per-directory config structure */
|
||||
merge_php_config, /* merge per-directory config structures */
|
||||
NULL, /* create per-server config structure */
|
||||
NULL, /* merge per-server config structures */
|
||||
php_dir_cmds, /* command apr_table_t */
|
||||
php_ap2_register_hook /* register hooks */
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
php_module
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 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: Sascha Schumann <sascha@schumann.cx> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef PHP_APACHE_H
|
||||
#define PHP_APACHE_H
|
||||
|
||||
#include "httpd.h"
|
||||
#include "http_config.h"
|
||||
#include "http_core.h"
|
||||
#include "http_log.h"
|
||||
|
||||
#include "php.h"
|
||||
#include "main/php_streams.h"
|
||||
|
||||
/* Enable per-module logging in Apache 2.4+ */
|
||||
#ifdef APLOG_USE_MODULE
|
||||
APLOG_USE_MODULE(php);
|
||||
#endif
|
||||
|
||||
/* Declare this so we can get to it from outside the sapi_apache2.c file */
|
||||
extern module AP_MODULE_DECLARE_DATA php_module;
|
||||
|
||||
/* A way to specify the location of the php.ini dir in an apache directive */
|
||||
extern char *apache2_php_ini_path_override;
|
||||
|
||||
/* The server_context used by PHP */
|
||||
typedef struct php_struct {
|
||||
int state;
|
||||
request_rec *r;
|
||||
apr_bucket_brigade *brigade;
|
||||
/* stat structure of the current file */
|
||||
zend_stat_t finfo;
|
||||
/* Whether or not we've processed PHP in the output filters yet. */
|
||||
int request_processed;
|
||||
/* final content type */
|
||||
char *content_type;
|
||||
} php_struct;
|
||||
|
||||
void *merge_php_config(apr_pool_t *p, void *base_conf, void *new_conf);
|
||||
void *create_php_config(apr_pool_t *p, char *dummy);
|
||||
char *get_php_config(void *conf, char *name, size_t name_len);
|
||||
void apply_config(void *);
|
||||
extern const command_rec php_dir_cmds[];
|
||||
void php_ap2_register_hook(apr_pool_t *p);
|
||||
|
||||
#define APR_ARRAY_FOREACH_OPEN(arr, key, val) \
|
||||
{ \
|
||||
apr_table_entry_t *elts; \
|
||||
int i; \
|
||||
elts = (apr_table_entry_t *) arr->elts; \
|
||||
for (i = 0; i < arr->nelts; i++) { \
|
||||
key = elts[i].key; \
|
||||
val = elts[i].val;
|
||||
|
||||
#define APR_ARRAY_FOREACH_CLOSE() }}
|
||||
|
||||
typedef struct {
|
||||
zend_bool engine;
|
||||
zend_bool xbithack;
|
||||
zend_bool last_modified;
|
||||
} php_apache2_info_struct;
|
||||
|
||||
extern zend_module_entry apache2_module_entry;
|
||||
|
||||
#ifdef ZTS
|
||||
extern int php_apache2_info_id;
|
||||
#define AP2(v) ZEND_TSRMG(php_apache2_info_id, php_apache2_info_struct *, v)
|
||||
ZEND_TSRMLS_CACHE_EXTERN()
|
||||
#else
|
||||
extern php_apache2_info_struct php_apache2_info;
|
||||
#define AP2(v) (php_apache2_info.v)
|
||||
#endif
|
||||
|
||||
/* fix for gcc4 visibility patch */
|
||||
#ifndef PHP_WIN32
|
||||
# undef AP_MODULE_DECLARE_DATA
|
||||
# define AP_MODULE_DECLARE_DATA PHPAPI
|
||||
#endif
|
||||
|
||||
#endif /* PHP_APACHE_H */
|
||||
@@ -1,509 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 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: Sascha Schumann <sascha@schumann.cx> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
|
||||
|
||||
#include "php.h"
|
||||
#ifdef strcasecmp
|
||||
# undef strcasecmp
|
||||
#endif
|
||||
#ifdef strncasecmp
|
||||
# undef strncasecmp
|
||||
#endif
|
||||
#include "zend_smart_str.h"
|
||||
#include "ext/standard/info.h"
|
||||
#include "ext/standard/head.h"
|
||||
#include "php_ini.h"
|
||||
#include "SAPI.h"
|
||||
|
||||
#define CORE_PRIVATE
|
||||
#include "apr_strings.h"
|
||||
#include "apr_time.h"
|
||||
#include "ap_config.h"
|
||||
#include "util_filter.h"
|
||||
#include "httpd.h"
|
||||
#include "http_config.h"
|
||||
#include "http_request.h"
|
||||
#include "http_core.h"
|
||||
#include "http_protocol.h"
|
||||
#include "http_log.h"
|
||||
#include "http_main.h"
|
||||
#include "util_script.h"
|
||||
#include "http_core.h"
|
||||
#include "ap_mpm.h"
|
||||
#ifndef PHP_WIN32
|
||||
#include "unixd.h"
|
||||
#endif
|
||||
|
||||
#include "php_apache.h"
|
||||
#include "php_functions_arginfo.h"
|
||||
|
||||
#ifdef ZTS
|
||||
int php_apache2_info_id;
|
||||
#else
|
||||
php_apache2_info_struct php_apache2_info;
|
||||
#endif
|
||||
|
||||
#define SECTION(name) PUTS("<h2>" name "</h2>\n")
|
||||
|
||||
static request_rec *php_apache_lookup_uri(char *filename)
|
||||
{
|
||||
php_struct *ctx = SG(server_context);
|
||||
|
||||
if (!filename || !ctx || !ctx->r) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ap_sub_req_lookup_uri(filename, ctx->r, ctx->r->output_filters);
|
||||
}
|
||||
|
||||
/* {{{ Perform an apache sub-request */
|
||||
PHP_FUNCTION(virtual)
|
||||
{
|
||||
char *filename;
|
||||
size_t filename_len;
|
||||
request_rec *rr;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &filename, &filename_len) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
if (!(rr = php_apache_lookup_uri(filename))) {
|
||||
php_error_docref(NULL, E_WARNING, "Unable to include '%s' - URI lookup failed", filename);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (rr->status != HTTP_OK) {
|
||||
php_error_docref(NULL, E_WARNING, "Unable to include '%s' - error finding URI", filename);
|
||||
ap_destroy_sub_req(rr);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* Flush everything. */
|
||||
php_output_end_all();
|
||||
php_header();
|
||||
|
||||
/* Ensure that the ap_r* layer for the main request is flushed, to
|
||||
* work around http://issues.apache.org/bugzilla/show_bug.cgi?id=17629 */
|
||||
ap_rflush(rr->main);
|
||||
|
||||
if (ap_run_sub_req(rr)) {
|
||||
php_error_docref(NULL, E_WARNING, "Unable to include '%s' - request execution failed", filename);
|
||||
ap_destroy_sub_req(rr);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
ap_destroy_sub_req(rr);
|
||||
RETURN_TRUE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
#define ADD_LONG(name) \
|
||||
add_property_long(return_value, #name, rr->name)
|
||||
#define ADD_TIME(name) \
|
||||
add_property_long(return_value, #name, apr_time_sec(rr->name));
|
||||
#define ADD_STRING(name) \
|
||||
if (rr->name) add_property_string(return_value, #name, (char *) rr->name)
|
||||
|
||||
PHP_FUNCTION(apache_lookup_uri)
|
||||
{
|
||||
request_rec *rr;
|
||||
char *filename;
|
||||
size_t filename_len;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &filename, &filename_len) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
if (!(rr = php_apache_lookup_uri(filename))) {
|
||||
php_error_docref(NULL, E_WARNING, "Unable to include '%s' - URI lookup failed", filename);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
if (rr->status == HTTP_OK) {
|
||||
object_init(return_value);
|
||||
|
||||
ADD_LONG(status);
|
||||
ADD_STRING(the_request);
|
||||
ADD_STRING(status_line);
|
||||
ADD_STRING(method);
|
||||
ADD_TIME(mtime);
|
||||
ADD_LONG(clength);
|
||||
#if MODULE_MAGIC_NUMBER < 20020506
|
||||
ADD_STRING(boundary);
|
||||
#endif
|
||||
ADD_STRING(range);
|
||||
ADD_LONG(chunked);
|
||||
ADD_STRING(content_type);
|
||||
ADD_STRING(handler);
|
||||
ADD_LONG(no_cache);
|
||||
ADD_LONG(no_local_copy);
|
||||
ADD_STRING(unparsed_uri);
|
||||
ADD_STRING(uri);
|
||||
ADD_STRING(filename);
|
||||
ADD_STRING(path_info);
|
||||
ADD_STRING(args);
|
||||
ADD_LONG(allowed);
|
||||
ADD_LONG(sent_bodyct);
|
||||
ADD_LONG(bytes_sent);
|
||||
ADD_LONG(mtime);
|
||||
ADD_TIME(request_time);
|
||||
|
||||
ap_destroy_sub_req(rr);
|
||||
return;
|
||||
}
|
||||
|
||||
php_error_docref(NULL, E_WARNING, "Unable to include '%s' - error finding URI", filename);
|
||||
ap_destroy_sub_req(rr);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
/* {{{ Fetch all HTTP request headers */
|
||||
PHP_FUNCTION(apache_request_headers)
|
||||
{
|
||||
php_struct *ctx;
|
||||
const apr_array_header_t *arr;
|
||||
char *key, *val;
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
array_init(return_value);
|
||||
|
||||
ctx = SG(server_context);
|
||||
arr = apr_table_elts(ctx->r->headers_in);
|
||||
|
||||
APR_ARRAY_FOREACH_OPEN(arr, key, val)
|
||||
if (!val) val = "";
|
||||
add_assoc_string(return_value, key, val);
|
||||
APR_ARRAY_FOREACH_CLOSE()
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Fetch all HTTP response headers */
|
||||
PHP_FUNCTION(apache_response_headers)
|
||||
{
|
||||
php_struct *ctx;
|
||||
const apr_array_header_t *arr;
|
||||
char *key, *val;
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
array_init(return_value);
|
||||
|
||||
ctx = SG(server_context);
|
||||
arr = apr_table_elts(ctx->r->headers_out);
|
||||
|
||||
APR_ARRAY_FOREACH_OPEN(arr, key, val)
|
||||
if (!val) val = "";
|
||||
add_assoc_string(return_value, key, val);
|
||||
APR_ARRAY_FOREACH_CLOSE()
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Get and set Apache request notes */
|
||||
PHP_FUNCTION(apache_note)
|
||||
{
|
||||
php_struct *ctx;
|
||||
char *note_name, *note_val = NULL;
|
||||
size_t note_name_len, note_val_len;
|
||||
char *old_note_val=NULL;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s!", ¬e_name, ¬e_name_len, ¬e_val, ¬e_val_len) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
ctx = SG(server_context);
|
||||
|
||||
old_note_val = (char *) apr_table_get(ctx->r->notes, note_name);
|
||||
|
||||
if (note_val) {
|
||||
apr_table_set(ctx->r->notes, note_name, note_val);
|
||||
}
|
||||
|
||||
if (old_note_val) {
|
||||
RETURN_STRING(old_note_val);
|
||||
}
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ Set an Apache subprocess_env variable */
|
||||
/*
|
||||
* XXX this doesn't look right. shouldn't it be the parent ?*/
|
||||
PHP_FUNCTION(apache_setenv)
|
||||
{
|
||||
php_struct *ctx;
|
||||
char *variable=NULL, *string_val=NULL;
|
||||
size_t variable_len, string_val_len;
|
||||
zend_bool walk_to_top = 0;
|
||||
int arg_count = ZEND_NUM_ARGS();
|
||||
request_rec *r;
|
||||
|
||||
if (zend_parse_parameters(arg_count, "ss|b", &variable, &variable_len, &string_val, &string_val_len, &walk_to_top) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
ctx = SG(server_context);
|
||||
|
||||
r = ctx->r;
|
||||
if (arg_count == 3) {
|
||||
if (walk_to_top) {
|
||||
while(r->prev) {
|
||||
r = r->prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apr_table_set(r->subprocess_env, variable, string_val);
|
||||
|
||||
RETURN_TRUE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Get an Apache subprocess_env variable */
|
||||
/*
|
||||
* XXX: shouldn't this be the parent not the 'prev'
|
||||
*/
|
||||
PHP_FUNCTION(apache_getenv)
|
||||
{
|
||||
php_struct *ctx;
|
||||
char *variable;
|
||||
size_t variable_len;
|
||||
zend_bool walk_to_top = 0;
|
||||
int arg_count = ZEND_NUM_ARGS();
|
||||
char *env_val=NULL;
|
||||
request_rec *r;
|
||||
|
||||
if (zend_parse_parameters(arg_count, "s|b", &variable, &variable_len, &walk_to_top) == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
ctx = SG(server_context);
|
||||
|
||||
r = ctx->r;
|
||||
if (arg_count == 2) {
|
||||
if (walk_to_top) {
|
||||
while(r->prev) {
|
||||
r = r->prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
env_val = (char*) apr_table_get(r->subprocess_env, variable);
|
||||
|
||||
if (env_val != NULL) {
|
||||
RETURN_STRING(env_val);
|
||||
}
|
||||
|
||||
RETURN_FALSE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static char *php_apache_get_version()
|
||||
{
|
||||
#if MODULE_MAGIC_NUMBER_MAJOR >= 20060905
|
||||
return (char *) ap_get_server_banner();
|
||||
#else
|
||||
return (char *) ap_get_server_version();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* {{{ Fetch Apache version */
|
||||
PHP_FUNCTION(apache_get_version)
|
||||
{
|
||||
char *apv = php_apache_get_version();
|
||||
|
||||
if (apv && *apv) {
|
||||
RETURN_STRING(apv);
|
||||
} else {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Get a list of loaded Apache modules */
|
||||
PHP_FUNCTION(apache_get_modules)
|
||||
{
|
||||
int n;
|
||||
char *p;
|
||||
|
||||
array_init(return_value);
|
||||
|
||||
for (n = 0; ap_loaded_modules[n]; ++n) {
|
||||
char *s = (char *) ap_loaded_modules[n]->name;
|
||||
if ((p = strchr(s, '.'))) {
|
||||
add_next_index_stringl(return_value, s, (p - s));
|
||||
} else {
|
||||
add_next_index_string(return_value, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
PHP_MINFO_FUNCTION(apache)
|
||||
{
|
||||
char *apv = php_apache_get_version();
|
||||
smart_str tmp1 = {0};
|
||||
char tmp[1024];
|
||||
int n, max_requests;
|
||||
char *p;
|
||||
server_rec *serv = ((php_struct *) SG(server_context))->r->server;
|
||||
#ifndef PHP_WIN32
|
||||
# if MODULE_MAGIC_NUMBER_MAJOR >= 20081201
|
||||
AP_DECLARE_DATA extern unixd_config_rec ap_unixd_config;
|
||||
# else
|
||||
AP_DECLARE_DATA extern unixd_config_rec unixd_config;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
for (n = 0; ap_loaded_modules[n]; ++n) {
|
||||
char *s = (char *) ap_loaded_modules[n]->name;
|
||||
if ((p = strchr(s, '.'))) {
|
||||
smart_str_appendl(&tmp1, s, (p - s));
|
||||
} else {
|
||||
smart_str_appends(&tmp1, s);
|
||||
}
|
||||
smart_str_appendc(&tmp1, ' ');
|
||||
}
|
||||
if (tmp1.s) {
|
||||
if (tmp1.s->len > 0) {
|
||||
tmp1.s->val[tmp1.s->len - 1] = '\0';
|
||||
} else {
|
||||
tmp1.s->val[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
php_info_print_table_start();
|
||||
if (apv && *apv) {
|
||||
php_info_print_table_row(2, "Apache Version", apv);
|
||||
}
|
||||
snprintf(tmp, sizeof(tmp), "%d", MODULE_MAGIC_NUMBER);
|
||||
php_info_print_table_row(2, "Apache API Version", tmp);
|
||||
|
||||
if (serv->server_admin && *(serv->server_admin)) {
|
||||
php_info_print_table_row(2, "Server Administrator", serv->server_admin);
|
||||
}
|
||||
|
||||
snprintf(tmp, sizeof(tmp), "%s:%u", serv->server_hostname, serv->port);
|
||||
php_info_print_table_row(2, "Hostname:Port", tmp);
|
||||
|
||||
#ifndef PHP_WIN32
|
||||
#if MODULE_MAGIC_NUMBER_MAJOR >= 20081201
|
||||
snprintf(tmp, sizeof(tmp), "%s(%d)/%d", ap_unixd_config.user_name, ap_unixd_config.user_id, ap_unixd_config.group_id);
|
||||
#else
|
||||
snprintf(tmp, sizeof(tmp), "%s(%d)/%d", unixd_config.user_name, unixd_config.user_id, unixd_config.group_id);
|
||||
#endif
|
||||
php_info_print_table_row(2, "User/Group", tmp);
|
||||
#endif
|
||||
|
||||
ap_mpm_query(AP_MPMQ_MAX_REQUESTS_DAEMON, &max_requests);
|
||||
snprintf(tmp, sizeof(tmp), "Per Child: %d - Keep Alive: %s - Max Per Connection: %d", max_requests, (serv->keep_alive ? "on":"off"), serv->keep_alive_max);
|
||||
php_info_print_table_row(2, "Max Requests", tmp);
|
||||
|
||||
apr_snprintf(tmp, sizeof tmp,
|
||||
"Connection: %" APR_TIME_T_FMT " - Keep-Alive: %" APR_TIME_T_FMT,
|
||||
apr_time_sec(serv->timeout), apr_time_sec(serv->keep_alive_timeout));
|
||||
php_info_print_table_row(2, "Timeouts", tmp);
|
||||
|
||||
php_info_print_table_row(2, "Virtual Server", (serv->is_virtual ? "Yes" : "No"));
|
||||
php_info_print_table_row(2, "Server Root", ap_server_root);
|
||||
php_info_print_table_row(2, "Loaded Modules", tmp1.s->val);
|
||||
|
||||
smart_str_free(&tmp1);
|
||||
php_info_print_table_end();
|
||||
|
||||
DISPLAY_INI_ENTRIES();
|
||||
|
||||
{
|
||||
const apr_array_header_t *arr = apr_table_elts(((php_struct *) SG(server_context))->r->subprocess_env);
|
||||
char *key, *val;
|
||||
|
||||
SECTION("Apache Environment");
|
||||
php_info_print_table_start();
|
||||
php_info_print_table_header(2, "Variable", "Value");
|
||||
APR_ARRAY_FOREACH_OPEN(arr, key, val)
|
||||
if (!val) {
|
||||
val = "";
|
||||
}
|
||||
php_info_print_table_row(2, key, val);
|
||||
APR_ARRAY_FOREACH_CLOSE()
|
||||
|
||||
php_info_print_table_end();
|
||||
|
||||
SECTION("HTTP Headers Information");
|
||||
php_info_print_table_start();
|
||||
php_info_print_table_colspan_header(2, "HTTP Request Headers");
|
||||
php_info_print_table_row(2, "HTTP Request", ((php_struct *) SG(server_context))->r->the_request);
|
||||
|
||||
arr = apr_table_elts(((php_struct *) SG(server_context))->r->headers_in);
|
||||
APR_ARRAY_FOREACH_OPEN(arr, key, val)
|
||||
if (!val) {
|
||||
val = "";
|
||||
}
|
||||
php_info_print_table_row(2, key, val);
|
||||
APR_ARRAY_FOREACH_CLOSE()
|
||||
|
||||
php_info_print_table_colspan_header(2, "HTTP Response Headers");
|
||||
arr = apr_table_elts(((php_struct *) SG(server_context))->r->headers_out);
|
||||
APR_ARRAY_FOREACH_OPEN(arr, key, val)
|
||||
if (!val) {
|
||||
val = "";
|
||||
}
|
||||
php_info_print_table_row(2, key, val);
|
||||
APR_ARRAY_FOREACH_CLOSE()
|
||||
|
||||
php_info_print_table_end();
|
||||
}
|
||||
}
|
||||
|
||||
PHP_INI_BEGIN()
|
||||
STD_PHP_INI_BOOLEAN("xbithack", "0", PHP_INI_ALL, OnUpdateBool, xbithack, php_apache2_info_struct, php_apache2_info)
|
||||
STD_PHP_INI_BOOLEAN("engine", "1", PHP_INI_ALL, OnUpdateBool, engine, php_apache2_info_struct, php_apache2_info)
|
||||
STD_PHP_INI_BOOLEAN("last_modified", "0", PHP_INI_ALL, OnUpdateBool, last_modified, php_apache2_info_struct, php_apache2_info)
|
||||
PHP_INI_END()
|
||||
|
||||
static PHP_MINIT_FUNCTION(apache)
|
||||
{
|
||||
#ifdef ZTS
|
||||
ts_allocate_id(&php_apache2_info_id, sizeof(php_apache2_info_struct), (ts_allocate_ctor) NULL, NULL);
|
||||
#endif
|
||||
REGISTER_INI_ENTRIES();
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static PHP_MSHUTDOWN_FUNCTION(apache)
|
||||
{
|
||||
UNREGISTER_INI_ENTRIES();
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
zend_module_entry php_apache_module = {
|
||||
STANDARD_MODULE_HEADER,
|
||||
"apache2handler",
|
||||
ext_functions,
|
||||
PHP_MINIT(apache),
|
||||
PHP_MSHUTDOWN(apache),
|
||||
NULL,
|
||||
NULL,
|
||||
PHP_MINFO(apache),
|
||||
PHP_VERSION,
|
||||
STANDARD_MODULE_PROPERTIES
|
||||
};
|
||||
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
|
||||
/** @generate-function-entries */
|
||||
|
||||
function apache_lookup_uri(string $filename): object|false {}
|
||||
|
||||
function virtual(string $uri): bool {}
|
||||
|
||||
function apache_request_headers(): array {}
|
||||
|
||||
/** @alias apache_request_headers */
|
||||
function getallheaders(): array {}
|
||||
|
||||
function apache_response_headers(): array {}
|
||||
|
||||
function apache_note(string $note_name, ?string $note_value = null): string|false {}
|
||||
|
||||
function apache_setenv(string $variable, string $value, bool $walk_to_top = false): bool {}
|
||||
|
||||
function apache_getenv(string $variable, bool $walk_to_top = false): string|false {}
|
||||
|
||||
function apache_get_version(): string|false {}
|
||||
|
||||
function apache_get_modules(): array {}
|
||||
@@ -1,64 +0,0 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 2e2e63b5c845bb74309b2b3e52ca5a3d76f2c80b */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_apache_lookup_uri, 0, 1, MAY_BE_OBJECT|MAY_BE_FALSE)
|
||||
ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_virtual, 0, 1, _IS_BOOL, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, uri, IS_STRING, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_apache_request_headers, 0, 0, IS_ARRAY, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_getallheaders arginfo_apache_request_headers
|
||||
|
||||
#define arginfo_apache_response_headers arginfo_apache_request_headers
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_apache_note, 0, 1, MAY_BE_STRING|MAY_BE_FALSE)
|
||||
ZEND_ARG_TYPE_INFO(0, note_name, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, note_value, IS_STRING, 1, "null")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_apache_setenv, 0, 2, _IS_BOOL, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, variable, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, walk_to_top, _IS_BOOL, 0, "false")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_apache_getenv, 0, 1, MAY_BE_STRING|MAY_BE_FALSE)
|
||||
ZEND_ARG_TYPE_INFO(0, variable, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, walk_to_top, _IS_BOOL, 0, "false")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_apache_get_version, 0, 0, MAY_BE_STRING|MAY_BE_FALSE)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_apache_get_modules arginfo_apache_request_headers
|
||||
|
||||
|
||||
ZEND_FUNCTION(apache_lookup_uri);
|
||||
ZEND_FUNCTION(virtual);
|
||||
ZEND_FUNCTION(apache_request_headers);
|
||||
ZEND_FUNCTION(apache_response_headers);
|
||||
ZEND_FUNCTION(apache_note);
|
||||
ZEND_FUNCTION(apache_setenv);
|
||||
ZEND_FUNCTION(apache_getenv);
|
||||
ZEND_FUNCTION(apache_get_version);
|
||||
ZEND_FUNCTION(apache_get_modules);
|
||||
|
||||
|
||||
static const zend_function_entry ext_functions[] = {
|
||||
ZEND_FE(apache_lookup_uri, arginfo_apache_lookup_uri)
|
||||
ZEND_FE(virtual, arginfo_virtual)
|
||||
ZEND_FE(apache_request_headers, arginfo_apache_request_headers)
|
||||
ZEND_FALIAS(getallheaders, apache_request_headers, arginfo_getallheaders)
|
||||
ZEND_FE(apache_response_headers, arginfo_apache_response_headers)
|
||||
ZEND_FE(apache_note, arginfo_apache_note)
|
||||
ZEND_FE(apache_setenv, arginfo_apache_setenv)
|
||||
ZEND_FE(apache_getenv, arginfo_apache_getenv)
|
||||
ZEND_FE(apache_get_version, arginfo_apache_get_version)
|
||||
ZEND_FE(apache_get_modules, arginfo_apache_get_modules)
|
||||
ZEND_FE_END
|
||||
};
|
||||
@@ -1,758 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 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: Sascha Schumann <sascha@schumann.cx> |
|
||||
| Parts based on Apache 1.3 SAPI module by |
|
||||
| Rasmus Lerdorf and Zeev Suraski |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
|
||||
|
||||
#include "php.h"
|
||||
#ifdef strcasecmp
|
||||
# undef strcasecmp
|
||||
#endif
|
||||
#ifdef strncasecmp
|
||||
# undef strncasecmp
|
||||
#endif
|
||||
#include "php_main.h"
|
||||
#include "php_ini.h"
|
||||
#include "php_variables.h"
|
||||
#include "SAPI.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "zend_smart_str.h"
|
||||
#include "ext/standard/php_standard.h"
|
||||
|
||||
#include "apr_strings.h"
|
||||
#include "ap_config.h"
|
||||
#include "util_filter.h"
|
||||
#include "httpd.h"
|
||||
#include "http_config.h"
|
||||
#include "http_request.h"
|
||||
#include "http_core.h"
|
||||
#include "http_protocol.h"
|
||||
#include "http_log.h"
|
||||
#include "http_main.h"
|
||||
#include "util_script.h"
|
||||
#include "http_core.h"
|
||||
#include "ap_mpm.h"
|
||||
|
||||
#include "php_apache.h"
|
||||
|
||||
/* UnixWare define shutdown to _shutdown, which causes problems later
|
||||
* on when using a structure member named shutdown. Since this source
|
||||
* file does not use the system call shutdown, it is safe to #undef it.
|
||||
*/
|
||||
#undef shutdown
|
||||
|
||||
#define PHP_MAGIC_TYPE "application/x-httpd-php"
|
||||
#define PHP_SOURCE_MAGIC_TYPE "application/x-httpd-php-source"
|
||||
#define PHP_SCRIPT "php-script"
|
||||
|
||||
/* A way to specify the location of the php.ini dir in an apache directive */
|
||||
char *apache2_php_ini_path_override = NULL;
|
||||
#if defined(PHP_WIN32) && defined(ZTS)
|
||||
ZEND_TSRMLS_CACHE_DEFINE()
|
||||
#endif
|
||||
|
||||
static size_t
|
||||
php_apache_sapi_ub_write(const char *str, size_t str_length)
|
||||
{
|
||||
request_rec *r;
|
||||
php_struct *ctx;
|
||||
|
||||
ctx = SG(server_context);
|
||||
r = ctx->r;
|
||||
|
||||
if (ap_rwrite(str, str_length, r) < 0) {
|
||||
php_handle_aborted_connection();
|
||||
}
|
||||
|
||||
return str_length; /* we always consume all the data passed to us. */
|
||||
}
|
||||
|
||||
static int
|
||||
php_apache_sapi_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers)
|
||||
{
|
||||
php_struct *ctx;
|
||||
char *val, *ptr;
|
||||
|
||||
ctx = SG(server_context);
|
||||
|
||||
switch (op) {
|
||||
case SAPI_HEADER_DELETE:
|
||||
apr_table_unset(ctx->r->headers_out, sapi_header->header);
|
||||
return 0;
|
||||
|
||||
case SAPI_HEADER_DELETE_ALL:
|
||||
apr_table_clear(ctx->r->headers_out);
|
||||
return 0;
|
||||
|
||||
case SAPI_HEADER_ADD:
|
||||
case SAPI_HEADER_REPLACE:
|
||||
val = strchr(sapi_header->header, ':');
|
||||
|
||||
if (!val) {
|
||||
return 0;
|
||||
}
|
||||
ptr = val;
|
||||
|
||||
*val = '\0';
|
||||
|
||||
do {
|
||||
val++;
|
||||
} while (*val == ' ');
|
||||
|
||||
if (!strcasecmp(sapi_header->header, "content-type")) {
|
||||
if (ctx->content_type) {
|
||||
efree(ctx->content_type);
|
||||
}
|
||||
ctx->content_type = estrdup(val);
|
||||
} else if (!strcasecmp(sapi_header->header, "content-length")) {
|
||||
apr_off_t clen = 0;
|
||||
|
||||
if (APR_SUCCESS != apr_strtoff(&clen, val, (char **) NULL, 10)) {
|
||||
/* We'll fall back to strtol, since that's what we used to
|
||||
* do anyway. */
|
||||
clen = (apr_off_t) strtol(val, (char **) NULL, 10);
|
||||
}
|
||||
|
||||
ap_set_content_length(ctx->r, clen);
|
||||
} else if (op == SAPI_HEADER_REPLACE) {
|
||||
apr_table_set(ctx->r->headers_out, sapi_header->header, val);
|
||||
} else {
|
||||
apr_table_add(ctx->r->headers_out, sapi_header->header, val);
|
||||
}
|
||||
|
||||
*ptr = ':';
|
||||
|
||||
return SAPI_HEADER_ADD;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
php_apache_sapi_send_headers(sapi_headers_struct *sapi_headers)
|
||||
{
|
||||
php_struct *ctx = SG(server_context);
|
||||
const char *sline = SG(sapi_headers).http_status_line;
|
||||
|
||||
ctx->r->status = SG(sapi_headers).http_response_code;
|
||||
|
||||
/* httpd requires that r->status_line is set to the first digit of
|
||||
* the status-code: */
|
||||
if (sline && strlen(sline) > 12 && strncmp(sline, "HTTP/1.", 7) == 0 && sline[8] == ' ') {
|
||||
ctx->r->status_line = apr_pstrdup(ctx->r->pool, sline + 9);
|
||||
ctx->r->proto_num = 1000 + (sline[7]-'0');
|
||||
if ((sline[7]-'0') == 0) {
|
||||
apr_table_set(ctx->r->subprocess_env, "force-response-1.0", "true");
|
||||
}
|
||||
}
|
||||
|
||||
/* call ap_set_content_type only once, else each time we call it,
|
||||
configured output filters for that content type will be added */
|
||||
if (!ctx->content_type) {
|
||||
ctx->content_type = sapi_get_default_content_type();
|
||||
}
|
||||
ap_set_content_type(ctx->r, apr_pstrdup(ctx->r->pool, ctx->content_type));
|
||||
efree(ctx->content_type);
|
||||
ctx->content_type = NULL;
|
||||
|
||||
return SAPI_HEADER_SENT_SUCCESSFULLY;
|
||||
}
|
||||
|
||||
static apr_size_t
|
||||
php_apache_sapi_read_post(char *buf, size_t count_bytes)
|
||||
{
|
||||
apr_size_t len, tlen=0;
|
||||
php_struct *ctx = SG(server_context);
|
||||
request_rec *r;
|
||||
apr_bucket_brigade *brigade;
|
||||
|
||||
r = ctx->r;
|
||||
brigade = ctx->brigade;
|
||||
len = count_bytes;
|
||||
|
||||
/*
|
||||
* This loop is needed because ap_get_brigade() can return us partial data
|
||||
* which would cause premature termination of request read. Therefor we
|
||||
* need to make sure that if data is available we fill the buffer completely.
|
||||
*/
|
||||
|
||||
while (ap_get_brigade(r->input_filters, brigade, AP_MODE_READBYTES, APR_BLOCK_READ, len) == APR_SUCCESS) {
|
||||
apr_brigade_flatten(brigade, buf, &len);
|
||||
apr_brigade_cleanup(brigade);
|
||||
tlen += len;
|
||||
if (tlen == count_bytes || !len) {
|
||||
break;
|
||||
}
|
||||
buf += len;
|
||||
len = count_bytes - tlen;
|
||||
}
|
||||
|
||||
return tlen;
|
||||
}
|
||||
|
||||
static zend_stat_t*
|
||||
php_apache_sapi_get_stat(void)
|
||||
{
|
||||
php_struct *ctx = SG(server_context);
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
ctx->finfo.st_uid = 0;
|
||||
ctx->finfo.st_gid = 0;
|
||||
#else
|
||||
ctx->finfo.st_uid = ctx->r->finfo.user;
|
||||
ctx->finfo.st_gid = ctx->r->finfo.group;
|
||||
#endif
|
||||
ctx->finfo.st_dev = ctx->r->finfo.device;
|
||||
ctx->finfo.st_ino = ctx->r->finfo.inode;
|
||||
ctx->finfo.st_atime = apr_time_sec(ctx->r->finfo.atime);
|
||||
ctx->finfo.st_mtime = apr_time_sec(ctx->r->finfo.mtime);
|
||||
ctx->finfo.st_ctime = apr_time_sec(ctx->r->finfo.ctime);
|
||||
ctx->finfo.st_size = ctx->r->finfo.size;
|
||||
ctx->finfo.st_nlink = ctx->r->finfo.nlink;
|
||||
|
||||
return &ctx->finfo;
|
||||
}
|
||||
|
||||
static char *
|
||||
php_apache_sapi_read_cookies(void)
|
||||
{
|
||||
php_struct *ctx = SG(server_context);
|
||||
const char *http_cookie;
|
||||
|
||||
http_cookie = apr_table_get(ctx->r->headers_in, "cookie");
|
||||
|
||||
/* The SAPI interface should use 'const char *' */
|
||||
return (char *) http_cookie;
|
||||
}
|
||||
|
||||
static char *
|
||||
php_apache_sapi_getenv(const char *name, size_t name_len)
|
||||
{
|
||||
php_struct *ctx = SG(server_context);
|
||||
const char *env_var;
|
||||
|
||||
if (ctx == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
env_var = apr_table_get(ctx->r->subprocess_env, name);
|
||||
|
||||
return (char *) env_var;
|
||||
}
|
||||
|
||||
static void
|
||||
php_apache_sapi_register_variables(zval *track_vars_array)
|
||||
{
|
||||
php_struct *ctx = SG(server_context);
|
||||
const apr_array_header_t *arr = apr_table_elts(ctx->r->subprocess_env);
|
||||
char *key, *val;
|
||||
size_t new_val_len;
|
||||
|
||||
APR_ARRAY_FOREACH_OPEN(arr, key, val)
|
||||
if (!val) {
|
||||
val = "";
|
||||
}
|
||||
if (sapi_module.input_filter(PARSE_SERVER, key, &val, strlen(val), &new_val_len)) {
|
||||
php_register_variable_safe(key, val, new_val_len, track_vars_array);
|
||||
}
|
||||
APR_ARRAY_FOREACH_CLOSE()
|
||||
|
||||
if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &ctx->r->uri, strlen(ctx->r->uri), &new_val_len)) {
|
||||
php_register_variable_safe("PHP_SELF", ctx->r->uri, new_val_len, track_vars_array);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
php_apache_sapi_flush(void *server_context)
|
||||
{
|
||||
php_struct *ctx;
|
||||
request_rec *r;
|
||||
|
||||
ctx = server_context;
|
||||
|
||||
/* If we haven't registered a server_context yet,
|
||||
* then don't bother flushing. */
|
||||
if (!server_context) {
|
||||
return;
|
||||
}
|
||||
|
||||
r = ctx->r;
|
||||
|
||||
sapi_send_headers();
|
||||
|
||||
r->status = SG(sapi_headers).http_response_code;
|
||||
SG(headers_sent) = 1;
|
||||
|
||||
if (ap_rflush(r) < 0 || r->connection->aborted) {
|
||||
php_handle_aborted_connection();
|
||||
}
|
||||
}
|
||||
|
||||
static void php_apache_sapi_log_message(const char *msg, int syslog_type_int)
|
||||
{
|
||||
php_struct *ctx;
|
||||
int aplog_type = APLOG_ERR;
|
||||
|
||||
ctx = SG(server_context);
|
||||
|
||||
switch (syslog_type_int) {
|
||||
#if LOG_EMERG != LOG_CRIT
|
||||
case LOG_EMERG:
|
||||
aplog_type = APLOG_EMERG;
|
||||
break;
|
||||
#endif
|
||||
#if LOG_ALERT != LOG_CRIT
|
||||
case LOG_ALERT:
|
||||
aplog_type = APLOG_ALERT;
|
||||
break;
|
||||
#endif
|
||||
case LOG_CRIT:
|
||||
aplog_type = APLOG_CRIT;
|
||||
break;
|
||||
case LOG_ERR:
|
||||
aplog_type = APLOG_ERR;
|
||||
break;
|
||||
case LOG_WARNING:
|
||||
aplog_type = APLOG_WARNING;
|
||||
break;
|
||||
case LOG_NOTICE:
|
||||
aplog_type = APLOG_NOTICE;
|
||||
break;
|
||||
#if LOG_INFO != LOG_NOTICE
|
||||
case LOG_INFO:
|
||||
aplog_type = APLOG_INFO;
|
||||
break;
|
||||
#endif
|
||||
#if LOG_NOTICE != LOG_DEBUG
|
||||
case LOG_DEBUG:
|
||||
aplog_type = APLOG_DEBUG;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ctx == NULL) { /* we haven't initialized our ctx yet, oh well */
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_STARTUP, 0, NULL, "%s", msg);
|
||||
} else {
|
||||
ap_log_rerror(APLOG_MARK, aplog_type, 0, ctx->r, "%s", msg);
|
||||
}
|
||||
}
|
||||
|
||||
static void php_apache_sapi_log_message_ex(const char *msg, request_rec *r)
|
||||
{
|
||||
if (r) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, msg, r->filename);
|
||||
} else {
|
||||
php_apache_sapi_log_message(msg, -1);
|
||||
}
|
||||
}
|
||||
|
||||
static double php_apache_sapi_get_request_time(void)
|
||||
{
|
||||
php_struct *ctx = SG(server_context);
|
||||
return ((double) ctx->r->request_time) / 1000000.0;
|
||||
}
|
||||
|
||||
extern zend_module_entry php_apache_module;
|
||||
|
||||
static int php_apache2_startup(sapi_module_struct *sapi_module)
|
||||
{
|
||||
if (php_module_startup(sapi_module, &php_apache_module, 1)==FAILURE) {
|
||||
return FAILURE;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static sapi_module_struct apache2_sapi_module = {
|
||||
"apache2handler",
|
||||
"Apache 2.0 Handler",
|
||||
|
||||
php_apache2_startup, /* startup */
|
||||
php_module_shutdown_wrapper, /* shutdown */
|
||||
|
||||
NULL, /* activate */
|
||||
NULL, /* deactivate */
|
||||
|
||||
php_apache_sapi_ub_write, /* unbuffered write */
|
||||
php_apache_sapi_flush, /* flush */
|
||||
php_apache_sapi_get_stat, /* get uid */
|
||||
php_apache_sapi_getenv, /* getenv */
|
||||
|
||||
php_error, /* error handler */
|
||||
|
||||
php_apache_sapi_header_handler, /* header handler */
|
||||
php_apache_sapi_send_headers, /* send headers handler */
|
||||
NULL, /* send header handler */
|
||||
|
||||
php_apache_sapi_read_post, /* read POST data */
|
||||
php_apache_sapi_read_cookies, /* read Cookies */
|
||||
|
||||
php_apache_sapi_register_variables,
|
||||
php_apache_sapi_log_message, /* Log message */
|
||||
php_apache_sapi_get_request_time, /* Request Time */
|
||||
NULL, /* Child Terminate */
|
||||
|
||||
STANDARD_SAPI_MODULE_PROPERTIES
|
||||
};
|
||||
|
||||
static apr_status_t php_apache_server_shutdown(void *tmp)
|
||||
{
|
||||
apache2_sapi_module.shutdown(&apache2_sapi_module);
|
||||
sapi_shutdown();
|
||||
#ifdef ZTS
|
||||
tsrm_shutdown();
|
||||
#endif
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
static apr_status_t php_apache_child_shutdown(void *tmp)
|
||||
{
|
||||
apache2_sapi_module.shutdown(&apache2_sapi_module);
|
||||
#if defined(ZTS) && !defined(PHP_WIN32)
|
||||
tsrm_shutdown();
|
||||
#endif
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
static void php_apache_add_version(apr_pool_t *p)
|
||||
{
|
||||
if (PG(expose_php)) {
|
||||
ap_add_version_component(p, "PHP/" PHP_VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
static int php_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
|
||||
{
|
||||
#ifndef ZTS
|
||||
int threaded_mpm;
|
||||
|
||||
ap_mpm_query(AP_MPMQ_IS_THREADED, &threaded_mpm);
|
||||
if(threaded_mpm) {
|
||||
ap_log_error(APLOG_MARK, APLOG_CRIT, 0, 0, "Apache is running a threaded MPM, but your PHP Module is not compiled to be threadsafe. You need to recompile PHP.");
|
||||
return DONE;
|
||||
}
|
||||
#endif
|
||||
/* When this is NULL, apache won't override the hard-coded default
|
||||
* php.ini path setting. */
|
||||
apache2_php_ini_path_override = NULL;
|
||||
return OK;
|
||||
}
|
||||
|
||||
static int
|
||||
php_apache_server_startup(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
|
||||
{
|
||||
void *data = NULL;
|
||||
const char *userdata_key = "apache2hook_post_config";
|
||||
|
||||
/* Apache will load, unload and then reload a DSO module. This
|
||||
* prevents us from starting PHP until the second load. */
|
||||
apr_pool_userdata_get(&data, userdata_key, s->process->pool);
|
||||
if (data == NULL) {
|
||||
/* We must use set() here and *not* setn(), otherwise the
|
||||
* static string pointed to by userdata_key will be mapped
|
||||
* to a different location when the DSO is reloaded and the
|
||||
* pointers won't match, causing get() to return NULL when
|
||||
* we expected it to return non-NULL. */
|
||||
apr_pool_userdata_set((const void *)1, userdata_key, apr_pool_cleanup_null, s->process->pool);
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Set up our overridden path. */
|
||||
if (apache2_php_ini_path_override) {
|
||||
apache2_sapi_module.php_ini_path_override = apache2_php_ini_path_override;
|
||||
}
|
||||
#ifdef ZTS
|
||||
php_tsrm_startup();
|
||||
# ifdef PHP_WIN32
|
||||
ZEND_TSRMLS_CACHE_UPDATE();
|
||||
# endif
|
||||
#endif
|
||||
|
||||
zend_signal_startup();
|
||||
|
||||
sapi_startup(&apache2_sapi_module);
|
||||
if (apache2_sapi_module.startup(&apache2_sapi_module) != SUCCESS) {
|
||||
return DONE;
|
||||
}
|
||||
apr_pool_cleanup_register(pconf, NULL, php_apache_server_shutdown, apr_pool_cleanup_null);
|
||||
php_apache_add_version(pconf);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static apr_status_t php_server_context_cleanup(void *data_)
|
||||
{
|
||||
void **data = data_;
|
||||
*data = NULL;
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
static int php_apache_request_ctor(request_rec *r, php_struct *ctx)
|
||||
{
|
||||
char *content_length;
|
||||
const char *auth;
|
||||
|
||||
SG(sapi_headers).http_response_code = !r->status ? HTTP_OK : r->status;
|
||||
SG(request_info).content_type = apr_table_get(r->headers_in, "Content-Type");
|
||||
SG(request_info).query_string = apr_pstrdup(r->pool, r->args);
|
||||
SG(request_info).request_method = r->method;
|
||||
SG(request_info).proto_num = r->proto_num;
|
||||
SG(request_info).request_uri = apr_pstrdup(r->pool, r->uri);
|
||||
SG(request_info).path_translated = apr_pstrdup(r->pool, r->filename);
|
||||
r->no_local_copy = 1;
|
||||
|
||||
content_length = (char *) apr_table_get(r->headers_in, "Content-Length");
|
||||
if (content_length) {
|
||||
ZEND_ATOL(SG(request_info).content_length, content_length);
|
||||
} else {
|
||||
SG(request_info).content_length = 0;
|
||||
}
|
||||
|
||||
apr_table_unset(r->headers_out, "Content-Length");
|
||||
apr_table_unset(r->headers_out, "Last-Modified");
|
||||
apr_table_unset(r->headers_out, "Expires");
|
||||
apr_table_unset(r->headers_out, "ETag");
|
||||
|
||||
auth = apr_table_get(r->headers_in, "Authorization");
|
||||
php_handle_auth_data(auth);
|
||||
|
||||
if (SG(request_info).auth_user == NULL && r->user) {
|
||||
SG(request_info).auth_user = estrdup(r->user);
|
||||
}
|
||||
|
||||
ctx->r->user = apr_pstrdup(ctx->r->pool, SG(request_info).auth_user);
|
||||
|
||||
return php_request_startup();
|
||||
}
|
||||
|
||||
static void php_apache_request_dtor(request_rec *r)
|
||||
{
|
||||
php_request_shutdown(NULL);
|
||||
}
|
||||
|
||||
static void php_apache_ini_dtor(request_rec *r, request_rec *p)
|
||||
{
|
||||
if (strcmp(r->protocol, "INCLUDED")) {
|
||||
zend_try { zend_ini_deactivate(); } zend_end_try();
|
||||
} else {
|
||||
typedef struct {
|
||||
HashTable config;
|
||||
} php_conf_rec;
|
||||
zend_string *str;
|
||||
php_conf_rec *c = ap_get_module_config(r->per_dir_config, &php_module);
|
||||
|
||||
ZEND_HASH_FOREACH_STR_KEY(&c->config, str) {
|
||||
zend_restore_ini_entry(str, ZEND_INI_STAGE_SHUTDOWN);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
if (p) {
|
||||
((php_struct *)SG(server_context))->r = p;
|
||||
} else {
|
||||
apr_pool_cleanup_run(r->pool, (void *)&SG(server_context), php_server_context_cleanup);
|
||||
}
|
||||
}
|
||||
|
||||
static int php_handler(request_rec *r)
|
||||
{
|
||||
php_struct * volatile ctx;
|
||||
void *conf;
|
||||
apr_bucket_brigade * volatile brigade;
|
||||
apr_bucket *bucket;
|
||||
apr_status_t rv;
|
||||
request_rec * volatile parent_req = NULL;
|
||||
#ifdef ZTS
|
||||
/* initial resource fetch */
|
||||
(void)ts_resource(0);
|
||||
# ifdef PHP_WIN32
|
||||
ZEND_TSRMLS_CACHE_UPDATE();
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define PHPAP_INI_OFF php_apache_ini_dtor(r, parent_req);
|
||||
|
||||
conf = ap_get_module_config(r->per_dir_config, &php_module);
|
||||
|
||||
/* apply_config() needs r in some cases, so allocate server_context early */
|
||||
ctx = SG(server_context);
|
||||
if (ctx == NULL || (ctx && ctx->request_processed && !strcmp(r->protocol, "INCLUDED"))) {
|
||||
normal:
|
||||
ctx = SG(server_context) = apr_pcalloc(r->pool, sizeof(*ctx));
|
||||
/* register a cleanup so we clear out the SG(server_context)
|
||||
* after each request. Note: We pass in the pointer to the
|
||||
* server_context in case this is handled by a different thread.
|
||||
*/
|
||||
apr_pool_cleanup_register(r->pool, (void *)&SG(server_context), php_server_context_cleanup, apr_pool_cleanup_null);
|
||||
ctx->r = r;
|
||||
ctx = NULL; /* May look weird to null it here, but it is to catch the right case in the first_try later on */
|
||||
} else {
|
||||
parent_req = ctx->r;
|
||||
ctx->r = r;
|
||||
}
|
||||
apply_config(conf);
|
||||
|
||||
if (strcmp(r->handler, PHP_MAGIC_TYPE) && strcmp(r->handler, PHP_SOURCE_MAGIC_TYPE) && strcmp(r->handler, PHP_SCRIPT)) {
|
||||
/* Check for xbithack in this case. */
|
||||
if (!AP2(xbithack) || strcmp(r->handler, "text/html") || !(r->finfo.protection & APR_UEXECUTE)) {
|
||||
PHPAP_INI_OFF;
|
||||
return DECLINED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Give a 404 if PATH_INFO is used but is explicitly disabled in
|
||||
* the configuration; default behaviour is to accept. */
|
||||
if (r->used_path_info == AP_REQ_REJECT_PATH_INFO
|
||||
&& r->path_info && r->path_info[0]) {
|
||||
PHPAP_INI_OFF;
|
||||
return HTTP_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* handle situations where user turns the engine off */
|
||||
if (!AP2(engine)) {
|
||||
PHPAP_INI_OFF;
|
||||
return DECLINED;
|
||||
}
|
||||
|
||||
if (r->finfo.filetype == 0) {
|
||||
php_apache_sapi_log_message_ex("script '%s' not found or unable to stat", r);
|
||||
PHPAP_INI_OFF;
|
||||
return HTTP_NOT_FOUND;
|
||||
}
|
||||
if (r->finfo.filetype == APR_DIR) {
|
||||
php_apache_sapi_log_message_ex("attempt to invoke directory '%s' as script", r);
|
||||
PHPAP_INI_OFF;
|
||||
return HTTP_FORBIDDEN;
|
||||
}
|
||||
|
||||
/* Setup the CGI variables if this is the main request */
|
||||
if (r->main == NULL ||
|
||||
/* .. or if the sub-request environment differs from the main-request. */
|
||||
r->subprocess_env != r->main->subprocess_env
|
||||
) {
|
||||
/* setup standard CGI variables */
|
||||
ap_add_common_vars(r);
|
||||
ap_add_cgi_vars(r);
|
||||
}
|
||||
|
||||
zend_first_try {
|
||||
|
||||
if (ctx == NULL) {
|
||||
brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc);
|
||||
ctx = SG(server_context);
|
||||
ctx->brigade = brigade;
|
||||
|
||||
if (php_apache_request_ctor(r, ctx)!=SUCCESS) {
|
||||
zend_bailout();
|
||||
}
|
||||
} else {
|
||||
if (!parent_req) {
|
||||
parent_req = ctx->r;
|
||||
}
|
||||
if (parent_req && parent_req->handler &&
|
||||
strcmp(parent_req->handler, PHP_MAGIC_TYPE) &&
|
||||
strcmp(parent_req->handler, PHP_SOURCE_MAGIC_TYPE) &&
|
||||
strcmp(parent_req->handler, PHP_SCRIPT)) {
|
||||
if (php_apache_request_ctor(r, ctx)!=SUCCESS) {
|
||||
zend_bailout();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* check if coming due to ErrorDocument
|
||||
* We make a special exception of 413 (Invalid POST request) as the invalidity of the request occurs
|
||||
* during processing of the request by PHP during POST processing. Therefor we need to re-use the exiting
|
||||
* PHP instance to handle the request rather then creating a new one.
|
||||
*/
|
||||
if (parent_req && parent_req->status != HTTP_OK && parent_req->status != 413 && strcmp(r->protocol, "INCLUDED")) {
|
||||
parent_req = NULL;
|
||||
goto normal;
|
||||
}
|
||||
ctx->r = r;
|
||||
brigade = ctx->brigade;
|
||||
}
|
||||
|
||||
if (AP2(last_modified)) {
|
||||
ap_update_mtime(r, r->finfo.mtime);
|
||||
ap_set_last_modified(r);
|
||||
}
|
||||
|
||||
/* Determine if we need to parse the file or show the source */
|
||||
if (strncmp(r->handler, PHP_SOURCE_MAGIC_TYPE, sizeof(PHP_SOURCE_MAGIC_TYPE) - 1) == 0) {
|
||||
zend_syntax_highlighter_ini syntax_highlighter_ini;
|
||||
php_get_highlight_struct(&syntax_highlighter_ini);
|
||||
highlight_file((char *)r->filename, &syntax_highlighter_ini);
|
||||
} else {
|
||||
zend_file_handle zfd;
|
||||
zend_stream_init_filename(&zfd, (char *) r->filename);
|
||||
|
||||
if (!parent_req) {
|
||||
php_execute_script(&zfd);
|
||||
} else {
|
||||
zend_execute_scripts(ZEND_INCLUDE, NULL, 1, &zfd);
|
||||
}
|
||||
|
||||
apr_table_set(r->notes, "mod_php_memory_usage",
|
||||
apr_psprintf(ctx->r->pool, "%" APR_SIZE_T_FMT, zend_memory_peak_usage(1)));
|
||||
}
|
||||
|
||||
} zend_end_try();
|
||||
|
||||
if (!parent_req) {
|
||||
php_apache_request_dtor(r);
|
||||
ctx->request_processed = 1;
|
||||
apr_brigade_cleanup(brigade);
|
||||
bucket = apr_bucket_eos_create(r->connection->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_TAIL(brigade, bucket);
|
||||
|
||||
rv = ap_pass_brigade(r->output_filters, brigade);
|
||||
if (rv != APR_SUCCESS || r->connection->aborted) {
|
||||
zend_first_try {
|
||||
php_handle_aborted_connection();
|
||||
} zend_end_try();
|
||||
}
|
||||
apr_brigade_cleanup(brigade);
|
||||
apr_pool_cleanup_run(r->pool, (void *)&SG(server_context), php_server_context_cleanup);
|
||||
} else {
|
||||
ctx->r = parent_req;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
static void php_apache_child_init(apr_pool_t *pchild, server_rec *s)
|
||||
{
|
||||
apr_pool_cleanup_register(pchild, NULL, php_apache_child_shutdown, apr_pool_cleanup_null);
|
||||
}
|
||||
|
||||
#ifdef ZEND_SIGNALS
|
||||
static void php_apache_signal_init(apr_pool_t *pchild, server_rec *s)
|
||||
{
|
||||
zend_signal_init();
|
||||
}
|
||||
#endif
|
||||
|
||||
void php_ap2_register_hook(apr_pool_t *p)
|
||||
{
|
||||
ap_hook_pre_config(php_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
ap_hook_post_config(php_apache_server_startup, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
ap_hook_handler(php_handler, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
#ifdef ZEND_SIGNALS
|
||||
ap_hook_child_init(php_apache_signal_init, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
#endif
|
||||
ap_hook_child_init(php_apache_child_init, NULL, NULL, APR_HOOK_MIDDLE);
|
||||
}
|
||||
Reference in New Issue
Block a user