ianh            Sat Feb 15 00:49:31 2003 EDT

  Added files:                 (Branch: PHP_4_3)
    /php4/sapi/apache2handler   .cvsignore CREDITS README apache_config.c 
                                config.m4 php.sym php4apache2.dsp 
                                php_apache.h php_functions.c 
                                sapi_apache2.c 
  Log:
  alternate apache2 SAPI.
  
  
Index: php4/sapi/apache2handler/.cvsignore
+++ php4/sapi/apache2handler/.cvsignore
libphp4.module
*.la
*.lo
deps
*.plg
*.opt
*.ncb
Release
Release_inline
Debug
Release_TS
Release_TSDbg
Release_TS_inline
Debug_TS

Index: php4/sapi/apache2handler/apache_config.c
+++ php4/sapi/apache2handler/apache_config.c
/*
   +----------------------------------------------------------------------+
   | PHP Version 4                                                        |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997-2003 The PHP Group                                |
   +----------------------------------------------------------------------+
   | 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          |
   | [EMAIL PROTECTED] so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
   | Author: Sascha Schumann <[EMAIL PROTECTED]>                         |
   +----------------------------------------------------------------------+
 */

/* $Id: apache_config.c,v 1.1 2003/02/11 17:40:11 ianh Exp $ */

#include "php.h"
#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;
} 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;
        
        zend_hash_update(&d->config, (char *) name, strlen(name) + 1, &e, 
                        sizeof(e), NULL);
        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;
}


void *merge_php_config(apr_pool_t *p, void *base_conf, void *new_conf)
{
        php_conf_rec *d = base_conf, *e = new_conf;
        php_dir_entry *pe;
        php_dir_entry *data;
        char *str;
        uint str_len;
        ulong num_index;

        phpapdebug((stderr, "Merge dir (%p) (%p)\n", base_conf, new_conf));
        for (zend_hash_internal_pointer_reset(&d->config);
                        zend_hash_get_current_key_ex(&d->config, &str, &str_len, 
                                &num_index, 0, NULL) == HASH_KEY_IS_STRING;
                        zend_hash_move_forward(&d->config)) {
                pe = NULL;
                zend_hash_get_current_data(&d->config, (void **) &data);
                if (zend_hash_find(&e->config, str, str_len, (void **) &pe) == 
SUCCESS) {
                        if (pe->status >= data->status) continue;
                }
                zend_hash_update(&e->config, str, str_len, data, sizeof(*data), NULL);
                phpapdebug((stderr, "ADDING/OVERWRITING %s (%d vs. %d)\n", str, 
                                        data->status, pe?pe->status:-1));
        }
        return new_conf;
}

char *get_php_config(void *conf, char *name, size_t name_len)
{
        php_conf_rec *d = conf;
        php_dir_entry *pe;
        
        if (zend_hash_find(&d->config, name, name_len, (void **) &pe) == SUCCESS) {
                return pe->value;
        }

        return "";
}

void apply_config(void *dummy)
{
        php_conf_rec *d = dummy;
        char *str;
        uint str_len;
        php_dir_entry *data;
        
        for (zend_hash_internal_pointer_reset(&d->config);
                        zend_hash_get_current_key_ex(&d->config, &str, &str_len, NULL, 
0, 
                                NULL) == HASH_KEY_IS_STRING;
                        zend_hash_move_forward(&d->config)) {
                zend_hash_get_current_data(&d->config, (void **) &data);
                phpapdebug((stderr, "APPLYING (%s)(%s)\n", str, data->value));
                if (zend_alter_ini_entry(str, str_len, data->value, data->value_len, 
                                        data->status, PHP_INI_STAGE_RUNTIME) == 
FAILURE) {
                        phpapdebug((stderr, "..FAILED\n"));
                }       
        }
}

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;
}

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, NULL, 1);
        apr_pool_cleanup_register(p, newx, destroy_php_config, apr_pool_cleanup_null);
        return (void *) newx;
}

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: sw=4 ts=4 fdm=marker
 * vim<600: sw=4 ts=4
 */

Index: php4/sapi/apache2handler/config.m4
+++ php4/sapi/apache2handler/config.m4
dnl
dnl $Id: config.m4,v 1.1 2003/02/11 17:40:11 ianh Exp $
dnl

AC_MSG_CHECKING(for Apache 2.0 handler-module support via DSO through APXS)
AC_ARG_WITH(apxs2handler,
[  --with-apxs2handler[=FILE]     EXPERIMENTAL: Build shared Apache 2.0 module. FILE 
is the optional
                          pathname to the Apache apxs tool; defaults to "apxs".],[
  if test "$withval" = "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($withval, 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-apxs2handler=/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
    AC_MSG_ERROR([Aborting])
  fi 

  APXS_INCLUDEDIR=`$APXS -q INCLUDEDIR`
  APXS_HTTPD=`$APXS -q SBINDIR`/`$APXS -q TARGET`
  APXS_CFLAGS=`$APXS -q CFLAGS`
  APXS_MPM=`$APXS -q MPM_NAME`

  for flag in $APXS_CFLAGS; do
    case $flag in
    -D*) CPPFLAGS="$CPPFLAGS $flag";;
    esac
  done

  # Test that we're trying to configure with apache 2.x
  PHP_AP_EXTRACT_VERSION($APXS_HTTPD)
  if test "$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
    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
    optarg=
  else
    optarg=-a
  fi

  INSTALL_IT='$(mkinstalldirs) '"$APXS_LIBEXECDIR && $APXS -S 
LIBEXECDIR='$APXS_LIBEXECDIR' -i ${optarg} -n php4"

  case $host_alias in
  *aix*)
    EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-brtl -Wl,-bI:$APXS_LIBEXECDIR/httpd.exp"
    PHP_SELECT_SAPI(apache2handler, shared, sapi_apache2.c apache_config.c 
php_functions.c)
    INSTALL_IT="$INSTALL_IT $SAPI_LIBTOOL" 
    ;;
  *darwin*)
    dnl When using bundles on Darwin, we must resolve all symbols.  However,
    dnl the linker does not recursively look at the bundle loader and
    dnl pull in its dependencies.  Therefore, we must pull in the APR
    dnl and APR-util libraries.
    APXS_BINDIR=`$APXS -q BINDIR`
    if test -f $APXS_BINDIR/apr-config; then
        MH_BUNDLE_FLAGS="`$APXS_BINDIR/apr-config --ldflags --link-ld --libs`"
    fi
    if test -f $APXS_BINDIR/apu-config; then
        MH_BUNDLE_FLAGS="`$APXS_BINDIR/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, sapi_apache2.c apache_config.c 
php_functions.c)
    SAPI_SHARED=libs/libphp4.so
    INSTALL_IT="$INSTALL_IT $SAPI_SHARED"
    ;;
  *beos*)
    APXS_BINDIR=`$APXS -q BINDIR`
    if test -f _APP_; then `rm _APP_`; fi
    `ln -s $APXS_BINDIR/httpd _APP_`
    EXTRA_LIBS="$EXTRA_LIBS _APP_"
    PHP_SELECT_SAPI(apache2handler, shared, sapi_apache2.c apache_config.c 
php_functions.c)
    INSTALL_IT="$INSTALL_IT $SAPI_LIBTOOL" 
    ;;
  *)
    PHP_SELECT_SAPI(apache2handler, shared, sapi_apache2.c apache_config.c 
php_functions.c) 
    INSTALL_IT="$INSTALL_IT $SAPI_LIBTOOL"
    ;;
  esac

  PHP_ADD_INCLUDE($APXS_INCLUDEDIR)
  if test "$APXS_MPM" != "prefork"; then
    PHP_BUILD_THREAD_SAFE
  fi
  AC_MSG_RESULT(yes)
],[
  AC_MSG_RESULT(no)
])

PHP_SUBST(APXS)

dnl ## Local Variables:
dnl ## tab-width: 4
dnl ## End:

Index: php4/sapi/apache2handler/php.sym
+++ php4/sapi/apache2handler/php.sym
php4_module

Index: php4/sapi/apache2handler/php4apache2.dsp
+++ php4/sapi/apache2handler/php4apache2.dsp
# Microsoft Developer Studio Project File - Name="php4apache2h" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **

# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102

CFG=php4apache2h - Win32 Debug_TS
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE 
!MESSAGE NMAKE /f "php4apache2h.mak".
!MESSAGE 
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE 
!MESSAGE NMAKE /f "php4apache2h.mak" CFG="php4apache2h - Win32 Debug_TS"
!MESSAGE 
!MESSAGE Possible choices for configuration are:
!MESSAGE 
!MESSAGE "php4apache2h - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link 
Library")
!MESSAGE "php4apache2h - Win32 Release_TS_inline" (based on "Win32 (x86) Dynamic-Link 
Library")
!MESSAGE "php4apache2h - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE 

# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe

!IF  "$(CFG)" == "php4apache2h - Win32 Release_TS"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release_TS"
# PROP BASE Intermediate_Dir "Release_TS"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "..\..\Release_TS"
# PROP Intermediate_Dir "Release_TS"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" 
/D "_USRDLL" /D "php4apache2h_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "...\..\include" /I "..\..\win32" /I "..\..\Zend" 
/I "..\.." /I "..\..\..\bindlib_w32" /I "..\..\main" /I "..\..\TSRM" /D ZEND_DEBUG=0 
/D "NDEBUG" /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "_WINDOWS" /D "_USRDLL" /D 
"WIN32" /D "_MBCS" /D "_WINSOCK2API_" /D "_MSWSOCK_" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x407 /d "NDEBUG"
# ADD RSC /l 0x407 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib 
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 
/nologo /dll /machine:I386
# ADD LINK32 php4ts.lib libhttpd.lib libapr.lib libaprutil.lib kernel32.lib user32.lib 
gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib 
uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 
/libpath:"..\..\Release_TS" /libpath:"..\..\TSRM\Release_TS" 
/libpath:"..\..\Zend\Release_TS"

!ELSEIF  "$(CFG)" == "php4apache2h - Win32 Release_TS_inline"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release_TS_inline"
# PROP BASE Intermediate_Dir "Release_TS_inline"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "..\..\Release_TS_inline"
# PROP Intermediate_Dir "Release_TS_inline"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" 
/D "_USRDLL" /D "php4apache2h_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "...\..\include" /I "..\..\win32" /I "..\..\Zend" 
/I "..\.." /I "..\..\..\bindlib_w32" /I "..\..\main" /I "..\..\TSRM" /D ZEND_DEBUG=0 
/D "ZEND_WIN32_FORCE_INLINE" /D "NDEBUG" /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D 
"_WINDOWS" /D "_USRDLL" /D "WIN32" /D "_MBCS" /D "_WINSOCK2API_" /D "_MSWSOCK_" /YX 
/FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x407 /d "NDEBUG"
# ADD RSC /l 0x407 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib 
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 
/nologo /dll /machine:I386
# ADD LINK32 php4ts.lib libhttpd.lib libapr.lib libaprutil.lib kernel32.lib user32.lib 
gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib 
uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 
/out:"..\..\Release_TS_inline/php4apache2h.dll" /libpath:"..\..\Release_TS_inline" 
/libpath:"..\..\TSRM\Release_TS_inline" /libpath:"..\..\Zend\Release_TS_inline"

!ELSEIF  "$(CFG)" == "php4apache2h - Win32 Debug_TS"

# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug_TS"
# PROP BASE Intermediate_Dir "Debug_TS"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "..\..\Debug_TS"
# PROP Intermediate_Dir "Debug_TS"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" 
/D "_MBCS" /D "_USRDLL" /D "php4apache2h_EXPORTS" /YX /FD /GZ  /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "...\..\include" /I "..\..\win32" /I 
"..\..\Zend" /I "..\.." /I "..\..\..\bindlib_w32" /I "..\..\main" /I "..\..\TSRM" /D 
"_DEBUG" /D ZEND_DEBUG=1 /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "_WINDOWS" /D 
"_USRDLL" /D "WIN32" /D "_MBCS" /D "_WINSOCK2API_" /D "_MSWSOCK_" /YX /FD /GZ  /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x407 /d "_DEBUG"
# ADD RSC /l 0x407 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib 
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib 
/nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 php4ts_debug.lib libhttpd.lib libapr.lib libaprutil.lib kernel32.lib 
user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib 
oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 
/pdbtype:sept /libpath:"..\..\Debug_TS" /libpath:"..\..\TSRM\Debug_TS" 
/libpath:"..\..\Zend\Debug_TS"

!ENDIF 

# Begin Target

# Name "php4apache2h - Win32 Release_TS"
# Name "php4apache2h - Win32 Release_TS_inline"
# Name "php4apache2h - Win32 Debug_TS"
# Begin Group "Source Files"

# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File

SOURCE=.\apache_config.c
# End Source File
# Begin Source File

SOURCE=.\php_functions.c
# End Source File
# Begin Source File

SOURCE=.\sapi_apache2.c
# End Source File
# End Group
# Begin Group "Header Files"

# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File

SOURCE=.\php_apache.h
# End Source File
# End Group
# End Target
# End Project

Index: php4/sapi/apache2handler/php_apache.h
+++ php4/sapi/apache2handler/php_apache.h
/*
   +----------------------------------------------------------------------+
   | PHP Version 4                                                        |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997-2003 The PHP Group                                |
   +----------------------------------------------------------------------+
   | 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          |
   | [EMAIL PROTECTED] so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
   | Author: Sascha Schumann <[EMAIL PROTECTED]>                         |
   +----------------------------------------------------------------------+
 */

/* $Id: php_apache.h,v 1.1 2003/02/11 17:40:11 ianh Exp $ */

#ifndef PHP_APACHE_H
#define PHP_APACHE_H

#include "httpd.h"
#include "http_config.h"
#include "http_core.h"

/* Declare this so we can get to it from outside the sapi_apache2.c file */
extern module AP_MODULE_DECLARE_DATA php4_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;
        conn_rec *c;

    apr_bucket_brigade *bb;
        /* Length of post_data buffer */
        int post_len;
        /* Index for reading from buffer */
        int post_idx;
        /* stat structure of the current file */        
#if defined(NETWARE) && defined(CLIB_STAT_PATCH)
        struct stat_libc finfo;
#else
        struct stat finfo;
#endif
        /* Buffer for request body filter */
        char *post_data;
        /* Whether or not we've processed PHP in the output filters yet. */
        int request_processed;
} 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[];

#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() }}

#endif /* PHP_APACHE_H */

Index: php4/sapi/apache2handler/php_functions.c
+++ php4/sapi/apache2handler/php_functions.c
/*
   +----------------------------------------------------------------------+
   | PHP Version 4                                                        |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997-2003 The PHP Group                                |
   +----------------------------------------------------------------------+
   | 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          |
   | [EMAIL PROTECTED] so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
   | Author: Sascha Schumann <[EMAIL PROTECTED]>                         |
   +----------------------------------------------------------------------+
 */

/* $Id: php_functions.c,v 1.1 2003/02/11 17:40:11 ianh Exp $ */

#include "php.h"
#include "ext/standard/php_smart_str.h"
#include "ext/standard/info.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 "php_apache.h"

static request_rec *php_apache_lookup_uri(char *filename TSRMLS_DC)
{
        php_struct *ctx;
        
        if (!filename) {
                return NULL;
        }
        
        ctx = SG(server_context);
        return ap_sub_req_lookup_uri(filename, ctx->r, ctx->r->output_filters);
}

/*  proto bool virtual(string uri)
 Perform an apache sub-request */
PHP_FUNCTION(virtual)
{
        zval **filename;
        request_rec *rr;

        if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &filename) == FAILURE) {
                WRONG_PARAM_COUNT;
        }

        convert_to_string_ex(filename);
        
        php_error_docref(NULL TSRMLS_CC, E_ERROR, 
            "Virtual Function is not implemented in Apache2Handler '%s' "
            "use SSI instead http://httpd.apache.org/docs-2.0/mod/mod_include.html";, 
            Z_STRVAL_PP(filename));
        ap_destroy_sub_req(rr);
    RETURN_FALSE;

    /* ### this function is unsafe until PHP becomes re-entrant
     * as running virtual('foo.php') from inside another php script
     * can cause bad things to happen.
     * Workaround:
     * Use <!--#include virtual="filename" --> instead, and add the INCLUDES filter
     */
#ifdef NEVER
        if (!(rr = php_apache_lookup_uri(Z_STRVAL_PP(filename) TSRMLS_CC))) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - 
URI lookup failed", Z_STRVAL_PP(filename));
                RETURN_FALSE;
        }
        
        if (rr->status == HTTP_OK) {
                if (ap_run_sub_req(rr)) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include 
'%s' - request execution failed", Z_STRVAL_PP(filename));
                        ap_destroy_sub_req(rr);
                        RETURN_FALSE;
                }
                ap_destroy_sub_req(rr);
                RETURN_TRUE;
        }
        
        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - error 
finding URI", Z_STRVAL_PP(filename));
        ap_destroy_sub_req(rr);
        RETURN_FALSE;
#endif
}
/*  */

#define ADD_LONG(name) \
                add_property_long(return_value, #name, rr->name)
#define ADD_TIME(name) \
                add_property_long(return_value, #name, rr->name / APR_USEC_PER_SEC);
#define ADD_STRING(name) \
                if (rr->name) add_property_string(return_value, #name, (char *) 
rr->name, 1)

PHP_FUNCTION(apache_lookup_uri)
{
        request_rec *rr;
        zval **filename;

        if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &filename) == FAILURE) {
                WRONG_PARAM_COUNT;
        }

        convert_to_string_ex(filename);
        
        if (!(rr = php_apache_lookup_uri(Z_STRVAL_PP(filename) TSRMLS_CC))) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - 
URI lookup failed", Z_STRVAL_PP(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(request_time);
                ADD_LONG(mtime);
                ADD_TIME(request_time);

                ap_destroy_sub_req(rr);
                return;
        }
        
        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - error 
finding URI", Z_STRVAL_PP(filename));
        ap_destroy_sub_req(rr);
        RETURN_FALSE;
}

/*  proto array getallheaders(void)
   Fetch all HTTP request headers */
PHP_FUNCTION(apache_request_headers)
{
        php_struct *ctx;
        const apr_array_header_t *arr;
        char *key, *val;

        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 = empty_string;
                add_assoc_string(return_value, key, val, 1);
        APR_ARRAY_FOREACH_CLOSE()
}
/*  */

/* {{{ proto array apache_response_headers(void)
   Fetch all HTTP response headers */
PHP_FUNCTION(apache_response_headers)
{
        php_struct *ctx;
        const apr_array_header_t *arr;
        char *key, *val;

        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 = empty_string;
                add_assoc_string(return_value, key, val, 1);
        APR_ARRAY_FOREACH_CLOSE()
}
/* }}} */

/* {{{ proto string apache_note(string note_name [, string note_value])
   Get and set Apache request notes */
PHP_FUNCTION(apache_note)
{
        php_struct *ctx;
        zval **note_name, **note_val;
        char *old_note_val=NULL;
        int arg_count = ZEND_NUM_ARGS();

        if (arg_count<1 || arg_count>2 ||
                zend_get_parameters_ex(arg_count, &note_name, &note_val) == FAILURE) {
                WRONG_PARAM_COUNT;
        }
        
        ctx = SG(server_context);
        
        convert_to_string_ex(note_name);

        old_note_val = (char *) apr_table_get(ctx->r->notes, Z_STRVAL_PP(note_name));
        
        if (arg_count == 2) {
                convert_to_string_ex(note_val);
                apr_table_set(ctx->r->notes, Z_STRVAL_PP(note_name), 
Z_STRVAL_PP(note_val));
        }

        if (old_note_val) {
                RETURN_STRING(old_note_val, 1);
        } else {
                RETURN_FALSE;
        }
}
/* }}} */


/* {{{ proto bool apache_setenv(string variable, string value [, bool walk_to_top])
   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;
        zval **variable=NULL, **string_val=NULL, **walk_to_top=NULL;
        int arg_count = ZEND_NUM_ARGS();
    request_rec *r;

        if (arg_count<1 || arg_count>3 ||
                zend_get_parameters_ex(arg_count, &variable, &string_val, 
&walk_to_top) == FAILURE) {
                WRONG_PARAM_COUNT;
        }

        ctx = SG(server_context);

        if (arg_count == 3 && Z_STRVAL_PP(walk_to_top)) {
        r = ctx->r;
                while(r->prev) {
                        r = r->prev;
                }       
        }

        convert_to_string_ex(variable);
        convert_to_string_ex(string_val);
        
        apr_table_set(r->subprocess_env, Z_STRVAL_PP(variable), 
Z_STRVAL_PP(string_val));

        RETURN_TRUE;
}
/* }}} */

/* {{{ proto bool apache_getenv(string variable [, bool walk_to_top])
   Get an Apache subprocess_env variable */
/*
 * XXX: shouldn't this be the parent not the 'prev'
 */
PHP_FUNCTION(apache_getenv)
{
        php_struct *ctx;
        zval **variable=NULL, **walk_to_top=NULL;
        int arg_count = ZEND_NUM_ARGS();
        char *env_val=NULL;
    request_rec *r;

        if (arg_count<1 || arg_count>2 ||
                zend_get_parameters_ex(arg_count, &variable, &walk_to_top) == FAILURE) 
{
                WRONG_PARAM_COUNT;
        }

        ctx = SG(server_context);

    r = ctx->r;
        if (arg_count == 2 && Z_STRVAL_PP(walk_to_top)) {
                while(r->prev) {
                        r = r->prev;
                }       
        }

        convert_to_string_ex(variable);
        
        env_val = (char*) apr_table_get(r->subprocess_env, Z_STRVAL_PP(variable));
        if (env_val != NULL) {
                RETURN_STRING(env_val, 1);
        } else { 
                RETURN_FALSE;
        }       
}
/* }}} */

static char *php_apache_get_version()
{
        return (char *) ap_get_server_version();
}

/* {{{ proto string apache_get_version(void)
   Fetch Apache version */
PHP_FUNCTION(apache_get_version)
{
        char *apv = php_apache_get_version();

        if (apv && *apv) {
                RETURN_STRING(apv, 1);
        } else {
                RETURN_FALSE;
        }
}
/* }}} */

/* {{{ proto array apache_get_modules(void)
   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), 1);
                } else {
                        add_next_index_string(return_value, s, 1);
                }
        }
}
/* }}} */

PHP_MINFO_FUNCTION(apache)
{
        char *apv = php_apache_get_version();
        smart_str tmp1 = {0};
        int n;
        char *p;
        
        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.len - 1) >= 0) {
                tmp1.c[tmp1.len - 1] = '\0';
        }
            
        php_info_print_table_start();
        if (apv && *apv) {
                php_info_print_table_row(2, "Apache Version", apv);
        }
        php_info_print_table_row(2, "Loaded Modules", tmp1.c);
        smart_str_free(&tmp1);
        php_info_print_table_end();
}

static function_entry apache_functions[] = {
        PHP_FE(apache_lookup_uri, NULL)
        PHP_FE(virtual, NULL) 
        PHP_FE(apache_request_headers, NULL)
        PHP_FE(apache_response_headers, NULL)
        PHP_FE(apache_setenv, NULL)
        PHP_FE(apache_getenv, NULL)
        PHP_FE(apache_note, NULL)
        PHP_FE(apache_get_version, NULL)
        PHP_FE(apache_get_modules, NULL)
        PHP_FALIAS(getallheaders, apache_request_headers, NULL)
        {NULL, NULL, NULL}
};

zend_module_entry php_apache_module = {
        STANDARD_MODULE_HEADER,
        "Apache 2.0",
        apache_functions,
        NULL,
        NULL,
        NULL,
        NULL,
        PHP_MINFO(apache),
        NULL,
        STANDARD_MODULE_PROPERTIES
};

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: sw=4 ts=4 fdm=marker
 * vim<600: sw=4 ts=4
 */

Index: php4/sapi/apache2handler/sapi_apache2.c
+++ php4/sapi/apache2handler/sapi_apache2.c
/*
   +----------------------------------------------------------------------+
   | PHP Version 4                                                        |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997-2003 The PHP Group                                |
   +----------------------------------------------------------------------+
   | 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          |
   | [EMAIL PROTECTED] so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
   | Authors: Sascha Schumann <[EMAIL PROTECTED]>                        |
   |          Parts based on Apache 1.3 SAPI module by                    |
   |          Rasmus Lerdorf and Zeev Suraski                             |
   +----------------------------------------------------------------------+
 */

/* $Id: sapi_apache2.c,v 1.1 2003/02/11 17:40:11 ianh Exp $ */

#include <fcntl.h>

#include "php.h"
#include "php_main.h"
#include "php_ini.h"
#include "php_variables.h"
#include "SAPI.h"

#include "ext/standard/php_smart_str.h"
#ifndef NETWARE
#include "ext/standard/php_standard.h"
#else
#include "ext/standard/basic_functions.h"
#endif

#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"
 
#ifdef NETWARE
#undef shutdown /* To avoid Winsock confusion */
#endif

/* A way to specify the location of the php.ini dir in an apache directive */
char *apache2_php_ini_path_override = NULL;

static int
php_apache_sapi_ub_write(const char *str, uint str_length TSRMLS_DC)
{
        apr_bucket *b;
        apr_bucket_brigade *bb;
        apr_bucket_alloc_t *ba;
        php_struct *ctx;
    char* copy_str;

        ctx = SG(server_context);
        if (str_length == 0) 
        return 0;
    copy_str = apr_pmemdup( ctx->r->pool, str, str_length+1);
        b = apr_bucket_pool_create(copy_str, str_length, ctx->r->pool, 
ctx->c->bucket_alloc);
        APR_BRIGADE_INSERT_TAIL(ctx->bb, b);

#if 0
        /* Add a Flush bucket to the end of this brigade, so that
         * the transient buckets above are more likely to make it out
         * the end of the filter instead of having to be copied into
         * someone's setaside. */
        b = apr_bucket_flush_create(ba);
        APR_BRIGADE_INSERT_TAIL(bb, b);
#endif
/*      
        if (ap_pass_brigade(f->next, bb) != APR_SUCCESS) {
                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_headers_struct 
*sapi_headers TSRMLS_DC)
{
        php_struct *ctx;
        ap_filter_t *f;
        char *val;

        ctx = SG(server_context);
        f = ctx->r->output_filters;

        val = strchr(sapi_header->header, ':');

        if (!val) {
                sapi_free_header(sapi_header);
                return 0;
        }

        *val = '\0';
        
        do {
                val++;
        } while (*val == ' ');

        if (!strcasecmp(sapi_header->header, "content-type"))
                ctx->r->content_type = apr_pstrdup(ctx->r->pool, val);
        else if (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);
        
        sapi_free_header(sapi_header);

        return 0;
}

static int
php_apache_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
{
        php_struct *ctx = SG(server_context);

        ctx->r->status = SG(sapi_headers).http_response_code;

        return SAPI_HEADER_SENT_SUCCESSFULLY;
}

static int
php_apache_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC)
{
        int n;
        int to_read;
        php_struct *ctx;
        apr_status_t rv;
    apr_bucket_brigade *bb;
    apr_bucket *bucket;
    char *last=buf;
    int last_count=0;
    int seen_eos=0;

    ctx = SG(server_context);
    bb = apr_brigade_create(ctx->r->pool, ctx->c->bucket_alloc);

        if ((rv = ap_get_brigade(ctx->r->input_filters, bb, AP_MODE_READBYTES, 
APR_BLOCK_READ, count_bytes)) != APR_SUCCESS) {
                return 0;
        }
        
    APR_BRIGADE_FOREACH(bucket,bb) {
            const char*data;
            apr_size_t len;
            if (APR_BUCKET_IS_EOS(bucket)) {
                seen_eos = 1;
                break;
            }
            /* We can't do much with this. */
            if (APR_BUCKET_IS_FLUSH(bucket)) {
                continue;
            }

            apr_bucket_read(bucket, &data, &len, APR_BLOCK_READ);
            if (last_count +len >  count_bytes) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r,
                      "PHP: Read too much post data raise a bug please: %s", 
ctx->r->uri);
                break;
            }
            memcpy( last, data, len);
            last += len;
            last_count += len;
    }
    /*
    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, ctx->r,
                      "PHP: read post data : %s %*s len %ld", ctx->r->uri, last_count, 
buf, last_count);
*/
        return last_count;
}

static struct stat*
php_apache_sapi_get_stat(TSRMLS_D)
{
        php_struct *ctx = SG(server_context);

        ctx->finfo.st_uid = ctx->r->finfo.user;
        ctx->finfo.st_gid = ctx->r->finfo.group;
        ctx->finfo.st_ino = ctx->r->finfo.inode;
#if defined(NETWARE) && defined(CLIB_STAT_PATCH)
        ctx->finfo.st_atime.tv_sec = ctx->r->finfo.atime/1000000;
        ctx->finfo.st_mtime.tv_sec = ctx->r->finfo.mtime/1000000;
        ctx->finfo.st_ctime.tv_sec = ctx->r->finfo.ctime/1000000;
#else
        ctx->finfo.st_atime = ctx->r->finfo.atime/1000000;
        ctx->finfo.st_mtime = ctx->r->finfo.mtime/1000000;
        ctx->finfo.st_ctime = ctx->r->finfo.ctime/1000000;
#endif

        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(TSRMLS_D)
{
        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(char *name, size_t name_len TSRMLS_DC)
{
        php_struct *ctx = SG(server_context);
        const char *env_var;
        
        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 TSRMLS_DC)
{
        php_struct *ctx = SG(server_context);
        const apr_array_header_t *arr = apr_table_elts(ctx->r->subprocess_env);
        char *key, *val;
        
        APR_ARRAY_FOREACH_OPEN(arr, key, val)
                if (!val) val = empty_string;
                php_register_variable(key, val, track_vars_array TSRMLS_CC);
        APR_ARRAY_FOREACH_CLOSE()
                
        php_register_variable("PHP_SELF", ctx->r->uri, track_vars_array TSRMLS_CC);
}

static void
php_apache_sapi_flush(void *server_context)
{
        php_struct *ctx;
        apr_bucket_alloc_t *ba;
        apr_bucket *b;
    /*
     * XXX: handle flush
     * this has issues has PHP is not re-entrant, and can introduce race issues
     * so until PHP is reentrant don't flush.
     */
    return;

#ifdef NEVER
        ctx = server_context;

        /* If we haven't registered a server_context yet,
         * then don't bother flushing. */
        if (!server_context)
                return;
    
        /* Send a flush bucket down the filter chain. The current default
         * handler seems to act on the first flush bucket, but ignores
         * all further flush buckets.
         */
        
        ba = ctx->c->bucket_alloc;
        b = apr_bucket_flush_create(ba);
        APR_BRIGADE_INSERT_TAIL(ctx->bb, b);
        if (ap_pass_brigade(r->output_filters, ctx->bb) != APR_SUCCESS) {
                php_handle_aborted_connection();
        }
#endif
}

static void php_apache_sapi_log_message(char *msg)
{
        php_struct *ctx;
        TSRMLS_FETCH();

        ctx = SG(server_context);
   
        /* We use APLOG_STARTUP because it keeps us from printing the
         * data and time information at the beginning of the error log
         * line.  Not sure if this is correct, but it mirrors what happens
         * with Apache 1.3 -- rbb
         */
        if (ctx == NULL) { /* we haven't initialized our ctx yet, oh well */
                ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO | APLOG_STARTUP,
                                         0, NULL, "%s", msg);
        }
        else {
                ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO | APLOG_STARTUP,
                                         0, ctx->r, "%s", msg);
        }
}

static int
php_apache_disable_caching(ap_filter_t *f)
{
        /* Identify PHP scripts as non-cacheable, thus preventing 
         * Apache from sending a 304 status when the browser sends
         * If-Modified-Since header.
         */
        f->r->no_local_copy = 1;
        
        return OK;
}

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 = {
        "apache2hook",
        "Apache 2.0 Hook",

        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 */

        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 void php_apache_add_version(apr_pool_t *p)
{
        TSRMLS_FETCH();
        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
        tsrm_startup(1, 1, 0, NULL);
#endif
        sapi_startup(&apache2_sapi_module);
        apache2_sapi_module.startup(&apache2_sapi_module);
        apr_pool_cleanup_register(pconf, NULL, php_apache_server_shutdown, 
apr_pool_cleanup_null);
        php_apache_add_version(pconf);

        return OK;
}

static void php_add_filter(request_rec *r, ap_filter_t *f)
{
        int output = (f == r->output_filters);

        /* for those who still have Set*Filter PHP configured */
        while (f) {
                if (strcmp(f->frec->name, "PHP") == 0) {
                        ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_NOERRNO,
                                     0, r->server,
                                     "\"Set%sFilter PHP\" already configured for %s",
                                     output ? "Output" : "Input", r->uri);
                        return;
                }
                f = f->next;
        }

        if (output) {
                ap_add_output_filter("PHP", NULL, r, r->connection);
        } else {
                ap_add_input_filter("PHP", NULL, r, r->connection);
        }
}

static apr_status_t php_server_context_cleanup(void *data_)
{
        void **data = data_;
        *data = NULL;
        return APR_SUCCESS;
}

static int php_handler(request_rec *r)
{
        int content_type_len = strlen("application/x-httpd-php");
        const char *auth;
        php_struct *ctx;
    zend_file_handle zfd;
        TSRMLS_FETCH();

    if (!r->content_type) {
        return DECLINED;
    }
    if (strncmp(r->handler, "application/x-httpd-php", content_type_len -1))  {
        return DECLINED;
    }

    r->allowed |= (AP_METHOD_BIT << M_GET);
    r->allowed |= (AP_METHOD_BIT << M_POST);
    if (r->method_number != M_GET && r->method_number != M_POST ) {
        return DECLINED;
    }

    /* XXX not sure if we need this */
    if (r->finfo.filetype == 0) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                "File does not exist: %s", r->filename);
        return HTTP_NOT_FOUND;
    }
    
        /* Initialize filter context */
        SG(server_context) = ctx = 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);

        ap_add_common_vars(r);
        ap_add_cgi_vars(r);

        SG(sapi_headers).http_response_code = 200;
        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).request_uri = apr_pstrdup(r->pool, r->uri);
        r->no_local_copy = 1;
        r->content_type = apr_pstrdup(r->pool, 
sapi_get_default_content_type(TSRMLS_C));
    /*
     * XXX handle POST data
     */
    SG(request_info).post_data = NULL;
    SG(request_info).post_data_length = 0;
    /*
        SG(request_info).post_data = ctx->post_data;
        SG(request_info).post_data_length = ctx->post_len;
    */
        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");
        apr_table_unset(r->headers_in, "Connection");
        if (!PG(safe_mode)) {
                auth = apr_table_get(r->headers_in, "Authorization");
                php_handle_auth_data(auth TSRMLS_CC);
        } else {
                SG(request_info).auth_user = NULL;
                SG(request_info).auth_password = NULL;
        }
        /* setup standard CGI variables */
        ctx = SG(server_context);
        if (ctx == NULL) {
                ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
                                         "php failed to get server context");
        return HTTP_INTERNAL_SERVER_ERROR;
        }

    ctx->r = r;
    ctx->c = r->connection;

        php_request_startup(TSRMLS_C);

    ctx->bb = apr_brigade_create(r->pool, ctx->c->bucket_alloc);

    zfd.type = ZEND_HANDLE_FILENAME;
        zfd.filename = r->filename;
        zfd.free_filename = 0;
        zfd.opened_path = NULL;
        php_execute_script(&zfd TSRMLS_CC);
#if MEMORY_LIMIT
        {
        char *mem_usage;

        mem_usage = apr_psprintf(r->pool, "%u", AG(allocated_memory_peak));
        AG(allocated_memory_peak) = 0;
        apr_table_set(r->notes, "mod_php_memory_usage", mem_usage);
    }
#endif

        php_request_shutdown(NULL);
/*
 * handled by APR
        if (SG(request_info).query_string) {
                free(SG(request_info).query_string);
        }
        if (SG(request_info).request_uri) {
                free(SG(request_info).request_uri);
        }
*/
    APR_BRIGADE_INSERT_TAIL(ctx->bb, apr_bucket_eos_create(ctx->c->bucket_alloc));
    r->status = SG(sapi_headers).http_response_code;
    return ap_pass_brigade( r->output_filters, ctx->bb);
/*
 * XXX: check.. how do we set the response code ?
    return SG(sapi_headers).http_response_code;
 */

}
static void php_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_insert_filter(php_insert_filter, NULL, NULL, APR_HOOK_MIDDLE);
        ap_hook_post_read_request(php_post_read_request, NULL, NULL, APR_HOOK_MIDDLE);
    */
    ap_hook_handler(php_handler, NULL, NULL, APR_HOOK_MIDDLE);
    /*
        ap_register_output_filter("PHP", php_output_filter, 
php_apache_disable_caching, AP_FTYPE_RESOURCE);
        ap_register_input_filter("PHP", php_input_filter, php_apache_disable_caching, 
AP_FTYPE_RESOURCE);
    */
}

AP_MODULE_DECLARE_DATA module php4_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_register_hook               /* register hooks */
};

/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: sw=4 ts=4 fdm=marker
 * vim<600: sw=4 ts=4
 */

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to