diff options
Diffstat (limited to 'sapi')
326 files changed, 16548 insertions, 34060 deletions
diff --git a/sapi/aolserver/CREDITS b/sapi/aolserver/CREDITS deleted file mode 100644 index 8f9a4af950..0000000000 --- a/sapi/aolserver/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -AOLserver -Sascha Schumann diff --git a/sapi/aolserver/README b/sapi/aolserver/README deleted file mode 100644 index 80c186ea5d..0000000000 --- a/sapi/aolserver/README +++ /dev/null @@ -1,69 +0,0 @@ -AOLserver README ($Id$) - -To compile PHP 4.0 as a module for AOLserver, you need: - -- installed AOLserver 3.1 or later - (see the note below for AOLserver 3.0) - -NOTE: You should not use this module in production. PHP is not 100% stable - yet in threaded mode. To increase reliability enable the Global Lock - by removing #define NO_GLOBAL_LOCK in main/main.c. Also don't use - php_value as it will lead to races in a sub-system (use an ini file - instead). - - -1.) Configuring AOLserver - -Read doc/install.txt in the source distribution - -It usually boils down to changing the INST/PREFIX variable in -include/Makefile.global and running make all install. - -2.) Configuring PHP - -$ ./configure \ - --with-aolserver=/path/to/installed/aolserver \ - <other options> - -NOTE: If you are still using AOLserver 3.0, you need to retain the - AOLserver source code and pass another option to PHP: - - --with-aolserver-src=/path/to/source/distribution - -3.) Compiling and Installing PHP - -$ make install - -4.) Changing nsd.tcl - -a) New section - -Add a new section to pass options to PHP (required): - -ns_section "ns/server/${servername}/module/php" - -You can use the following commands in this section: - -The 'map' command will cause AOLserver to pass all requests to *.php to -the PHP module (can be specified multiple times). Example: - -ns_param map *.php - -The 'php_value "name val"' command assigns the configuration option name -the value val (can be used multiple times). Example: - -ns_param php_value "session.auto_start 1" - -b) Enabling PHP - -Then enable the PHP module: - -ns_section "ns/server/${servername}/modules" -... -ns_param php ${bindir}/libphp5.so - - -============================================================================= -This has been tested with AOLserver release 3.0. - -AOLserver support has been written by Sascha Schumann <sascha@schumann.cx>. diff --git a/sapi/aolserver/aolserver.c b/sapi/aolserver/aolserver.c deleted file mode 100644 index 3ea8b89900..0000000000 --- a/sapi/aolserver/aolserver.c +++ /dev/null @@ -1,625 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 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> | - +----------------------------------------------------------------------+ - */ - -/* - * TODO: - * - write documentation - * - CGI/1.1 conformance - */ - -/* $Id$ */ - -/* conflict between PHP and AOLserver headers */ -#define Debug php_Debug -#include "php.h" -#undef Debug - -#ifdef HAVE_AOLSERVER - -#ifndef ZTS -#error AOLserver module is only useable in thread-safe mode -#endif - -#include "ext/standard/info.h" -#define SECTION(name) PUTS("<h2>" name "</h2>\n") - -#define NS_BUF_SIZE 511 - -#include "php_ini.h" -#include "php_globals.h" -#include "SAPI.h" -#include "php_main.h" -#include "php_variables.h" - -#include "ns.h" - -#include "php_version.h" - -/* This symbol is used by AOLserver to tell the API version we expect */ - -int Ns_ModuleVersion = 1; - -#define NSG(v) TSRMG(ns_globals_id, ns_globals_struct *, v) - -/* php_ns_context is per-server (thus only once at all) */ - -typedef struct { - sapi_module_struct *sapi_module; - char *ns_server; - char *ns_module; -} php_ns_context; - -/* ns_globals_struct is per-thread */ - -typedef struct { - Ns_Conn *conn; - size_t data_avail; -} ns_globals_struct; - -/* TSRM id */ - -static int ns_globals_id; - -/* global context */ - -static php_ns_context *global_context; - -static void php_ns_config(php_ns_context *ctx, char global); - -/* - * php_ns_sapi_ub_write() writes data to the client connection. - */ - -static int -php_ns_sapi_ub_write(const char *str, uint str_length TSRMLS_DC) -{ - int n; - uint sent = 0; - - while (str_length > 0) { - n = Ns_ConnWrite(NSG(conn), (void *) str, str_length); - - if (n == -1) - php_handle_aborted_connection(); - - str += n; - sent += n; - str_length -= n; - } - - return sent; -} - -/* - * php_ns_sapi_header_handler() sets a HTTP reply header to be - * sent to the client. - */ - -static int -php_ns_sapi_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - char *header_name, *header_content; - char *p; - - header_name = sapi_header->header; - header_content = p = strchr(header_name, ':'); - - if (p) { - *p = '\0'; - do { - header_content++; - } while (*header_content == ' '); - - if (!strcasecmp(header_name, "Content-type")) { - Ns_ConnSetTypeHeader(NSG(conn), header_content); - } else { - Ns_ConnSetHeaders(NSG(conn), header_name, header_content); - } - - *p = ':'; - } - - sapi_free_header(sapi_header); - - return 0; -} - -/* - * php_ns_sapi_send_headers() flushes the headers to the client. - * Called before real content is sent by PHP. - */ - -static int -php_ns_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - if(SG(sapi_headers).send_default_content_type) { - Ns_ConnSetRequiredHeaders(NSG(conn), "text/html", 0); - } - - Ns_ConnFlushHeaders(NSG(conn), SG(sapi_headers).http_response_code); - - return SAPI_HEADER_SENT_SUCCESSFULLY; -} - -/* - * php_ns_sapi_read_post() reads a specified number of bytes from - * the client. Used for POST/PUT requests. - */ - -static int -php_ns_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC) -{ - uint max_read; - uint total_read = 0; - - max_read = MIN(NSG(data_avail), count_bytes); - - total_read = Ns_ConnRead(NSG(conn), buf, max_read); - - if(total_read == NS_ERROR) { - total_read = -1; - } else { - NSG(data_avail) -= total_read; - } - - return total_read; -} - -/* - * php_ns_sapi_read_cookies() returns the Cookie header from - * the HTTP request header - */ - -static char *php_ns_sapi_read_cookies(TSRMLS_D) -{ - int i; - char *http_cookie = NULL; - - i = Ns_SetIFind(NSG(conn->headers), "cookie"); - if(i != -1) { - http_cookie = Ns_SetValue(NSG(conn->headers), i); - } - - return http_cookie; -} - -static void php_info_aolserver(ZEND_MODULE_INFO_FUNC_ARGS) -{ - char buf[512]; - int uptime = Ns_InfoUptime(); - int i; - - php_info_print_table_start(); - php_info_print_table_row(2, "SAPI module version", "$Id$"); - php_info_print_table_row(2, "Build date", Ns_InfoBuildDate()); - php_info_print_table_row(2, "Config file path", Ns_InfoConfigFile()); - php_info_print_table_row(2, "Error Log path", Ns_InfoErrorLog()); - php_info_print_table_row(2, "Installation path", Ns_InfoHomePath()); - php_info_print_table_row(2, "Hostname of server", Ns_InfoHostname()); - php_info_print_table_row(2, "Source code label", Ns_InfoLabel()); - php_info_print_table_row(2, "Server platform", Ns_InfoPlatform()); - snprintf(buf, 511, "%s/%s", Ns_InfoServerName(), Ns_InfoServerVersion()); - php_info_print_table_row(2, "Server version", buf); - snprintf(buf, 511, "%d day(s), %02d:%02d:%02d", - uptime / 86400, - (uptime / 3600) % 24, - (uptime / 60) % 60, - uptime % 60); - php_info_print_table_row(2, "Server uptime", buf); - 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", NSG(conn)->request->line); - for (i = 0; i < Ns_SetSize(NSG(conn)->headers); i++) { - php_info_print_table_row(2, Ns_SetKey(NSG(conn)->headers, i), Ns_SetValue(NSG(conn)->headers, i)); - } - - php_info_print_table_colspan_header(2, "HTTP Response Headers"); - for (i = 0; i < Ns_SetSize(NSG(conn)->outputheaders); i++) { - php_info_print_table_row(2, Ns_SetKey(NSG(conn)->outputheaders, i), Ns_SetValue(NSG(conn)->outputheaders, i)); - } - php_info_print_table_end(); -} - -PHP_FUNCTION(getallheaders); - -/* {{{ arginfo */ -ZEND_BEGIN_ARG_INFO(arginfo_aolserver_getallheaders, 0) -ZEND_END_ARG_INFO() -/* }}} */ - -static const zend_function_entry aolserver_functions[] = { - PHP_FE(getallheaders, arginfo_aolserver_getallheaders) - {NULL, NULL, NULL} -}; - -static zend_module_entry php_aolserver_module = { - STANDARD_MODULE_HEADER, - "AOLserver", - aolserver_functions, - NULL, - NULL, - NULL, - NULL, - php_info_aolserver, - NULL, - STANDARD_MODULE_PROPERTIES -}; - -PHP_FUNCTION(getallheaders) -{ - int i; - - array_init(return_value); - - for (i = 0; i < Ns_SetSize(NSG(conn->headers)); i++) { - char *key = Ns_SetKey(NSG(conn->headers), i); - char *value = Ns_SetValue(NSG(conn->headers), i); - - add_assoc_string(return_value, key, value, 1); - } -} - -static int -php_ns_startup(sapi_module_struct *sapi_module) -{ - if (php_module_startup(sapi_module, &php_aolserver_module, 1) == FAILURE) { - return FAILURE; - } else { - return SUCCESS; - } -} - - -/* - * php_ns_sapi_register_variables() populates the php script environment - * with a number of variables. HTTP_* variables are created for - * the HTTP header data, so that a script can access these. - */ - -#define ADD_STRINGX(name, buf) \ - php_register_variable(name, buf, track_vars_array TSRMLS_CC) - -#define ADD_STRING(name) \ - ADD_STRINGX(name, buf) - -static void -php_ns_sapi_register_variables(zval *track_vars_array TSRMLS_DC) -{ - int i; - char buf[NS_BUF_SIZE + 1]; - char *tmp; - - for(i = 0; i < Ns_SetSize(NSG(conn->headers)); i++) { - char *key = Ns_SetKey(NSG(conn->headers), i); - char *value = Ns_SetValue(NSG(conn->headers), i); - char *p; - char c; - - snprintf(buf, NS_BUF_SIZE, "HTTP_%s", key); - - for(p = buf + 5; (c = *p); p++) { - c = toupper(c); - if(c < 'A' || c > 'Z') { - c = '_'; - } - *p = c; - } - - ADD_STRINGX(buf, value); - } - - snprintf(buf, NS_BUF_SIZE, "%s/%s", Ns_InfoServerName(), Ns_InfoServerVersion()); - ADD_STRING("SERVER_SOFTWARE"); - snprintf(buf, NS_BUF_SIZE, "HTTP/%1.1f", NSG(conn)->request->version); - ADD_STRING("SERVER_PROTOCOL"); - - ADD_STRINGX("REQUEST_METHOD", NSG(conn)->request->method); - - if(NSG(conn)->request->query) - ADD_STRINGX("QUERY_STRING", NSG(conn)->request->query); - - ADD_STRINGX("SERVER_BUILDDATE", Ns_InfoBuildDate()); - - ADD_STRINGX("REMOTE_ADDR", Ns_ConnPeer(NSG(conn))); - - snprintf(buf, NS_BUF_SIZE, "%d", Ns_ConnPeerPort(NSG(conn))); - ADD_STRING("REMOTE_PORT"); - - snprintf(buf, NS_BUF_SIZE, "%d", Ns_ConnPort(NSG(conn))); - ADD_STRING("SERVER_PORT"); - - tmp = Ns_ConnHost(NSG(conn)); - if (tmp) - ADD_STRINGX("SERVER_NAME", tmp); - - ADD_STRINGX("PATH_TRANSLATED", SG(request_info).path_translated); - ADD_STRINGX("REQUEST_URI", SG(request_info).request_uri); - ADD_STRINGX("PHP_SELF", SG(request_info).request_uri); - - ADD_STRINGX("GATEWAY_INTERFACE", "CGI/1.1"); - - snprintf(buf, NS_BUF_SIZE, "%d", Ns_InfoBootTime()); - ADD_STRING("SERVER_BOOTTIME"); -} - - - -/* this structure is static (as in "it does not change") */ - -static sapi_module_struct aolserver_sapi_module = { - "aolserver", - "AOLserver", - - php_ns_startup, /* startup */ - php_module_shutdown_wrapper, /* shutdown */ - - NULL, /* activate */ - NULL, /* deactivate */ - - php_ns_sapi_ub_write, /* unbuffered write */ - NULL, /* flush */ - NULL, /* get uid */ - NULL, /* getenv */ - - php_error, /* error handler */ - - php_ns_sapi_header_handler, /* header handler */ - php_ns_sapi_send_headers, /* send headers handler */ - NULL, /* send header handler */ - - php_ns_sapi_read_post, /* read POST data */ - php_ns_sapi_read_cookies, /* read Cookies */ - - php_ns_sapi_register_variables, - NULL, /* Log message */ - NULL, /* Get request time */ - NULL, /* child terminate */ - - STANDARD_SAPI_MODULE_PROPERTIES -}; - -/* - * php_ns_module_main() is called by the per-request handler and - * "executes" the script - */ - -static int -php_ns_module_main(TSRMLS_D) -{ - zend_file_handle file_handle; - - file_handle.type = ZEND_HANDLE_FILENAME; - file_handle.filename = SG(request_info).path_translated; - file_handle.free_filename = 0; - file_handle.opened_path = NULL; - - php_ns_config(global_context, 0); - if (php_request_startup(TSRMLS_C) == FAILURE) { - return NS_ERROR; - } - - php_execute_script(&file_handle TSRMLS_CC); - php_request_shutdown(NULL); - - return NS_OK; -} - -/* - * php_ns_request_ctor() initializes the per-request data structure - * and fills it with data provided by the web server - */ - -static void -php_ns_request_ctor(TSRMLS_D) -{ - char *server; - Ns_DString ds; - char *root; - int index; - char *tmp; - - server = Ns_ConnServer(NSG(conn)); - -#define safe_strdup(x) ((x)?strdup((x)):NULL) - SG(request_info).query_string = safe_strdup(NSG(conn->request->query)); - - Ns_DStringInit(&ds); - Ns_UrlToFile(&ds, server, NSG(conn->request->url)); - - /* path_translated is the absolute path to the file */ - SG(request_info).path_translated = safe_strdup(Ns_DStringValue(&ds)); - Ns_DStringFree(&ds); - root = Ns_PageRoot(server); - SG(request_info).request_uri = strdup(SG(request_info).path_translated + strlen(root)); - SG(request_info).request_method = NSG(conn)->request->method; - if(NSG(conn)->request->version > 1.0) SG(request_info).proto_num = 1001; - else SG(request_info).proto_num = 1000; - SG(request_info).content_length = Ns_ConnContentLength(NSG(conn)); - index = Ns_SetIFind(NSG(conn)->headers, "content-type"); - SG(request_info).content_type = index == -1 ? NULL : - Ns_SetValue(NSG(conn)->headers, index); - SG(sapi_headers).http_response_code = 200; - - tmp = Ns_ConnAuthUser(NSG(conn)); - if (tmp) - tmp = estrdup(tmp); - SG(request_info).auth_user = tmp; - - tmp = Ns_ConnAuthPasswd(NSG(conn)); - if (tmp) - tmp = estrdup(tmp); - SG(request_info).auth_password = tmp; - - NSG(data_avail) = SG(request_info).content_length; -} - -/* - * php_ns_request_dtor() destroys all data associated with - * the per-request structure - */ - -static void -php_ns_request_dtor(TSRMLS_D) -{ - free(SG(request_info).path_translated); - if (SG(request_info).query_string) - free(SG(request_info).query_string); - free(SG(request_info).request_uri); -} - -/* - * The php_ns_request_handler() is called per request and handles - * everything for one request. - */ - -static int -php_ns_request_handler(void *context, Ns_Conn *conn) -{ - int status = NS_OK; - TSRMLS_FETCH(); - - NSG(conn) = conn; - - SG(server_context) = global_context; - - php_ns_request_ctor(TSRMLS_C); - - status = php_ns_module_main(TSRMLS_C); - - php_ns_request_dtor(TSRMLS_C); - - return status; -} - -/* - * php_ns_config() fetches the configuration data. - * - * It understands the "map" and "php_value" command. - */ - -static void -php_ns_config(php_ns_context *ctx, char global) -{ - int i; - char *path; - Ns_Set *set; - - path = Ns_ConfigGetPath(ctx->ns_server, ctx->ns_module, NULL); - set = Ns_ConfigGetSection(path); - - for (i = 0; set && i < Ns_SetSize(set); i++) { - char *key = Ns_SetKey(set, i); - char *value = Ns_SetValue(set, i); - - if (global && !strcasecmp(key, "map")) { - Ns_Log(Notice, "Registering PHP for \"%s\"", value); - Ns_RegisterRequest(ctx->ns_server, "GET", value, php_ns_request_handler, NULL, ctx, 0); - Ns_RegisterRequest(ctx->ns_server, "POST", value, php_ns_request_handler, NULL, ctx, 0); - Ns_RegisterRequest(ctx->ns_server, "HEAD", value, php_ns_request_handler, NULL, ctx, 0); - - /* - * Deactivated for now. The ini system will cause random crashes when - * accessed from here (since there are no locks to protect the global - * known_directives) - */ - - } else if (!global && !strcasecmp(key, "php_value")) { - Ns_Log(Notice, "php_value has been deactivated temporarily. Please use a php.ini file to pass directives to PHP. Thanks."); -#if 0 - char *val; - - val = strchr(value, ' '); - if (val) { - char *new_key; - - new_key = estrndup(value, val - value); - - do { - val++; - } while(*val == ' '); - - Ns_Log(Debug, "PHP configuration option '%s=%s'", new_key, val); - zend_alter_ini_entry(new_key, strlen(new_key) + 1, val, - strlen(val) + 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); - - efree(new_key); - } -#endif - } - - } -} - -/* - * php_ns_server_shutdown() performs the last steps before the - * server exits. Shutdowns basic services and frees memory - */ - -static void -php_ns_server_shutdown(void *context) -{ - php_ns_context *ctx = (php_ns_context *) context; - - ctx->sapi_module->shutdown(ctx->sapi_module); - sapi_shutdown(); - tsrm_shutdown(); - - free(ctx->ns_module); - free(ctx->ns_server); - free(ctx); -} - -/* - * Ns_ModuleInit() is called by AOLserver once at startup - * - * This functions allocates basic structures and initializes - * basic services. - */ - -int Ns_ModuleInit(char *server, char *module) -{ - php_ns_context *ctx; - - tsrm_startup(1, 1, 0, NULL); - sapi_startup(&aolserver_sapi_module); - sapi_module.startup(&aolserver_sapi_module); - - /* TSRM is used to allocate a per-thread structure */ - ts_allocate_id(&ns_globals_id, sizeof(ns_globals_struct), NULL, NULL); - - /* the context contains data valid for all threads */ - ctx = malloc(sizeof *ctx); - ctx->sapi_module = &aolserver_sapi_module; - ctx->ns_server = strdup(server); - ctx->ns_module = strdup(module); - - /* read the configuration */ - php_ns_config(ctx, 1); - - global_context = ctx; - - /* register shutdown handler */ - Ns_RegisterServerShutdown(server, php_ns_server_shutdown, ctx); - - return NS_OK; -} - -#endif diff --git a/sapi/aolserver/config.m4 b/sapi/aolserver/config.m4 deleted file mode 100644 index a193bfd058..0000000000 --- a/sapi/aolserver/config.m4 +++ /dev/null @@ -1,31 +0,0 @@ -dnl -dnl $Id$ -dnl - -PHP_ARG_WITH(aolserver,, -[ --with-aolserver=DIR Specify path to the installed AOLserver], no, no) - -AC_MSG_CHECKING([for AOLserver support]) - -if test "$PHP_AOLSERVER" != "no"; then - if test -d "$PHP_AOLSERVER/include"; then - PHP_AOLSERVER_SRC=$PHP_AOLSERVER - fi - if test -z "$PHP_AOLSERVER_SRC" || test ! -d $PHP_AOLSERVER_SRC/include; then - AC_MSG_ERROR(Please specify the path to the source distribution of AOLserver using --with-aolserver-src=DIR) - fi - if test ! -d $PHP_AOLSERVER/bin ; then - AC_MSG_ERROR(Please specify the path to the root of AOLserver using --with-aolserver=DIR) - fi - PHP_BUILD_THREAD_SAFE - PHP_ADD_INCLUDE($PHP_AOLSERVER_SRC/include) - AC_DEFINE(HAVE_AOLSERVER,1,[Whether you have AOLserver]) - PHP_SELECT_SAPI(aolserver, shared, aolserver.c) - INSTALL_IT="\$(INSTALL) -m 0755 $SAPI_SHARED \$(INSTALL_ROOT)$PHP_AOLSERVER/bin/" -fi - -AC_MSG_RESULT([$PHP_AOLSERVER]) - -dnl ## Local Variables: -dnl ## tab-width: 4 -dnl ## End: diff --git a/sapi/aolserver/config.w32 b/sapi/aolserver/config.w32 deleted file mode 100644 index 75b4361efc..0000000000 --- a/sapi/aolserver/config.w32 +++ /dev/null @@ -1,16 +0,0 @@ -// vim:ft=javascript -// $Id$ - -ARG_WITH('aolserver', 'Build AOLserver support', 'no'); - -if (PHP_AOLSERVER != "no") { - if (PHP_ZTS == "no") { - WARNING("AOLSERVER module requires an --enable-zts build of PHP"); - } else { - if (CHECK_HEADER_ADD_INCLUDE("ns.h", "CFLAGS_AOLSERVER", PHP_AOLSERVER) && CHECK_LIB("nsd.lib", "aolserver", PHP_AOLSERVER)) { - SAPI('aolserver', 'aolserver.c', 'php' + PHP_VERSION + 'aolserver.so', '/D XP_WIN32 '); - } else { - WARNING("sapi/aolserver not enabled: Could not find libraries/headers"); - } - } -} diff --git a/sapi/aolserver/php.sym b/sapi/aolserver/php.sym deleted file mode 100644 index b401ffd2b3..0000000000 --- a/sapi/aolserver/php.sym +++ /dev/null @@ -1,2 +0,0 @@ -Ns_ModuleVersion -Ns_ModuleInit diff --git a/sapi/aolserver/php5aolserver.dsp b/sapi/aolserver/php5aolserver.dsp deleted file mode 100644 index dd6ad71c53..0000000000 --- a/sapi/aolserver/php5aolserver.dsp +++ /dev/null @@ -1,135 +0,0 @@ -# Microsoft Developer Studio Project File - Name="php5aolserver" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=php5aolserver - 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 "php5aolserver.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 "php5aolserver.mak" CFG="php5aolserver - Win32 Debug_TS"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "php5aolserver - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "php5aolserver - Win32 Release_TS_inline" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "php5aolserver - 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)" == "php5aolserver - 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 "PHP5AOLSERVER_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "..\..\..\php_build\nsapi30\include\\" /I "..\..\include" /I "..\..\win32" /I "..\..\Zend" /I "..\.." /I "..\..\..\bindlib_w32" /I "..\..\main" /I "..\..\tsrm" /D ZEND_DEBUG=0 /D "NDEBUG" /D "PHP5AOLSERVER_EXPORTS" /D "PHP_WIN32" /D "ZTS" /D "ZEND_WIN32" /D "_WINDOWS" /D "_USRDLL" /D "WIN32" /D "_MBCS" /D "HAVE_AOLSERVER" /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /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 nsd.lib php5ts.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 /base:"0x62000000" /version:4.0 /dll /machine:I386 /out:"../../Release_TS/php5aolserver.so" /libpath:"..\..\..\php_build\nsapi30\lib\\" /libpath:"..\..\Release_TS" /libpath:"..\..\TSRM\Release_TS" /libpath:"..\..\Zend\Release_TS"
-
-!ELSEIF "$(CFG)" == "php5aolserver - 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 "PHP5AOLSERVER_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "..\..\..\php_build\nsapi30\include\\" /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 "PHPAOLSERVER_EXPORTS" /D "PHP_WIN32" /D "ZTS" /D "ZEND_WIN32" /D "_WINDOWS" /D "_USRDLL" /D "WIN32" /D "_MBCS" /D "HAVE_AOLSERVER" /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /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 nsd.lib php5ts.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 /base:"0x62000000" /version:4.0 /dll /machine:I386 /out:"../../Release_TS_inline/php5aolserver.so" /libpath:"..\..\..\php_build\nsapi30\lib\\" /libpath:"..\..\Release_TS_inline" /libpath:"..\..\TSRM\Release_TS_inline" /libpath:"..\..\Zend\Release_TS_inline"
-
-!ELSEIF "$(CFG)" == "php5aolserver - 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 Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PHP5AOLSERVER_EXPORTS" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /I "..\..\..\php_build\nsapi30\include\\" /I "..\..\include" /I "..\..\win32" /I "..\..\Zend" /I "..\.." /I "..\..\..\bindlib_w32" /I "..\..\main" /I "..\..\tsrm" /D "_DEBUG" /D ZEND_DEBUG=1 /D "PHP5AOLSERVER_EXPORTS" /D "PHP_WIN32" /D "ZTS" /D "ZEND_WIN32" /D "_WINDOWS" /D "_USRDLL" /D "WIN32" /D "_MBCS" /D "HAVE_AOLSERVER" /FR /YX /FD /GZ /c
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /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 nsd.lib php5ts_debug.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 /base:"0x62000000" /version:4.0 /dll /debug /machine:I386 /out:"..\..\Debug_TS/php5aolserver.so" /pdbtype:sept /libpath:"..\..\..\php_build\nsapi30\lib\\" /libpath:"..\..\Debug_TS" /libpath:"..\..\TSRM\Debug_TS" /libpath:"..\..\Zend\Debug_TS"
-
-!ENDIF
-
-# Begin Target
-
-# Name "php5aolserver - Win32 Release_TS"
-# Name "php5aolserver - Win32 Release_TS_inline"
-# Name "php5aolserver - Win32 Debug_TS"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\aolserver.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/sapi/apache/CREDITS b/sapi/apache/CREDITS deleted file mode 100644 index 991deb5633..0000000000 --- a/sapi/apache/CREDITS +++ /dev/null @@ -1,3 +0,0 @@ -Apache 1.3 -Rasmus Lerdorf, Zeev Suraski, Stig Bakken, David Sklar - diff --git a/sapi/apache/apMakefile.libdir b/sapi/apache/apMakefile.libdir deleted file mode 100644 index 7b5254013a..0000000000 --- a/sapi/apache/apMakefile.libdir +++ /dev/null @@ -1,4 +0,0 @@ -This is a place-holder which indicates to Configure that it shouldn't -provide the default targets when building the Makefile in this directory. -Instead it'll just prepend all the important variable definitions, and -copy the Makefile.tmpl onto the end. diff --git a/sapi/apache/apMakefile.tmpl b/sapi/apache/apMakefile.tmpl deleted file mode 100644 index 5f77d9c9c9..0000000000 --- a/sapi/apache/apMakefile.tmpl +++ /dev/null @@ -1,77 +0,0 @@ -## -## Apache 1.3 Makefile template for PHP 5.0 Module -## [src/modules/php5/Makefile.tmpl] -## - -# the parametrized target -LIB=libphp5.$(LIBEXT) - -# objects for building the static library -OBJS=mod_php5.o -OBJS_LIB=libmodphp5.a - -# objects for building the shared object library -SHLIB_OBJS=mod_php5.so-o -SHLIB_OBJS_LIB=libmodphp5.a - -# the general targets -all: lib -lib: $(LIB) - -# build the static library by merging the object files -libphp5.a: $(OBJS) $(OBJS_LIB) - cp $(OBJS_LIB) $@ - ar r $@ $(OBJS) - $(RANLIB) $@ - -# ugly hack to support older Apache-1.3 betas that don't set $LIBEXT -libphp5.: $(OBJS) $(OBJS_LIB) - cp $(OBJS_LIB) $@ - ar r $@ $(OBJS) - $(RANLIB) $@ - cp libphp5. libphp5.a - -# build the shared object library by linking the object files -libphp5.so: $(SHLIB_OBJS) $(SHLIB_OBJS_LIB) - rm -f $@ - $(LD_SHLIB) $(LDFLAGS_SHLIB) -o $@ $(SHLIB_OBJS) $(SHLIB_OBJS_LIB) $(LIBS) $(PHP_LIBS) - -# 1. extension .o for shared objects cannot be used here because -# first these files aren't still shared objects and second we -# have to use a different name to trigger the different -# implicit Make rule -# 2. extension -so.o (as used elsewhere) cannot be used because -# the suffix feature of Make really wants just .x, so we use -# extension .so-o -.SUFFIXES: .o .so-o -.c.o: - $(CC) -c $(INCLUDES) $(CFLAGS) $(PHP_CFLAGS) $(CPPFLAGS) $(SPACER) $< -.c.so-o: - $(CC) -c $(INCLUDES) $(CFLAGS) $(CFLAGS_SHLIB) $(PHP_CFLAGS) $(CPPFLAGS) $(SPACER) $< && mv $*.o $*.so-o - -# cleanup -clean: - -rm -f $(OBJS) $(SHLIB_OBJS) $(LIB) - -# We really don't expect end users to use this rule. It works only with -# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after -# using it. -depend: - cp Makefile.tmpl Makefile.tmpl.bak \ - && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \ - && gcc -MM $(INCLUDES) $(CFLAGS) $(PHP_CFLAGS) $(CPPFLAGS) *.c >> Makefile.new \ - && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' Makefile.new \ - > Makefile.tmpl \ - && rm Makefile.new - -#Dependencies - -$(OBJS): Makefile - -# DO NOT REMOVE -mod_php5.o: mod_php5.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \ - $(INCDIR)/buff.h \ - $(INCDIR)/http_config.h \ - $(INCDIR)/http_core.h $(INCDIR)/http_main.h \ - $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \ - $(INCDIR)/http_log.h $(INCDIR)/util_script.h mod_php5.h diff --git a/sapi/apache/config.m4 b/sapi/apache/config.m4 deleted file mode 100644 index 7b0ee562eb..0000000000 --- a/sapi/apache/config.m4 +++ /dev/null @@ -1,273 +0,0 @@ -dnl -dnl $Id$ -dnl -AC_DEFUN([PHP_APACHE_FD_CHECK], [ -AC_CACHE_CHECK([for member fd in BUFF *],ac_cv_php_fd_in_buff,[ - save=$CPPFLAGS - if test -n "$APXS_INCLUDEDIR"; then - CPPFLAGS="$CPPFLAGS -I$APXS_INCLUDEDIR" - else - CPPFLAGS="$CPPFLAGS $APACHE_INCLUDE" - fi - AC_TRY_COMPILE([#include <httpd.h>],[conn_rec *c; int fd = c->client->fd;],[ - ac_cv_php_fd_in_buff=yes],[ac_cv_php_fd_in_buff=no],[ac_cv_php_fd_in_buff=no]) - CPPFLAGS=$save -]) -if test "$ac_cv_php_fd_in_buff" = "yes"; then - AC_DEFINE(PHP_APACHE_HAVE_CLIENT_FD,1,[ ]) -fi -]) - -dnl Apache 1.x shared module -PHP_ARG_WITH(apxs,, -[ --with-apxs[=FILE] Build shared Apache 1.x module. FILE is the optional - pathname to the Apache apxs tool [apxs]], no, no) - -AC_MSG_CHECKING([for Apache 1.x module support via DSO through APXS]) - -if test "$PHP_APXS" != "no"; then - if test "$PHP_APXS" = "yes"; then - APXS=apxs - $APXS -q CFLAGS >/dev/null 2>&1 - if test "$?" != "0" && test -x /usr/sbin/apxs; then #SUSE 6.x - APXS=/usr/sbin/apxs - fi - else - PHP_EXPAND_PATH($PHP_APXS, APXS) - fi - - $APXS -q CFLAGS >/dev/null 2>&1 - if test "$?" != "0"; then - AC_MSG_RESULT() - AC_MSG_RESULT() - AC_MSG_RESULT([Sorry, I was not able to successfully run APXS. Possible reasons:]) - AC_MSG_RESULT() - AC_MSG_RESULT([1. Perl is not installed;]) - AC_MSG_RESULT([2. Apache was not compiled with DSO support (--enable-module=so);]) - AC_MSG_RESULT([3. 'apxs' is not in your path. Try to use --with-apxs=/path/to/apxs]) - AC_MSG_RESULT([The output of $APXS follows]) - $APXS -q CFLAGS - AC_MSG_ERROR([Aborting]) - fi - - APXS_LDFLAGS="@SYBASE_LFLAGS@ @SYBASE_LIBS@ @SYBASE_CT_LFLAGS@ @SYBASE_CT_LIBS@" - APXS_INCLUDEDIR=`$APXS -q INCLUDEDIR` - APXS_CFLAGS=`$APXS -q CFLAGS` - APXS_HTTPD=`$APXS -q SBINDIR`/`$APXS -q TARGET` - APACHE_INCLUDE=-I$APXS_INCLUDEDIR - - # Test that we're trying to configure with apache 1.x - PHP_AP_EXTRACT_VERSION($APXS_HTTPD) - if test "$APACHE_VERSION" -ge 2000000; then - AC_MSG_ERROR([You have enabled Apache 1.3 support while your server is Apache 2. Please use the appropriate switch --with-apxs2]) - fi - - for flag in $APXS_CFLAGS; do - case $flag in - -D*) APACHE_CPPFLAGS="$APACHE_CPPFLAGS $flag";; - esac - done - - case $host_alias in - *aix*) - APXS_LIBEXECDIR=`$APXS -q LIBEXECDIR` - EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-brtl -Wl,-bI:$APXS_LIBEXECDIR/httpd.exp" - PHP_AIX_LDFLAGS="-Wl,-brtl" - build_type=shared - ;; - *darwin*) - MH_BUNDLE_FLAGS="-dynamic -twolevel_namespace -bundle -bundle_loader $APXS_HTTPD" - PHP_SUBST(MH_BUNDLE_FLAGS) - SAPI_SHARED=libs/libphp5.so - build_type=bundle - ;; - *) - build_type=shared - ;; - esac - - PHP_SELECT_SAPI(apache, $build_type, sapi_apache.c mod_php5.c php_apache.c, $APACHE_CPPFLAGS -I$APXS_INCLUDEDIR) - - # Test whether apxs support -S option - $APXS -q -S CFLAGS="$APXS_CFLAGS" CFLAGS >/dev/null 2>&1 - - if test "$?" != "0"; then - APACHE_INSTALL="$APXS -i -a -n php5 $SAPI_SHARED" # Old apxs does not have -S option - else - APXS_LIBEXECDIR='$(INSTALL_ROOT)'`$APXS -q LIBEXECDIR` - if test -z `$APXS -q SYSCONFDIR`; then - APACHE_INSTALL="\$(mkinstalldirs) '$APXS_LIBEXECDIR' && \ - $APXS -S LIBEXECDIR='$APXS_LIBEXECDIR' \ - -i -n php5 $SAPI_SHARED" - else - APXS_SYSCONFDIR='$(INSTALL_ROOT)'`$APXS -q SYSCONFDIR` - APACHE_INSTALL="\$(mkinstalldirs) '$APXS_LIBEXECDIR' && \ - \$(mkinstalldirs) '$APXS_SYSCONFDIR' && \ - $APXS -S LIBEXECDIR='$APXS_LIBEXECDIR' \ - -S SYSCONFDIR='$APXS_SYSCONFDIR' \ - -i -a -n php5 $SAPI_SHARED" - fi - fi - - if test -z "`$APXS -q LD_SHLIB`" || test "`$APXS -q LIBEXECDIR`" = "modules"; then - PHP_APXS_BROKEN=yes - fi - STRONGHOLD= - AC_DEFINE(HAVE_AP_CONFIG_H,1,[ ]) - AC_DEFINE(HAVE_AP_COMPAT_H,1,[ ]) - AC_DEFINE(HAVE_APACHE,1,[ ]) - AC_MSG_RESULT(yes) -else - AC_MSG_RESULT(no) -fi - -dnl Apache 1.x static module -PHP_ARG_WITH(apache,, -[ --with-apache[=DIR] Build Apache 1.x module. DIR is the top-level Apache - build directory [/usr/local/apache]], no, no) - -AC_MSG_CHECKING([for Apache 1.x module support]) - -if test "$PHP_SAPI" != "apache" && test "$PHP_APACHE" != "no"; then - - if test "$PHP_APACHE" = "yes"; then - # Apache's default directory - PHP_APACHE=/usr/local/apache - fi - - APACHE_INSTALL_FILES="\$(srcdir)/sapi/apache/mod_php5.* sapi/apache/libphp5.module" - - AC_DEFINE(HAVE_APACHE,1,[ ]) - APACHE_MODULE=yes - PHP_EXPAND_PATH($PHP_APACHE, PHP_APACHE) - # For Apache 1.2.x - if test -f $PHP_APACHE/src/httpd.h; then - APACHE_INCLUDE=-I$PHP_APACHE/src - APACHE_TARGET=$PHP_APACHE/src - PHP_SELECT_SAPI(apache, static, sapi_apache.c mod_php5.c php_apache.c, $APACHE_INCLUDE) - APACHE_INSTALL="mkdir -p $APACHE_TARGET; cp $SAPI_STATIC $APACHE_INSTALL_FILES $APACHE_TARGET" - PHP_LIBS="-L. -lphp3" - AC_MSG_RESULT([yes - Apache 1.2.x]) - STRONGHOLD= - if test -f $PHP_APACHE/src/ap_config.h; then - AC_DEFINE(HAVE_AP_CONFIG_H,1,[ ]) - fi - # For Apache 2.0.x - elif test -f $PHP_APACHE/include/httpd.h && test -f $PHP_APACHE/srclib/apr/include/apr_general.h ; then - AC_MSG_ERROR([Use --with-apxs2 with Apache 2.x!]) - # For Apache 1.3.x - elif test -f $PHP_APACHE/src/main/httpd.h; then - APACHE_HAS_REGEX=1 - APACHE_INCLUDE="-I$PHP_APACHE/src/main -I$PHP_APACHE/src/os/unix -I$PHP_APACHE/src/ap" - APACHE_TARGET=$PHP_APACHE/src/modules/php5 - if test ! -d $APACHE_TARGET; then - mkdir $APACHE_TARGET - fi - PHP_SELECT_SAPI(apache, static, sapi_apache.c mod_php5.c php_apache.c, $APACHE_INCLUDE) - APACHE_INSTALL="mkdir -p $APACHE_TARGET; cp $SAPI_STATIC $APACHE_TARGET/libmodphp5.a; cp $APACHE_INSTALL_FILES $APACHE_TARGET; cp $srcdir/sapi/apache/apMakefile.tmpl $APACHE_TARGET/Makefile.tmpl; cp $srcdir/sapi/apache/apMakefile.libdir $APACHE_TARGET/Makefile.libdir" - PHP_LIBS="-Lmodules/php5 -L../modules/php5 -L../../modules/php5 -lmodphp5" - AC_MSG_RESULT([yes - Apache 1.3.x]) - STRONGHOLD= - if test -f $PHP_APACHE/src/include/ap_config.h; then - AC_DEFINE(HAVE_AP_CONFIG_H, 1, [ ]) - fi - if test -f $PHP_APACHE/src/include/ap_compat.h; then - AC_DEFINE(HAVE_AP_COMPAT_H, 1, [ ]) - if test ! -f $PHP_APACHE/src/include/ap_config_auto.h; then - AC_MSG_ERROR([Please run Apache\'s configure or src/Configure program once and try again]) - fi - elif test -f $PHP_APACHE/src/include/compat.h; then - AC_DEFINE(HAVE_OLD_COMPAT_H, 1, [ ]) - fi - # Also for Apache 1.3.x - elif test -f $PHP_APACHE/src/include/httpd.h; then - APACHE_HAS_REGEX=1 - APACHE_INCLUDE="-I$PHP_APACHE/src/include -I$PHP_APACHE/src/os/unix" - APACHE_TARGET=$PHP_APACHE/src/modules/php5 - if test ! -d $APACHE_TARGET; then - mkdir $APACHE_TARGET - fi - PHP_SELECT_SAPI(apache, static, sapi_apache.c mod_php5.c php_apache.c, $APACHE_INCLUDE) - PHP_LIBS="-Lmodules/php5 -L../modules/php5 -L../../modules/php5 -lmodphp5" - APACHE_INSTALL="mkdir -p $APACHE_TARGET; cp $SAPI_STATIC $APACHE_TARGET/libmodphp5.a; cp $APACHE_INSTALL_FILES $APACHE_TARGET; cp $srcdir/sapi/apache/apMakefile.tmpl $APACHE_TARGET/Makefile.tmpl; cp $srcdir/sapi/apache/apMakefile.libdir $APACHE_TARGET/Makefile.libdir" - AC_MSG_RESULT([yes - Apache 1.3.x]) - STRONGHOLD= - if test -f $PHP_APACHE/src/include/ap_config.h; then - AC_DEFINE(HAVE_AP_CONFIG_H, 1, [ ]) - fi - if test -f $PHP_APACHE/src/include/ap_compat.h; then - AC_DEFINE(HAVE_AP_COMPAT_H, 1, [ ]) - if test ! -f $PHP_APACHE/src/include/ap_config_auto.h; then - AC_MSG_ERROR([Please run Apache\'s configure or src/Configure program once and try again]) - fi - elif test -f $PHP_APACHE/src/include/compat.h; then - AC_DEFINE(HAVE_OLD_COMPAT_H, 1, [ ]) - fi - # For StrongHold 2.2 - elif test -f $PHP_APACHE/apache/httpd.h; then - APACHE_INCLUDE="-I$PHP_APACHE/apache -I$PHP_APACHE/ssl/include" - APACHE_TARGET=$PHP_APACHE/apache - PHP_SELECT_SAPI(apache, static, sapi_apache.c mod_php5.c php_apache.c, $APACHE_INCLUDE) - PHP_LIBS="-Lmodules/php5 -L../modules/php5 -L../../modules/php5 -lmodphp5" - APACHE_INSTALL="mkdir -p $APACHE_TARGET; cp $SAPI_STATIC $APACHE_TARGET/libmodphp5.a; cp $APACHE_INSTALL_FILES $APACHE_TARGET" - STRONGHOLD=-DSTRONGHOLD=1 - AC_MSG_RESULT([yes - StrongHold]) - if test -f $PHP_APACHE/apache/ap_config.h; then - AC_DEFINE(HAVE_AP_CONFIG_H, 1, [ ]) - fi - if test -f $PHP_APACHE/src/ap_compat.h; then - AC_DEFINE(HAVE_AP_COMPAT_H, 1, [ ]) - if test ! -f $PHP_APACHE/src/include/ap_config_auto.h; then - AC_MSG_ERROR([Please run Apache\'s configure or src/Configure program once and try again]) - fi - elif test -f $PHP_APACHE/src/compat.h; then - AC_DEFINE(HAVE_OLD_COMPAT_H, 1, [ ]) - fi - else - AC_MSG_RESULT(no) - AC_MSG_ERROR([Invalid Apache directory - unable to find httpd.h under $PHP_APACHE]) - fi -else - AC_MSG_RESULT(no) -fi - -# compatibility -if test -z "$enable_mod_charset" && test "$with_mod_charset"; then - enable_mod_charset=$with_mod_charset -fi - -PHP_ARG_ENABLE(mod-charset, whether to enable Apache charset compatibility option, -[ --enable-mod-charset APACHE: Enable transfer tables for mod_charset (Rus Apache)], no, no) - -if test "$PHP_MOD_CHARSET" = "yes"; then - AC_DEFINE(USE_TRANSFER_TABLES, 1, [ ]) -fi - -dnl Build as static module -if test "$APACHE_MODULE" = "yes"; then - PHP_TARGET_RDYNAMIC - $php_shtool mkdir -p sapi/apache - PHP_OUTPUT(sapi/apache/libphp5.module) -fi - -dnl General -if test -n "$APACHE_INSTALL"; then - if test "x$APXS" != "x" -a "`uname -sv`" = "AIX 4" -a "$GCC" != "yes"; then - APXS_EXP=-bE:sapi/apache/mod_php5.exp - fi - - PHP_APACHE_FD_CHECK - INSTALL_IT=$APACHE_INSTALL - - PHP_SUBST(APXS_EXP) - PHP_SUBST(APACHE_INCLUDE) - PHP_SUBST(APACHE_TARGET) - PHP_SUBST(APXS) - PHP_SUBST(APXS_LDFLAGS) - PHP_SUBST(APACHE_INSTALL) - PHP_SUBST(STRONGHOLD) -fi - -dnl ## Local Variables: -dnl ## tab-width: 4 -dnl ## End: diff --git a/sapi/apache/config.w32 b/sapi/apache/config.w32 deleted file mode 100644 index e876d7500e..0000000000 --- a/sapi/apache/config.w32 +++ /dev/null @@ -1,24 +0,0 @@ -// vim:ft=javascript -// $Id$ - -ARG_ENABLE('apache', 'Build Apache 1.3.x version of PHP', 'no'); - -ARG_WITH('apache-includes', 'Where to find Apache 1.3 headers', null); -ARG_WITH('apache-libs', 'Where to find Apache 1.3 libraries', null); - -if (PHP_APACHE != "no") { - if (CHECK_HEADER_ADD_INCLUDE("httpd.h", "CFLAGS_APACHE", php_usual_include_suspects + - ";" + PROGRAM_FILES + "\\Apache Group\\Apache\\include" + - ";" + PHP_PHP_BUILD + "\\apache\\src\\include") && - CHECK_LIB("ApacheCore.lib", "apache", php_usual_lib_suspects + - ';' + PROGRAM_FILES + '\\Apache Group\\Apache\\libexec' + - ";" + PHP_PHP_BUILD + "\\apache\\src\\corer")) { - // We need to play tricks to get our readdir.h used by apache - // headers - SAPI('apache', 'mod_php5.c sapi_apache.c php_apache.c', - 'php' + PHP_VERSION + 'apache.dll', - '/D APACHEPHP5_EXPORTS /D APACHE_READDIR_H /I win32'); - } else { - WARNING("Could not find apache libraries/headers"); - } -} diff --git a/sapi/apache/libphp5.module.in b/sapi/apache/libphp5.module.in deleted file mode 100644 index 00d9c49f40..0000000000 --- a/sapi/apache/libphp5.module.in +++ /dev/null @@ -1,11 +0,0 @@ -Name: php5_module -ConfigStart - RULE_WANTHSREGEX=no - RULE_HIDE=yes - PHP_LIBS="@NATIVE_RPATHS@ @PHP_LDFLAGS@ @PHP_LIBS@ @EXTRA_LDFLAGS@ @EXTRA_LIBS@ $LIBS" - PHP_CFLAGS="$CFLAGS @OPENSSL_INCDIR_OPT@ -I@php_abs_top_builddir@/main -I@php_abs_top_builddir@/Zend -I@php_abs_top_builddir@/TSRM -I@php_abs_top_srcdir@ -I@php_abs_top_srcdir@/sapi/apache -I@php_abs_top_srcdir@/main -I@php_abs_top_srcdir@/Zend -I@php_abs_top_srcdir@/TSRM" - my_outfile="Makefile.config" - echo "PHP_CFLAGS=$PHP_CFLAGS" >>$my_outfile - echo "PHP_LIBS=$PHP_LIBS" >>$my_outfile - LIBS=$PHP_LIBS -ConfigEnd diff --git a/sapi/apache/libpre.c b/sapi/apache/libpre.c deleted file mode 100644 index 5bdec65bd3..0000000000 --- a/sapi/apache/libpre.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 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: | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#ifdef NETWARE - -/* ------------------------------------------------------------------ - * These functions are to be called when the shared NLM starts and - * stops. By using these functions instead of defining a main() - * and calling ExitThread(TSR_THREAD, 0), the load time of the - * shared NLM is faster and memory size reduced. - * - * You may also want to override these in your own Apache module - * to do any cleanup other than the mechanism Apache modules provide. - * ------------------------------------------------------------------ - */ - - -#ifdef __GNUC__ -#include <string.h> /* memset */ -extern char _edata, _end ; /* end of DATA (start of BSS), end of BSS */ -#endif - -int _lib_start() -{ -/* printf("Inside _lib_start\n");*/ -#ifdef __GNUC__ - memset (&_edata, 0, &_end - &_edata); -#endif - return 0; -} - -int _lib_stop() -{ -/* printf("Inside _lib_stop\n");*/ - return 0; -} - -#endif /* NETWARE */ diff --git a/sapi/apache/mod_php5.c b/sapi/apache/mod_php5.c deleted file mode 100644 index 545c725bde..0000000000 --- a/sapi/apache/mod_php5.c +++ /dev/null @@ -1,1040 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Rasmus Lerdorf <rasmus@php.net> | - | (with helpful hints from Dean Gaudet <dgaudet@arctic.org> | - | PHP 4.0 patches by Zeev Suraski <zeev@zend.com> | - +----------------------------------------------------------------------+ - */ -/* $Id$ */ - -#include "php_apache_http.h" -#include "http_conf_globals.h" - -#ifdef NETWARE -#define SIGPIPE SIGINT -#endif - -#undef shutdown - -/* {{{ Prototypes - */ -int apache_php_module_main(request_rec *r, int display_source_mode TSRMLS_DC); -static void php_save_umask(void); -static void php_restore_umask(void); -static int sapi_apache_read_post(char *buffer, uint count_bytes TSRMLS_DC); -static char *sapi_apache_read_cookies(TSRMLS_D); -static int sapi_apache_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC); -static int sapi_apache_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC); -static int send_php(request_rec *r, int display_source_mode, char *filename); -static int send_parsed_php(request_rec * r); -static int send_parsed_php_source(request_rec * r); -static int php_xbithack_handler(request_rec * r); -static void php_init_handler(server_rec *s, pool *p); -/* }}} */ - -#if MODULE_MAGIC_NUMBER >= 19970728 -static void php_child_exit_handler(server_rec *s, pool *p); -#endif - -#if MODULE_MAGIC_NUMBER > 19961007 -#define CONST_PREFIX const -#else -#define CONST_PREFIX -#endif -static CONST_PREFIX char *php_apache_value_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode); -static CONST_PREFIX char *php_apache_value_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2); -static CONST_PREFIX char *php_apache_admin_value_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2); -static CONST_PREFIX char *php_apache_flag_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2); -static CONST_PREFIX char *php_apache_flag_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode); -static CONST_PREFIX char *php_apache_admin_flag_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2); - -/* ### these should be defined in mod_php5.h or somewhere else */ -#define USE_PATH 1 -#define IGNORE_URL 2 -#define MAX_STATUS_LENGTH sizeof("xxxx LONGEST POSSIBLE STATUS DESCRIPTION") - -module MODULE_VAR_EXPORT php5_module; - -int saved_umask; -static unsigned char apache_php_initialized; - -typedef struct _php_per_dir_entry { - char *key; - char *value; - uint key_length; - uint value_length; - int type; - char htaccess; -} php_per_dir_entry; - -/* some systems are missing these from their header files */ - -/* {{{ php_save_umask - */ -static void php_save_umask(void) -{ - saved_umask = umask(077); - umask(saved_umask); -} -/* }}} */ - -/* {{{ sapi_apache_ub_write - */ -static int sapi_apache_ub_write(const char *str, uint str_length TSRMLS_DC) -{ - int ret=0; - - if (SG(server_context)) { - ret = rwrite(str, str_length, (request_rec *) SG(server_context)); - } - if (ret != str_length) { - php_handle_aborted_connection(); - } - return ret; -} -/* }}} */ - -/* {{{ sapi_apache_flush - */ -static void sapi_apache_flush(void *server_context) -{ - if (server_context) { -#if MODULE_MAGIC_NUMBER > 19970110 - rflush((request_rec *) server_context); -#else - bflush((request_rec *) server_context->connection->client); -#endif - } -} -/* }}} */ - -/* {{{ sapi_apache_read_post - */ -static int sapi_apache_read_post(char *buffer, uint count_bytes TSRMLS_DC) -{ - int total_read_bytes=0, read_bytes; - request_rec *r = (request_rec *) SG(server_context); - void (*handler)(int); - - /* - * This handles the situation where the browser sends a Expect: 100-continue header - * and needs to receive confirmation from the server on whether or not it can send - * the rest of the request. RFC 2616 - * - */ - if (!SG(read_post_bytes) && !ap_should_client_block(r)) { - return total_read_bytes; - } - - handler = signal(SIGPIPE, SIG_IGN); - while (total_read_bytes<count_bytes) { - hard_timeout("Read POST information", r); /* start timeout timer */ - read_bytes = get_client_block(r, buffer+total_read_bytes, count_bytes-total_read_bytes); - reset_timeout(r); - if (read_bytes<=0) { - break; - } - total_read_bytes += read_bytes; - } - signal(SIGPIPE, handler); - return total_read_bytes; -} -/* }}} */ - -/* {{{ sapi_apache_read_cookies - */ -static char *sapi_apache_read_cookies(TSRMLS_D) -{ - return (char *) table_get(((request_rec *) SG(server_context))->subprocess_env, "HTTP_COOKIE"); -} -/* }}} */ - -/* {{{ sapi_apache_header_handler - */ -static int sapi_apache_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - char *header_name, *header_content, *p; - request_rec *r = (request_rec *) SG(server_context); - if(!r) { - return 0; - } - - switch(op) { - case SAPI_HEADER_DELETE_ALL: - clear_table(r->headers_out); - return 0; - - case SAPI_HEADER_DELETE: - table_unset(r->headers_out, sapi_header->header); - return 0; - - case SAPI_HEADER_ADD: - case SAPI_HEADER_REPLACE: - header_name = sapi_header->header; - - header_content = p = strchr(header_name, ':'); - if (!p) { - return 0; - } - - *p = 0; - do { - header_content++; - } while (*header_content==' '); - - if (!strcasecmp(header_name, "Content-Type")) { - r->content_type = pstrdup(r->pool, header_content); - } else if (!strcasecmp(header_name, "Content-Length")) { - ap_set_content_length(r, strtol(header_content, (char **)NULL, 10)); - } else if (!strcasecmp(header_name, "Set-Cookie")) { - table_add(r->headers_out, header_name, header_content); - } else if (op == SAPI_HEADER_REPLACE) { - table_set(r->headers_out, header_name, header_content); - } else { - table_add(r->headers_out, header_name, header_content); - } - - *p = ':'; /* a well behaved header handler shouldn't change its original arguments */ - - return SAPI_HEADER_ADD; - - default: - return 0; - } -} -/* }}} */ - -/* {{{ sapi_apache_send_headers - */ -static int sapi_apache_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - request_rec *r = SG(server_context); - const char *sline = SG(sapi_headers).http_status_line; - int sline_len; - - if(r == NULL) { /* server_context is not here anymore */ - return SAPI_HEADER_SEND_FAILED; - } - - 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 && ((sline_len = strlen(sline)) > 12) && strncmp(sline, "HTTP/1.", 7) == 0 && sline[8] == ' ' && sline[12] == ' ') { - if ((sline_len - 9) > MAX_STATUS_LENGTH) { - r->status_line = ap_pstrndup(r->pool, sline + 9, MAX_STATUS_LENGTH); - } else { - r->status_line = ap_pstrndup(r->pool, sline + 9, sline_len - 9); - } - } - - if(r->status==304) { - send_error_response(r,0); - } else { - send_http_header(r); - } - return SAPI_HEADER_SENT_SUCCESSFULLY; -} -/* }}} */ - -/* {{{ sapi_apache_register_server_variables - */ -static void sapi_apache_register_server_variables(zval *track_vars_array TSRMLS_DC) -{ - register int i; - array_header *arr = table_elts(((request_rec *) SG(server_context))->subprocess_env); - table_entry *elts = (table_entry *) arr->elts; - zval **path_translated; - HashTable *symbol_table; - unsigned int new_val_len; - - for (i = 0; i < arr->nelts; i++) { - char *val; - int val_len; - - if (elts[i].val) { - val = elts[i].val; - } else { - val = ""; - } - val_len = strlen(val); - if (sapi_module.input_filter(PARSE_SERVER, elts[i].key, &val, val_len, &new_val_len TSRMLS_CC)) { - php_register_variable_safe(elts[i].key, val, new_val_len, track_vars_array TSRMLS_CC); - } - } - - /* If PATH_TRANSLATED doesn't exist, copy it from SCRIPT_FILENAME */ - if (track_vars_array) { - symbol_table = track_vars_array->value.ht; - } else { - symbol_table = NULL; - } - if (symbol_table - && !zend_hash_exists(symbol_table, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED")) - && zend_hash_find(symbol_table, "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME"), (void **) &path_translated)==SUCCESS) { - php_register_variable("PATH_TRANSLATED", Z_STRVAL_PP(path_translated), track_vars_array TSRMLS_CC); - } - - if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &((request_rec *) SG(server_context))->uri, strlen(((request_rec *) SG(server_context))->uri), &new_val_len TSRMLS_CC)) { - php_register_variable("PHP_SELF", ((request_rec *) SG(server_context))->uri, track_vars_array TSRMLS_CC); - } -} -/* }}} */ - -/* {{{ php_apache_startup - */ -static int php_apache_startup(sapi_module_struct *sapi_module) -{ - if (php_module_startup(sapi_module, &apache_module_entry, 1) == FAILURE) { - return FAILURE; - } else { - return SUCCESS; - } -} -/* }}} */ - -/* {{{ php_apache_log_message - */ -static void php_apache_log_message(char *message TSRMLS_DC) -{ - if (SG(server_context)) { -#if MODULE_MAGIC_NUMBER >= 19970831 - aplog_error(NULL, 0, APLOG_ERR | APLOG_NOERRNO, ((request_rec *) SG(server_context))->server, "%s", message); -#else - log_error(message, ((request_rec *) SG(server_context))->server); -#endif - } else { - fprintf(stderr, "%s\n", message); - } -} -/* }}} */ - -/* {{{ php_apache_request_shutdown - */ -static void php_apache_request_shutdown(void *dummy) -{ - TSRMLS_FETCH(); - - php_output_set_status(PHP_OUTPUT_DISABLED TSRMLS_CC); - if (AP(in_request)) { - AP(in_request) = 0; - php_request_shutdown(dummy); - } - SG(server_context) = NULL; - /* - * The server context (request) is NOT invalid by the time - * run_cleanups() is called - */ -} -/* }}} */ - -/* {{{ php_apache_sapi_activate - */ -static int php_apache_sapi_activate(TSRMLS_D) -{ - request_rec *r = (request_rec *) SG(server_context); - - /* - * For the Apache module version, this bit of code registers a cleanup - * function that gets triggered when our request pool is destroyed. - * We need this because at any point in our code we can be interrupted - * and that may happen before we have had time to free our memory. - * The php_request_shutdown function needs to free all outstanding allocated - * memory. - */ - block_alarms(); - register_cleanup(r->pool, NULL, php_apache_request_shutdown, php_request_shutdown_for_exec); - AP(in_request)=1; - unblock_alarms(); - - /* Override the default headers_only value - sometimes "GET" requests should actually only - * send headers. - */ - SG(request_info).headers_only = r->header_only; - return SUCCESS; -} -/* }}} */ - -/* {{{ php_apache_get_stat - */ -static struct stat *php_apache_get_stat(TSRMLS_D) -{ - return &((request_rec *) SG(server_context))->finfo; -} -/* }}} */ - -/* {{{ php_apache_getenv - */ -static char *php_apache_getenv(char *name, size_t name_len TSRMLS_DC) -{ - if (SG(server_context) == NULL) { - return NULL; - } - - return (char *) table_get(((request_rec *) SG(server_context))->subprocess_env, name); -} -/* }}} */ - -/* {{{ sapi_apache_get_fd - */ -static int sapi_apache_get_fd(int *nfd TSRMLS_DC) -{ -#if PHP_APACHE_HAVE_CLIENT_FD - request_rec *r = SG(server_context); - int fd; - - fd = r->connection->client->fd; - - if (fd >= 0) { - if (nfd) *nfd = fd; - return SUCCESS; - } -#endif - return FAILURE; -} -/* }}} */ - -/* {{{ sapi_apache_force_http_10 - */ -static int sapi_apache_force_http_10(TSRMLS_D) -{ - request_rec *r = SG(server_context); - - r->proto_num = HTTP_VERSION(1,0); - - return SUCCESS; -} -/* }}} */ - -/* {{{ sapi_apache_get_target_uid - */ -static int sapi_apache_get_target_uid(uid_t *obj TSRMLS_DC) -{ - *obj = ap_user_id; - return SUCCESS; -} -/* }}} */ - -/* {{{ sapi_apache_get_target_gid - */ -static int sapi_apache_get_target_gid(gid_t *obj TSRMLS_DC) -{ - *obj = ap_group_id; - return SUCCESS; -} -/* }}} */ - -/* {{{ php_apache_get_request_time - */ -static double php_apache_get_request_time(TSRMLS_D) -{ - return (double) ((request_rec *)SG(server_context))->request_time; -} -/* }}} */ - -/* {{{ sapi_apache_child_terminate - */ -static void sapi_apache_child_terminate(TSRMLS_D) -{ -#ifndef MULTITHREAD - ap_child_terminate((request_rec *)SG(server_context)); -#endif -} -/* }}} */ - -/* {{{ sapi_module_struct apache_sapi_module - */ -static sapi_module_struct apache_sapi_module = { - "apache", /* name */ - "Apache", /* pretty name */ - - php_apache_startup, /* startup */ - php_module_shutdown_wrapper, /* shutdown */ - - php_apache_sapi_activate, /* activate */ - NULL, /* deactivate */ - - sapi_apache_ub_write, /* unbuffered write */ - sapi_apache_flush, /* flush */ - php_apache_get_stat, /* get uid */ - php_apache_getenv, /* getenv */ - - php_error, /* error handler */ - - sapi_apache_header_handler, /* header handler */ - sapi_apache_send_headers, /* send headers handler */ - NULL, /* send header handler */ - - sapi_apache_read_post, /* read POST data */ - sapi_apache_read_cookies, /* read Cookies */ - - sapi_apache_register_server_variables, /* register server variables */ - php_apache_log_message, /* Log message */ - php_apache_get_request_time, /* Get request time */ - sapi_apache_child_terminate, - - NULL, /* php.ini path override */ - -#ifdef PHP_WIN32 - NULL, - NULL, -#else - block_alarms, /* Block interruptions */ - unblock_alarms, /* Unblock interruptions */ -#endif - - NULL, /* default post reader */ - NULL, /* treat data */ - NULL, /* exe location */ - 0, /* ini ignore */ - 0, /* ini ignore cwd */ - sapi_apache_get_fd, - sapi_apache_force_http_10, - sapi_apache_get_target_uid, - sapi_apache_get_target_gid -}; -/* }}} */ - -/* {{{ php_restore_umask - */ -static void php_restore_umask(void) -{ - umask(saved_umask); -} -/* }}} */ - -/* {{{ init_request_info - */ -static void init_request_info(TSRMLS_D) -{ - request_rec *r = ((request_rec *) SG(server_context)); - char *content_length = (char *) table_get(r->subprocess_env, "CONTENT_LENGTH"); - const char *authorization=NULL; - char *tmp, *tmp_user; - - SG(request_info).query_string = r->args; - SG(request_info).path_translated = r->filename; - SG(request_info).request_uri = r->uri; - SG(request_info).request_method = (char *)r->method; - SG(request_info).content_type = (char *) table_get(r->subprocess_env, "CONTENT_TYPE"); - SG(request_info).content_length = (content_length ? atol(content_length) : 0); - SG(sapi_headers).http_response_code = r->status; - SG(request_info).proto_num = r->proto_num; - - if (r->headers_in) { - authorization = table_get(r->headers_in, "Authorization"); - } - - SG(request_info).auth_user = NULL; - SG(request_info).auth_password = NULL; - SG(request_info).auth_digest = NULL; - - if (authorization) { - char *p = getword(r->pool, &authorization, ' '); - if (!strcasecmp(p, "Basic")) { - tmp = uudecode(r->pool, authorization); - tmp_user = getword_nulls_nc(r->pool, &tmp, ':'); - if (tmp_user) { - r->connection->user = pstrdup(r->connection->pool, tmp_user); - r->connection->ap_auth_type = "Basic"; - SG(request_info).auth_user = estrdup(tmp_user); - } - if (tmp) { - SG(request_info).auth_password = estrdup(tmp); - } - } else if (!strcasecmp(p, "Digest")) { - r->connection->ap_auth_type = "Digest"; - SG(request_info).auth_digest = estrdup(authorization); - } - } -} -/* }}} */ - -/* {{{ php_apache_alter_ini_entries - */ -static int php_apache_alter_ini_entries(php_per_dir_entry *per_dir_entry TSRMLS_DC) -{ - zend_alter_ini_entry(per_dir_entry->key, per_dir_entry->key_length+1, per_dir_entry->value, per_dir_entry->value_length, per_dir_entry->type, per_dir_entry->htaccess?PHP_INI_STAGE_HTACCESS:PHP_INI_STAGE_ACTIVATE); - return 0; -} -/* }}} */ - -/* {{{ php_apache_get_default_mimetype - */ -static char *php_apache_get_default_mimetype(request_rec *r TSRMLS_DC) -{ - - char *mimetype; - if (SG(default_mimetype) || SG(default_charset)) { - /* Assume output will be of the default MIME type. Individual - scripts may change this later. */ - char *tmpmimetype; - tmpmimetype = sapi_get_default_content_type(TSRMLS_C); - mimetype = pstrdup(r->pool, tmpmimetype); - efree(tmpmimetype); - } else { - mimetype = SAPI_DEFAULT_MIMETYPE "; charset=" SAPI_DEFAULT_CHARSET; - } - return mimetype; -} -/* }}} */ - -/* {{{ send_php - */ -static int send_php(request_rec *r, int display_source_mode, char *filename) -{ - int retval; - HashTable *per_dir_conf; - TSRMLS_FETCH(); - - if (AP(in_request)) { - zend_file_handle fh; - - fh.filename = r->filename; - fh.opened_path = NULL; - fh.free_filename = 0; - fh.type = ZEND_HANDLE_FILENAME; - - zend_execute_scripts(ZEND_INCLUDE TSRMLS_CC, NULL, 1, &fh); - return OK; - } - - SG(server_context) = r; - - zend_first_try { - - /* Make sure file exists */ - if (filename == NULL && r->finfo.st_mode == 0) { - return DECLINED; - } - - per_dir_conf = (HashTable *) get_module_config(r->per_dir_config, &php5_module); - if (per_dir_conf) { - zend_hash_apply((HashTable *) per_dir_conf, (apply_func_t) php_apache_alter_ini_entries TSRMLS_CC); - } - - /* If PHP parser engine has been turned off with an "engine off" - * directive, then decline to handle this request - */ - if (!AP(engine)) { - r->content_type = php_apache_get_default_mimetype(r TSRMLS_CC); - zend_try { - zend_ini_deactivate(TSRMLS_C); - } zend_end_try(); - return DECLINED; - } - if (filename == NULL) { - filename = r->filename; - } - - /* Apache 1.2 has a more complex mechanism for reading POST data */ -#if MODULE_MAGIC_NUMBER > 19961007 - if ((retval = setup_client_block(r, REQUEST_CHUNKED_DECHUNK))) { - zend_try { - zend_ini_deactivate(TSRMLS_C); - } zend_end_try(); - return retval; - } -#endif - - if (AP(last_modified)) { -#if MODULE_MAGIC_NUMBER < 19970912 - if ((retval = set_last_modified(r, r->finfo.st_mtime))) { - zend_try { - zend_ini_deactivate(TSRMLS_C); - } zend_end_try(); - return retval; - } -#else - update_mtime (r, r->finfo.st_mtime); - set_last_modified(r); - set_etag(r); -#endif - } - /* Assume output will be of the default MIME type. Individual - scripts may change this later in the request. */ - r->content_type = php_apache_get_default_mimetype(r TSRMLS_CC); - - /* Init timeout */ - hard_timeout("send", r); - - php_save_umask(); - add_common_vars(r); - add_cgi_vars(r); - - init_request_info(TSRMLS_C); - apache_php_module_main(r, display_source_mode TSRMLS_CC); - - /* Done, restore umask, turn off timeout, close file and return */ - php_restore_umask(); - kill_timeout(r); - } zend_end_try(); - - return OK; -} -/* }}} */ - -/* {{{ send_parsed_php - */ -static int send_parsed_php(request_rec * r) -{ - int result = send_php(r, 0, NULL); - TSRMLS_FETCH(); - - ap_table_setn(r->notes, "mod_php_memory_usage", - ap_psprintf(r->pool, "%lu", zend_memory_peak_usage(1 TSRMLS_CC))); - - return result; -} -/* }}} */ - -/* {{{ send_parsed_php_source - */ -static int send_parsed_php_source(request_rec * r) -{ - return send_php(r, 1, NULL); -} -/* }}} */ - -/* {{{ destroy_per_dir_entry - */ -static void destroy_per_dir_entry(php_per_dir_entry *per_dir_entry) -{ - free(per_dir_entry->key); - free(per_dir_entry->value); -} -/* }}} */ - -/* {{{ copy_per_dir_entry - */ -static void copy_per_dir_entry(php_per_dir_entry *per_dir_entry) -{ - php_per_dir_entry tmp = *per_dir_entry; - - per_dir_entry->key = (char *) malloc(tmp.key_length+1); - memcpy(per_dir_entry->key, tmp.key, tmp.key_length); - per_dir_entry->key[per_dir_entry->key_length] = 0; - - per_dir_entry->value = (char *) malloc(tmp.value_length+1); - memcpy(per_dir_entry->value, tmp.value, tmp.value_length); - per_dir_entry->value[per_dir_entry->value_length] = 0; -} -/* }}} */ - -/* {{{ should_overwrite_per_dir_entry - */ -static zend_bool should_overwrite_per_dir_entry(HashTable *target_ht, php_per_dir_entry *new_per_dir_entry, zend_hash_key *hash_key, void *pData) -{ - php_per_dir_entry *orig_per_dir_entry; - - if (zend_hash_find(target_ht, hash_key->arKey, hash_key->nKeyLength, (void **) &orig_per_dir_entry)==FAILURE) { - return 1; /* does not exist in dest, copy from source */ - } - - if (orig_per_dir_entry->type==PHP_INI_SYSTEM - && new_per_dir_entry->type!=PHP_INI_SYSTEM) { - return 0; - } else { - return 1; - } -} -/* }}} */ - -/* {{{ php_destroy_per_dir_info - */ -static void php_destroy_per_dir_info(HashTable *per_dir_info) -{ - zend_hash_destroy(per_dir_info); - free(per_dir_info); -} -/* }}} */ - -/* {{{ php_create_dir - */ -static void *php_create_dir(pool *p, char *dummy) -{ - HashTable *per_dir_info; - - per_dir_info = (HashTable *) malloc(sizeof(HashTable)); - zend_hash_init_ex(per_dir_info, 5, NULL, (void (*)(void *)) destroy_per_dir_entry, 1, 0); - register_cleanup(p, (void *) per_dir_info, (void (*)(void *)) php_destroy_per_dir_info, (void (*)(void *)) zend_hash_destroy); - - return per_dir_info; -} -/* }}} */ - -/* {{{ php_merge_dir - */ -static void *php_merge_dir(pool *p, void *basev, void *addv) -{ - /* This function *must* not modify addv or basev */ - HashTable *new; - - /* need a copy of addv to merge */ - new = php_create_dir(p, "php_merge_dir"); - zend_hash_copy(new, (HashTable *) basev, (copy_ctor_func_t) copy_per_dir_entry, NULL, sizeof(php_per_dir_entry)); - - zend_hash_merge_ex(new, (HashTable *) addv, (copy_ctor_func_t) copy_per_dir_entry, sizeof(php_per_dir_entry), (merge_checker_func_t) should_overwrite_per_dir_entry, NULL); - return new; -} -/* }}} */ - -/* {{{ php_apache_value_handler_ex - */ -static CONST_PREFIX char *php_apache_value_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode) -{ - php_per_dir_entry per_dir_entry; - - if (!apache_php_initialized) { - apache_php_initialized = 1; -#ifdef ZTS - tsrm_startup(1, 1, 0, NULL); -#endif - sapi_startup(&apache_sapi_module); - php_apache_startup(&apache_sapi_module); - } - per_dir_entry.type = mode; - per_dir_entry.htaccess = ((cmd->override & (RSRC_CONF|ACCESS_CONF)) == 0); - - if (strcasecmp(arg2, "none") == 0) { - arg2 = ""; - } - - per_dir_entry.key_length = strlen(arg1); - per_dir_entry.value_length = strlen(arg2); - - per_dir_entry.key = (char *) malloc(per_dir_entry.key_length+1); - memcpy(per_dir_entry.key, arg1, per_dir_entry.key_length); - per_dir_entry.key[per_dir_entry.key_length] = 0; - - per_dir_entry.value = (char *) malloc(per_dir_entry.value_length+1); - memcpy(per_dir_entry.value, arg2, per_dir_entry.value_length); - per_dir_entry.value[per_dir_entry.value_length] = 0; - - zend_hash_update(conf, per_dir_entry.key, per_dir_entry.key_length, &per_dir_entry, sizeof(php_per_dir_entry), NULL); - return NULL; -} -/* }}} */ - -/* {{{ php_apache_value_handler - */ -static CONST_PREFIX char *php_apache_value_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2) -{ - return php_apache_value_handler_ex(cmd, conf, arg1, arg2, PHP_INI_PERDIR); -} -/* }}} */ - -/* {{{ php_apache_admin_value_handler - */ -static CONST_PREFIX char *php_apache_admin_value_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2) -{ - return php_apache_value_handler_ex(cmd, conf, arg1, arg2, PHP_INI_SYSTEM); -} -/* }}} */ - -/* {{{ php_apache_flag_handler_ex - */ -static CONST_PREFIX char *php_apache_flag_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode) -{ - 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 php_apache_value_handler_ex(cmd, conf, arg1, bool_val, mode); -} -/* }}} */ - -/* {{{ php_apache_flag_handler - */ -static CONST_PREFIX char *php_apache_flag_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2) -{ - return php_apache_flag_handler_ex(cmd, conf, arg1, arg2, PHP_INI_PERDIR); -} -/* }}} */ - -/* {{{ php_apache_admin_flag_handler - */ -static CONST_PREFIX char *php_apache_admin_flag_handler(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2) -{ - return php_apache_flag_handler_ex(cmd, conf, arg1, arg2, PHP_INI_SYSTEM); -} -/* }}} */ - -/* {{{ php_apache_phpini_set - */ -static CONST_PREFIX char *php_apache_phpini_set(cmd_parms *cmd, HashTable *conf, char *arg) -{ - if (apache_sapi_module.php_ini_path_override) { - return "Only first PHPINIDir directive honored per configuration tree - subsequent ones ignored"; - } - apache_sapi_module.php_ini_path_override = ap_server_root_relative(cmd->pool, arg); - return NULL; -} -/* }}} */ - -/* {{{ int php_xbithack_handler(request_rec * r) - */ -static int php_xbithack_handler(request_rec * r) -{ - HashTable *per_dir_conf; - TSRMLS_FETCH(); - - if (!(r->finfo.st_mode & S_IXUSR)) { - return DECLINED; - } - per_dir_conf = (HashTable *) get_module_config(r->per_dir_config, &php5_module); - if (per_dir_conf) { - zend_hash_apply((HashTable *) per_dir_conf, (apply_func_t) php_apache_alter_ini_entries TSRMLS_CC); - } - if(!AP(xbithack)) { - zend_try { - zend_ini_deactivate(TSRMLS_C); - } zend_end_try(); - return DECLINED; - } - return send_parsed_php(r); -} -/* }}} */ - -/* {{{ apache_php_module_shutdown_wrapper - */ -static void apache_php_module_shutdown_wrapper(void) -{ - apache_php_initialized = 0; - apache_sapi_module.shutdown(&apache_sapi_module); - -#if MODULE_MAGIC_NUMBER >= 19970728 - /* This function is only called on server exit if the apache API - * child_exit handler exists, so shutdown globally - */ - sapi_shutdown(); -#endif - -#ifdef ZTS - tsrm_shutdown(); -#endif -} -/* }}} */ - -#if MODULE_MAGIC_NUMBER >= 19970728 -/* {{{ php_child_exit_handler - */ -static void php_child_exit_handler(server_rec *s, pool *p) -{ -/* apache_php_initialized = 0; */ - apache_sapi_module.shutdown(&apache_sapi_module); - -#ifdef ZTS - tsrm_shutdown(); -#endif -} -/* }}} */ -#endif - -/* {{{ void php_init_handler(server_rec *s, pool *p) - */ -static void php_init_handler(server_rec *s, pool *p) -{ - register_cleanup(p, NULL, (void (*)(void *))apache_php_module_shutdown_wrapper, (void (*)(void *))php_module_shutdown_for_exec); - if (!apache_php_initialized) { - apache_php_initialized = 1; -#ifdef ZTS - tsrm_startup(1, 1, 0, NULL); -#endif - sapi_startup(&apache_sapi_module); - php_apache_startup(&apache_sapi_module); - } -#if MODULE_MAGIC_NUMBER >= 19980527 - { - TSRMLS_FETCH(); - if (PG(expose_php)) { - ap_add_version_component("PHP/" PHP_VERSION); - } - } -#endif -} -/* }}} */ - -/* {{{ handler_rec php_handlers[] - */ -handler_rec php_handlers[] = -{ - {"application/x-httpd-php", send_parsed_php}, - {"application/x-httpd-php-source", send_parsed_php_source}, - {"text/html", php_xbithack_handler}, - {NULL} -}; -/* }}} */ - -/* {{{ command_rec php_commands[] - */ -command_rec php_commands[] = -{ - {"php_value", php_apache_value_handler, NULL, OR_OPTIONS, TAKE2, "PHP Value Modifier"}, - {"php_flag", php_apache_flag_handler, NULL, OR_OPTIONS, TAKE2, "PHP Flag Modifier"}, - {"php_admin_value", php_apache_admin_value_handler, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "PHP Value Modifier (Admin)"}, - {"php_admin_flag", php_apache_admin_flag_handler, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "PHP Flag Modifier (Admin)"}, - {"PHPINIDir", php_apache_phpini_set, NULL, RSRC_CONF, TAKE1, "Directory containing the php.ini file"}, - {NULL} -}; -/* }}} */ - -/* {{{ odule MODULE_VAR_EXPORT php5_module - */ -module MODULE_VAR_EXPORT php5_module = -{ - STANDARD_MODULE_STUFF, - php_init_handler, /* initializer */ - php_create_dir, /* per-directory config creator */ - php_merge_dir, /* dir merger */ - NULL, /* per-server config creator */ - NULL, /* merge server config */ - php_commands, /* command table */ - php_handlers, /* handlers */ - NULL, /* filename translation */ - NULL, /* check_user_id */ - NULL, /* check auth */ - NULL, /* check access */ - NULL, /* type_checker */ - NULL, /* fixups */ - NULL /* logger */ -#if MODULE_MAGIC_NUMBER >= 19970103 - , NULL /* header parser */ -#endif -#if MODULE_MAGIC_NUMBER >= 19970719 - , NULL /* child_init */ -#endif -#if MODULE_MAGIC_NUMBER >= 19970728 - , php_child_exit_handler /* child_exit */ -#endif -#if MODULE_MAGIC_NUMBER >= 19970902 - , NULL /* post read-request */ -#endif -}; -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/sapi/apache/mod_php5.exp b/sapi/apache/mod_php5.exp deleted file mode 100644 index 9ad0f0a0ad..0000000000 --- a/sapi/apache/mod_php5.exp +++ /dev/null @@ -1 +0,0 @@ -php5_module diff --git a/sapi/apache/php.sym b/sapi/apache/php.sym deleted file mode 100644 index 9ad0f0a0ad..0000000000 --- a/sapi/apache/php.sym +++ /dev/null @@ -1 +0,0 @@ -php5_module diff --git a/sapi/apache/php5apache.dsp b/sapi/apache/php5apache.dsp deleted file mode 100644 index fbdb7612b8..0000000000 --- a/sapi/apache/php5apache.dsp +++ /dev/null @@ -1,151 +0,0 @@ -# Microsoft Developer Studio Project File - Name="php5apache" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=php5apache - Win32 Release_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 "php5apache.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 "php5apache.mak" CFG="php5apache - Win32 Release_TS"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "php5apache - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "php5apache - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "php5apache - Win32 Release_TS_inline" (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)" == "php5apache - 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 "APACHEPHP5_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "...\..\include" /I "..\..\win32" /I "..\..\Zend" /I "..\.." /I "..\..\..\bindlib_w32" /I "..\..\..\php_build\includes" /I "..\..\main" /I "..\..\TSRM" /I "..\..\regex" /I "C:\Program Files\Apache Group\Apache\include" /D ZEND_DEBUG=0 /D "NDEBUG" /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "_WINDOWS" /D "_USRDLL" /D "APACHEPHP5_EXPORTS" /D "WIN32" /D "_MBCS" /D "APACHE_READDIR_H" /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /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 php5ts.lib ApacheCore.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 /base:"0x60000000" /version:4.0 /dll /machine:I386 /libpath:"..\..\..\php_build\release" /libpath:"..\..\Release_TS" /libpath:"..\..\TSRM\Release_TS" /libpath:"..\..\Zend\Release_TS" /libpath:"C:\Program Files\Apache Group\Apache\libexec"
-
-!ELSEIF "$(CFG)" == "php5apache - Win32 Debug_TS"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Debug_TS"
-# PROP BASE Intermediate_Dir "Debug_TS"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "..\..\Debug_TS"
-# PROP Intermediate_Dir "Debug_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 "APACHEPHP5_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "...\..\include" /I "..\..\win32" /I "..\..\Zend" /I "..\.." /I "..\..\..\bindlib_w32" /I "..\..\..\php_build\includes" /I "..\..\main" /I "..\..\TSRM" /I "..\..\regex" /I "C:\Program Files\Apache Group\Apache\include" /D "_DEBUG" /D ZEND_DEBUG=1 /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "_WINDOWS" /D "_USRDLL" /D "APACHEPHP5_EXPORTS" /D "WIN32" /D "_MBCS" /D "APACHE_READDIR_H" /FR /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /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 php5ts_debug.lib ApacheCore.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 /base:"0x60000000" /version:4.0 /dll /incremental:yes /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\php_build\release" /libpath:"..\..\Debug_TS" /libpath:"..\..\TSRM\Debug_TS" /libpath:"..\..\Zend\Debug_TS" /libpath:"C:\Program Files\Apache Group\Apache\libexec"
-
-!ELSEIF "$(CFG)" == "php5apache - 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 "APACHEPHP5_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "...\..\include" /I "..\..\win32" /I "..\..\Zend" /I "..\.." /I "..\..\..\bindlib_w32" /I "..\..\..\php_build\includes" /I "..\..\main" /I "..\..\TSRM" /I "..\..\regex" /I "C:\Program Files\Apache Group\Apache\include" /D ZEND_DEBUG=0 /D "ZEND_WIN32_FORCE_INLINE" /D "NDEBUG" /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "_WINDOWS" /D "_USRDLL" /D "APACHEPHP5_EXPORTS" /D "WIN32" /D "_MBCS" /D "APACHE_READDIR_H" /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /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 php5ts.lib ApacheCore.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 /version:4.0 /dll /machine:I386 /libpath:"..\..\..\php_build\release" /libpath:"..\..\Release_TS_inline" /libpath:"..\..\TSRM\Release_TS_inline" /libpath:"..\..\Zend\Release_TS_inline" /libpath:"C:\Program Files\Apache Group\Apache\libexec"
-
-!ENDIF
-
-# Begin Target
-
-# Name "php5apache - Win32 Release_TS"
-# Name "php5apache - Win32 Debug_TS"
-# Name "php5apache - Win32 Release_TS_inline"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\mod_php5.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\php_apache.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\sapi_apache.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\mod_php5.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\php_apache_http.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/sapi/apache/php_apache.c b/sapi/apache/php_apache.c deleted file mode 100644 index 2ca5cc10a5..0000000000 --- a/sapi/apache/php_apache.c +++ /dev/null @@ -1,607 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> | - | Stig Sæther Bakken <ssb@php.net> | - | David Sklar <sklar@student.net> | - +----------------------------------------------------------------------+ - */ -/* $Id$ */ - -#include "php_apache_http.h" - -#if defined(PHP_WIN32) || defined(NETWARE) -#include "zend.h" -#include "ap_compat.h" -#endif - -#ifdef ZTS -int php_apache_info_id; -#else -php_apache_info_struct php_apache_info; -#endif - -#define SECTION(name) PUTS("<h2>" name "</h2>\n") - -#ifndef PHP_WIN32 -extern module *top_module; -extern module **ap_loaded_modules; -#else -extern __declspec(dllimport) module *top_module; -extern __declspec(dllimport) module **ap_loaded_modules; -#endif - -PHP_FUNCTION(virtual); -PHP_FUNCTION(apache_request_headers); -PHP_FUNCTION(apache_response_headers); -PHP_FUNCTION(apachelog); -PHP_FUNCTION(apache_note); -PHP_FUNCTION(apache_lookup_uri); -PHP_FUNCTION(apache_child_terminate); -PHP_FUNCTION(apache_setenv); -PHP_FUNCTION(apache_get_version); -PHP_FUNCTION(apache_get_modules); -PHP_FUNCTION(apache_reset_timeout); - -PHP_MINFO_FUNCTION(apache); - -ZEND_BEGIN_ARG_INFO(arginfo_apache_child_terminate, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_apache_note, 0, 0, 1) - ZEND_ARG_INFO(0, note_name) - ZEND_ARG_INFO(0, note_value) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_apache_virtual, 0, 0, 1) - ZEND_ARG_INFO(0, filename) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_apache_request_headers, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_apache_response_headers, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_apache_setenv, 0, 0, 2) - ZEND_ARG_INFO(0, variable) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, walk_to_top) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_apache_lookup_uri, 0, 0, 1) - ZEND_ARG_INFO(0, uri) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_apache_get_version, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_apache_get_modules, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_apache_reset_timeout, 0) -ZEND_END_ARG_INFO() - - - -const zend_function_entry apache_functions[] = { - PHP_FE(virtual, arginfo_apache_virtual) - PHP_FE(apache_request_headers, arginfo_apache_request_headers) - PHP_FE(apache_note, arginfo_apache_note) - PHP_FE(apache_lookup_uri, arginfo_apache_lookup_uri) - PHP_FE(apache_child_terminate, arginfo_apache_child_terminate) - PHP_FE(apache_setenv, arginfo_apache_setenv) - PHP_FE(apache_response_headers, arginfo_apache_response_headers) - PHP_FE(apache_get_version, arginfo_apache_get_version) - PHP_FE(apache_get_modules, arginfo_apache_get_modules) - PHP_FE(apache_reset_timeout, arginfo_apache_reset_timeout) - PHP_FALIAS(getallheaders, apache_request_headers, arginfo_apache_request_headers) - {NULL, NULL, NULL} -}; - - -PHP_INI_BEGIN() - STD_PHP_INI_ENTRY("xbithack", "0", PHP_INI_ALL, OnUpdateLong, xbithack, php_apache_info_struct, php_apache_info) - STD_PHP_INI_ENTRY("engine", "1", PHP_INI_ALL, OnUpdateLong, engine, php_apache_info_struct, php_apache_info) - STD_PHP_INI_ENTRY("last_modified", "0", PHP_INI_ALL, OnUpdateLong, last_modified, php_apache_info_struct, php_apache_info) - STD_PHP_INI_ENTRY("child_terminate", "0", PHP_INI_ALL, OnUpdateLong, terminate_child, php_apache_info_struct, php_apache_info) -PHP_INI_END() - - - -static void php_apache_globals_ctor(php_apache_info_struct *apache_globals TSRMLS_DC) -{ - apache_globals->in_request = 0; -} - - -static PHP_MINIT_FUNCTION(apache) -{ -#ifdef ZTS - ts_allocate_id(&php_apache_info_id, sizeof(php_apache_info_struct), (ts_allocate_ctor) php_apache_globals_ctor, NULL); -#else - php_apache_globals_ctor(&php_apache_info TSRMLS_CC); -#endif - REGISTER_INI_ENTRIES(); - return SUCCESS; -} - - -static PHP_MSHUTDOWN_FUNCTION(apache) -{ - UNREGISTER_INI_ENTRIES(); - return SUCCESS; -} - -zend_module_entry apache_module_entry = { - STANDARD_MODULE_HEADER, - "apache", - apache_functions, - PHP_MINIT(apache), - PHP_MSHUTDOWN(apache), - NULL, - NULL, - PHP_MINFO(apache), - NO_VERSION_YET, - STANDARD_MODULE_PROPERTIES -}; - -/* {{{ PHP_MINFO_FUNCTION - */ -PHP_MINFO_FUNCTION(apache) -{ - char *apv = (char *) ap_get_server_version(); - module *modp = NULL; - char output_buf[128]; -#if !defined(WIN32) && !defined(WINNT) - char name[64]; - char modulenames[1024]; - char *p; -#endif - server_rec *serv; - extern char server_root[MAX_STRING_LEN]; - extern uid_t user_id; - extern char *user_name; - extern gid_t group_id; - extern int max_requests_per_child; - - serv = ((request_rec *) SG(server_context))->server; - - - php_info_print_table_start(); - -#ifdef PHP_WIN32 - php_info_print_table_row(1, "Apache for Windows 95/NT"); - php_info_print_table_end(); - php_info_print_table_start(); -#elif defined(NETWARE) - php_info_print_table_row(1, "Apache for NetWare"); - php_info_print_table_end(); - php_info_print_table_start(); -#else - php_info_print_table_row(2, "APACHE_INCLUDE", PHP_APACHE_INCLUDE); - php_info_print_table_row(2, "APACHE_TARGET", PHP_APACHE_TARGET); -#endif - - if (apv && *apv) { - php_info_print_table_row(2, "Apache Version", apv); - } - -#ifdef APACHE_RELEASE - snprintf(output_buf, sizeof(output_buf), "%d", APACHE_RELEASE); - php_info_print_table_row(2, "Apache Release", output_buf); -#endif - snprintf(output_buf, sizeof(output_buf), "%d", MODULE_MAGIC_NUMBER); - php_info_print_table_row(2, "Apache API Version", output_buf); - snprintf(output_buf, sizeof(output_buf), "%s:%u", serv->server_hostname, serv->port); - php_info_print_table_row(2, "Hostname:Port", output_buf); -#if !defined(WIN32) && !defined(WINNT) - snprintf(output_buf, sizeof(output_buf), "%s(%d)/%d", user_name, (int)user_id, (int)group_id); - php_info_print_table_row(2, "User/Group", output_buf); - snprintf(output_buf, sizeof(output_buf), "Per Child: %d - Keep Alive: %s - Max Per Connection: %d", max_requests_per_child, serv->keep_alive ? "on":"off", serv->keep_alive_max); - php_info_print_table_row(2, "Max Requests", output_buf); -#endif - snprintf(output_buf, sizeof(output_buf), "Connection: %d - Keep-Alive: %d", serv->timeout, serv->keep_alive_timeout); - php_info_print_table_row(2, "Timeouts", output_buf); -#if !defined(WIN32) && !defined(WINNT) -/* - This block seems to be working on NetWare; But it seems to be showing - all modules instead of just the loaded ones -*/ - php_info_print_table_row(2, "Server Root", server_root); - - strcpy(modulenames, ""); - for(modp = top_module; modp; modp = modp->next) { - strlcpy(name, modp->name, sizeof(name)); - if ((p = strrchr(name, '.'))) { - *p='\0'; /* Cut off ugly .c extensions on module names */ - } - strlcat(modulenames, name, sizeof(modulenames)); - if (modp->next) { - strlcat(modulenames, ", ", sizeof(modulenames)); - } - } - php_info_print_table_row(2, "Loaded Modules", modulenames); -#endif - - php_info_print_table_end(); - - DISPLAY_INI_ENTRIES(); - - { - register int i; - array_header *arr; - table_entry *elts; - request_rec *r; - - r = ((request_rec *) SG(server_context)); - arr = table_elts(r->subprocess_env); - elts = (table_entry *)arr->elts; - - SECTION("Apache Environment"); - php_info_print_table_start(); - php_info_print_table_header(2, "Variable", "Value"); - for (i=0; i < arr->nelts; i++) { - php_info_print_table_row(2, elts[i].key, elts[i].val); - } - php_info_print_table_end(); - } - - { - array_header *env_arr; - table_entry *env; - int i; - request_rec *r; - - r = ((request_rec *) SG(server_context)); - 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", r->the_request); - env_arr = table_elts(r->headers_in); - env = (table_entry *)env_arr->elts; - for (i = 0; i < env_arr->nelts; ++i) { - if (env[i].key) { - php_info_print_table_row(2, env[i].key, env[i].val); - } - } - php_info_print_table_colspan_header(2, "HTTP Response Headers"); - env_arr = table_elts(r->headers_out); - env = (table_entry *)env_arr->elts; - for(i = 0; i < env_arr->nelts; ++i) { - if (env[i].key) { - php_info_print_table_row(2, env[i].key, env[i].val); - } - } - php_info_print_table_end(); - } -} -/* }}} */ - -/* {{{ proto bool apache_child_terminate(void) - Terminate apache process after this request */ -PHP_FUNCTION(apache_child_terminate) -{ -#ifndef MULTITHREAD - if (AP(terminate_child)) { - ap_child_terminate( ((request_rec *)SG(server_context)) ); - RETURN_TRUE; - } else { /* tell them to get lost! */ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "This function is disabled"); - RETURN_FALSE; - } -#else - php_error_docref(NULL TSRMLS_CC, E_WARNING, "This function is not supported in this build"); - RETURN_FALSE; -#endif -} -/* }}} */ - -/* {{{ proto string apache_note(string note_name [, string note_value]) - Get and set Apache request notes */ -PHP_FUNCTION(apache_note) -{ - char *note_name, *note_val = NULL; - int note_name_len, note_val_len; - char *old_val; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", ¬e_name, ¬e_name_len, ¬e_val, ¬e_val_len) == FAILURE) { - return; - } - - old_val = (char *) table_get(((request_rec *)SG(server_context))->notes, note_name); - - if (note_val) { - table_set(((request_rec *)SG(server_context))->notes, note_name, note_val); - } - - if (old_val) { - RETURN_STRING(old_val, 1); - } - - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto bool virtual(string filename) - Perform an Apache sub-request */ -/* This function is equivalent to <!--#include virtual...--> - * in mod_include. It does an Apache sub-request. It is useful - * for including CGI scripts or .shtml files, or anything else - * that you'd parse through Apache (for .phtml files, you'd probably - * want to use <?Include>. This only works when PHP is compiled - * as an Apache module, since it uses the Apache API for doing - * sub requests. - */ -PHP_FUNCTION(virtual) -{ - char *filename; - int filename_len; - request_rec *rr = NULL; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) { - return; - } - - if (!(rr = sub_req_lookup_uri (filename, ((request_rec *) SG(server_context))))) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - URI lookup failed", filename); - if (rr) - destroy_sub_req (rr); - RETURN_FALSE; - } - - if (rr->status != 200) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - error finding URI", filename); - if (rr) - destroy_sub_req (rr); - RETURN_FALSE; - } - - php_output_end_all(TSRMLS_C); - php_header(TSRMLS_C); - - if (run_sub_req(rr)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - request execution failed", filename); - if (rr) - destroy_sub_req (rr); - RETURN_FALSE; - } - - if (rr) - destroy_sub_req (rr); - - RETURN_TRUE; -} -/* }}} */ - -/* {{{ proto array getallheaders(void) - Alias for apache_request_headers() */ -/* }}} */ - -/* {{{ proto array apache_request_headers(void) - Fetch all HTTP request headers */ -PHP_FUNCTION(apache_request_headers) -{ - array_header *env_arr; - table_entry *tenv; - int i; - - array_init(return_value); - env_arr = table_elts(((request_rec *) SG(server_context))->headers_in); - tenv = (table_entry *)env_arr->elts; - for (i = 0; i < env_arr->nelts; ++i) { - if (!tenv[i].key) { - continue; - } - if (add_assoc_string(return_value, tenv[i].key, (tenv[i].val==NULL) ? "" : tenv[i].val, 1)==FAILURE) { - RETURN_FALSE; - } - } -} -/* }}} */ - -/* {{{ proto array apache_response_headers(void) - Fetch all HTTP response headers */ -PHP_FUNCTION(apache_response_headers) -{ - array_header *env_arr; - table_entry *tenv; - int i; - - array_init(return_value); - env_arr = table_elts(((request_rec *) SG(server_context))->headers_out); - tenv = (table_entry *)env_arr->elts; - for (i = 0; i < env_arr->nelts; ++i) { - if (!tenv[i].key) continue; - if (add_assoc_string(return_value, tenv[i].key, (tenv[i].val==NULL) ? "" : tenv[i].val, 1)==FAILURE) { - RETURN_FALSE; - } - } -} -/* }}} */ - -/* {{{ proto bool apache_setenv(string variable, string value [, bool walk_to_top]) - Set an Apache subprocess_env variable */ -PHP_FUNCTION(apache_setenv) -{ - int var_len, val_len; - zend_bool top=0; - char *var = NULL, *val = NULL; - request_rec *r = (request_rec *) SG(server_context); - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &var, &var_len, &val, &val_len, &top) == FAILURE) { - return; - } - - while(top) { - if(r->prev) r = r->prev; - else break; - } - - ap_table_setn(r->subprocess_env, ap_pstrndup(r->pool, var, var_len), ap_pstrndup(r->pool, val, val_len)); - RETURN_TRUE; -} -/* }}} */ - -/* {{{ proto object apache_lookup_uri(string URI) - Perform a partial request of the given URI to obtain information about it */ -PHP_FUNCTION(apache_lookup_uri) -{ - char *filename; - int filename_len; - request_rec *rr=NULL; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { - return; - } - - if (!(rr = sub_req_lookup_uri(filename, ((request_rec *) SG(server_context))))) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "URI lookup failed '%s'", filename); - RETURN_FALSE; - } - - object_init(return_value); - add_property_long(return_value,"status", rr->status); - - if (rr->the_request) { - add_property_string(return_value,"the_request", rr->the_request, 1); - } - if (rr->status_line) { - add_property_string(return_value,"status_line", (char *)rr->status_line, 1); - } - if (rr->method) { - add_property_string(return_value,"method", (char *)rr->method, 1); - } - if (rr->content_type) { - add_property_string(return_value,"content_type", (char *)rr->content_type, 1); - } - if (rr->handler) { - add_property_string(return_value,"handler", (char *)rr->handler, 1); - } - if (rr->uri) { - add_property_string(return_value,"uri", rr->uri, 1); - } - if (rr->filename) { - add_property_string(return_value,"filename", rr->filename, 1); - } - if (rr->path_info) { - add_property_string(return_value,"path_info", rr->path_info, 1); - } - if (rr->args) { - add_property_string(return_value,"args", rr->args, 1); - } - if (rr->boundary) { - add_property_string(return_value,"boundary", rr->boundary, 1); - } - - add_property_long(return_value,"no_cache", rr->no_cache); - add_property_long(return_value,"no_local_copy", rr->no_local_copy); - add_property_long(return_value,"allowed", rr->allowed); - add_property_long(return_value,"sent_bodyct", rr->sent_bodyct); - add_property_long(return_value,"bytes_sent", rr->bytes_sent); - add_property_long(return_value,"byterange", rr->byterange); - add_property_long(return_value,"clength", rr->clength); - -#if MODULE_MAGIC_NUMBER >= 19980324 - if (rr->unparsed_uri) { - add_property_string(return_value,"unparsed_uri", rr->unparsed_uri, 1); - } - if(rr->mtime) { - add_property_long(return_value,"mtime", rr->mtime); - } -#endif - if(rr->request_time) { - add_property_long(return_value,"request_time", rr->request_time); - } - - destroy_sub_req(rr); -} -/* }}} */ - - -#if 0 -/* -This function is most likely a bad idea. Just playing with it for now. -*/ -PHP_FUNCTION(apache_exec_uri) -{ - char *filename; - int filename_len; - request_rec *rr=NULL; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { - return; - } - - if(!(rr = ap_sub_req_lookup_uri(filename, ((request_rec *) SG(server_context))))) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "URI lookup failed", filename); - RETURN_FALSE; - } - - RETVAL_LONG(ap_run_sub_req(rr)); - ap_destroy_sub_req(rr); -} -#endif - -/* {{{ proto string apache_get_version(void) - Fetch Apache version */ -PHP_FUNCTION(apache_get_version) -{ - char *apv = (char *) ap_get_server_version(); - - if (apv && *apv) { - RETURN_STRING(apv, 1); - } - - 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); - } - } -} -/* }}} */ - -/* {{{ proto bool apache_reset_timeout(void) - Reset the Apache write timer */ -PHP_FUNCTION(apache_reset_timeout) -{ - ap_reset_timeout((request_rec *)SG(server_context)); - RETURN_TRUE; -} -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/sapi/apache/php_apache_http.h b/sapi/apache/php_apache_http.h deleted file mode 100644 index 9de9fc1fb9..0000000000 --- a/sapi/apache/php_apache_http.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> | - | Stig Sæther Bakken <ssb@php.net> | - | David Sklar <sklar@student.net> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#define NO_REGEX_EXTRA_H - -#ifdef WIN32 -#include <stddef.h> -#endif - -#ifdef NETWARE -#include <netinet/in.h> -#endif - -#include "zend.h" -#include "ext/ereg/php_regex.h" -#include "php_compat.h" - -#ifdef HAVE_OPENSSL_EXT -/* zlib typedefs free_func which causes problems if the SSL includes happen - * after zlib.h is included */ -# include <openssl/ssl.h> -#endif - -#ifdef regex_t -#undef regex_t -#endif - -#include "httpd.h" -#include "http_config.h" - -#if MODULE_MAGIC_NUMBER > 19980712 -# include "ap_compat.h" -#else -# if MODULE_MAGIC_NUMBER > 19980324 -# include "compat.h" -# endif -#endif - -#include "http_core.h" -#include "http_main.h" -#include "http_protocol.h" -#include "http_request.h" -#include "http_log.h" -#include "util_script.h" - -#include "php_variables.h" -#include "php_main.h" -#include "php_ini.h" -#include "ext/standard/php_standard.h" - -#include "mod_php5.h" diff --git a/sapi/apache/sapi_apache.c b/sapi/apache/sapi_apache.c deleted file mode 100644 index c869bd28e4..0000000000 --- a/sapi/apache/sapi_apache.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Rasmus Lerdorf <rasmus@php.net> | - | (with helpful hints from Dean Gaudet <dgaudet@arctic.org> | - | PHP 4.0 patches by: | - | Zeev Suraski <zeev@zend.com> | - | Stig Bakken <ssb@php.net> | - +----------------------------------------------------------------------+ - */ -/* $Id$ */ - -#include "php_apache_http.h" - -/* {{{ apache_php_module_main - */ -int apache_php_module_main(request_rec *r, int display_source_mode TSRMLS_DC) -{ - int retval = OK; - zend_file_handle file_handle; - - if (php_request_startup(TSRMLS_C) == FAILURE) { - return FAILURE; - } - /* sending a file handle to another dll is not working - so let zend open it. */ - - if (display_source_mode) { - zend_syntax_highlighter_ini syntax_highlighter_ini; - - php_get_highlight_struct(&syntax_highlighter_ini); - if (highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini TSRMLS_CC) != SUCCESS) { - retval = NOT_FOUND; - } - } else { - file_handle.type = ZEND_HANDLE_FILENAME; - file_handle.handle.fd = 0; - file_handle.filename = SG(request_info).path_translated; - file_handle.opened_path = NULL; - file_handle.free_filename = 0; - - (void) php_execute_script(&file_handle TSRMLS_CC); - } - - AP(in_request) = 0; - - zend_try { - php_request_shutdown(NULL); - } zend_end_try(); - - return retval; -} -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/sapi/apache2filter/CREDITS b/sapi/apache2filter/CREDITS deleted file mode 100644 index c298a9bf6a..0000000000 --- a/sapi/apache2filter/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -Apache 2.0 Filter -Sascha Schumann, Aaron Bannert diff --git a/sapi/apache2filter/EXPERIMENTAL b/sapi/apache2filter/EXPERIMENTAL deleted file mode 100644 index 293159a693..0000000000 --- a/sapi/apache2filter/EXPERIMENTAL +++ /dev/null @@ -1,5 +0,0 @@ -this module is experimental, -its functions may change their names -or move to extension all together -so do not rely to much on them -you have been warned! diff --git a/sapi/apache2filter/README b/sapi/apache2filter/README deleted file mode 100644 index bd6eb17066..0000000000 --- a/sapi/apache2filter/README +++ /dev/null @@ -1,71 +0,0 @@ -WHAT IS THIS? - - This module exploits the layered I/O support in Apache 2.0. - -HOW DOES IT WORK? - - In Apache 2.0, you have handlers which generate content (like - reading a script from disk). The content goes then through - a chain of filters. PHP can be such a filter, so that it processes - your script and hands the output to the next filter (which will - usually cause a write to the network). - -DOES IT WORK? - - It is experimental as interfaces in Apache 2.0 might change in the - future. - -HOW TO INSTALL - - This SAPI module is known to work with Apache 2.0.40. - - $ cd apache-2.x - $ cd src - $ ./configure --enable-so - $ make install - - For testing purposes, you might want to use --with-mpm=prefork. - (Albeit PHP also works with threaded MPMs.) - - Configure PHP 4: - - $ cd php-4.x - $ ./configure --with-apxs2=/path/to/apache-2.0/bin/apxs - $ make install - - At the end of conf/httpd.conf, add: - - AddType application/x-httpd-php .php - - If you would like to enable source code highlighting functionality add: - - AddType application/x-httpd-php-source .phps - - That's it. Now start bin/httpd. - -HOW TO CONFIGURE - - The Apache 2.0 PHP module supports a new configuration directive that - allows an admin to override the php.ini search path. For example, - place your php.ini file in Apache's ServerRoot/conf directory and - add this to your httpd.conf file: - - PHPINIDir "conf" - -DEBUGGING APACHE AND PHP - - To debug Apache, we recommend: - - 1. Use the Prefork MPM (Apache 1.3-like process model) by - configuring Apache with '--with-mpm=prefork'. - 2. Start httpd using -DONE_PROCESS (e.g. (gdb) r -DONE_PROCESS). - - If you want to debug a part of the PHP startup procedure, set a - breakpoint on 'load_module'. Step through it until apr_dso_load() is - done. Then you can set a breakpoint on any PHP-related symbol. - -TODO - - PHP functions like apache_sub_req (see php_functions.c) - Protocol handlers - Passing script data to engine without temporary file diff --git a/sapi/apache2filter/apache_config.c b/sapi/apache2filter/apache_config.c deleted file mode 100644 index a44e7d42a7..0000000000 --- a/sapi/apache2filter/apache_config.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 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> | - +----------------------------------------------------------------------+ - */ - -/* $Id$ */ - -#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS - -#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; - 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_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, *n = NULL; - php_dir_entry *pe; - php_dir_entry *data; - char *str; - uint str_len; - ulong num_index; - - n = create_php_config(p, "merge_php_config"); - zend_hash_copy(&n->config, &e->config, NULL, NULL, sizeof(php_dir_entry)); - - phpapdebug((stderr, "Merge dir (%p)+(%p)=(%p)\n", base_conf, new_conf, n)); - 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(&n->config, str, str_len, (void **) &pe) == SUCCESS) { - if (pe->status >= data->status) continue; - } - zend_hash_update(&n->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 n; -} - -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, data->htaccess?PHP_INI_STAGE_HTACCESS:PHP_INI_STAGE_ACTIVATE) == 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 - */ diff --git a/sapi/apache2filter/config.m4 b/sapi/apache2filter/config.m4 deleted file mode 100644 index b6524fd874..0000000000 --- a/sapi/apache2filter/config.m4 +++ /dev/null @@ -1,139 +0,0 @@ -dnl -dnl $Id$ -dnl - -PHP_ARG_WITH(apxs2filter,, -[ --with-apxs2filter[=FILE] - EXPERIMENTAL: Build shared Apache 2.0 Filter module. FILE is the optional - pathname to the Apache apxs tool [apxs]], no, no) - -AC_MSG_CHECKING([for Apache 2.0 filter-module support via DSO through APXS]) - -if test "$PHP_APXS2FILTER" != "no"; then - if test "$PHP_APXS2FILTER" = "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_APXS2FILTER, 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-apxs2filter=/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` - - # 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" - - # 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 appropriate switch --with-apxs (without the 2)]) - elif test "$APACHE_VERSION" -lt 2000040; then - AC_MSG_ERROR([Please note that Apache version >= 2.0.40 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 php5" - 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 php5" - fi - - case $host_alias in - *aix*) - EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-brtl -Wl,-bI:$APXS_LIBEXECDIR/httpd.exp" - PHP_SELECT_SAPI(apache2filter, shared, 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, - 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. - 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(apache2filter, bundle, sapi_apache2.c apache_config.c php_functions.c, $APACHE_CFLAGS) - SAPI_SHARED=libs/libphp5.so - INSTALL_IT="$INSTALL_IT $SAPI_SHARED" - ;; - *beos*) - if test -f _APP_; then `rm _APP_`; fi - `ln -s $APXS_BINDIR/httpd _APP_` - EXTRA_LIBS="$EXTRA_LIBS _APP_" - PHP_SELECT_SAPI(apache2filter, shared, sapi_apache2.c apache_config.c php_functions.c, $APACHE_CFLAGS) - INSTALL_IT="$INSTALL_IT $SAPI_LIBTOOL" - ;; - *) - PHP_SELECT_SAPI(apache2filter, shared, 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 | 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 - -dnl ## Local Variables: -dnl ## tab-width: 4 -dnl ## End: diff --git a/sapi/apache2filter/config.w32 b/sapi/apache2filter/config.w32 deleted file mode 100755 index 361d031074..0000000000 --- a/sapi/apache2filter/config.w32 +++ /dev/null @@ -1,39 +0,0 @@ -// vim:ft=javascript -// $Id$ - -ARG_ENABLE('apache2filter', 'Build Apache 2.x filter', 'no'); - -if (PHP_APACHE2FILTER != "no") { - if (PHP_ZTS == "no") { - WARNING("Apache2 module requires an --enable-zts build of PHP on windows"); - } else if (CHECK_HEADER_ADD_INCLUDE("httpd.h", "CFLAGS_APACHE2FILTER", PHP_PHP_BUILD + "\\include\\apache2") && - CHECK_LIB("libhttpd.lib", "apache2filter", PHP_PHP_BUILD + "\\lib\\apache2") && - CHECK_LIB("libapr.lib", "apache2filter", PHP_PHP_BUILD + "\\lib\\apache2") && - CHECK_LIB("libaprutil.lib", "apache2filter", PHP_PHP_BUILD + "\\lib\\apache2") - ) { - SAPI('apache2filter', 'sapi_apache2.c apache_config.c php_functions.c', - 'php' + PHP_VERSION + 'apache2_filter.dll', - '/D PHP_APACHE2_EXPORTS /I win32'); - } else { - WARNING("Could not find apache2 filter libraries/headers"); - } -} - -ARG_ENABLE('apache2-2filter', 'Build Apache 2.2.x filter', 'no'); - -if (PHP_APACHE2_2FILTER != "no") { - if (PHP_ZTS == "no") { - WARNING("Apache2 module requires an --enable-zts build of PHP on windows"); - } else if (CHECK_HEADER_ADD_INCLUDE("httpd.h", "CFLAGS_APACHE2_2FILTER", PHP_PHP_BUILD + "\\include\\apache2_2") && - CHECK_LIB("libhttpd.lib", "apache2_2filter", PHP_PHP_BUILD + "\\lib\\apache2_2") && - CHECK_LIB("libapr-1.lib", "apache2_2filter", PHP_PHP_BUILD + "\\lib\\apache2_2") && - CHECK_LIB("libaprutil-1.lib", "apache2_2filter", PHP_PHP_BUILD + "\\lib\\apache2_2") - ) { - SAPI('apache2_2filter', 'sapi_apache2.c apache_config.c php_functions.c', - 'php' + PHP_VERSION + 'apache2_2_filter.dll', - '/D PHP_APACHE2_EXPORTS /I win32', - 'sapi\\apache2_2filter'); - } else { - WARNING("Could not find apache2.2 filter libraries/headers"); - } -} diff --git a/sapi/apache2filter/php.sym b/sapi/apache2filter/php.sym deleted file mode 100644 index 9ad0f0a0ad..0000000000 --- a/sapi/apache2filter/php.sym +++ /dev/null @@ -1 +0,0 @@ -php5_module diff --git a/sapi/apache2filter/php_apache.h b/sapi/apache2filter/php_apache.h deleted file mode 100644 index a7d88a853a..0000000000 --- a/sapi/apache2filter/php_apache.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 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> | - +----------------------------------------------------------------------+ - */ - -/* $Id$ */ - -#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 php5_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; - ap_filter_t *f; /* downstream output filters after the PHP filter. */ - /* stat structure of the current file */ - struct stat finfo; - /* Set-aside request body bucket brigade */ - apr_bucket_brigade *post_data; - /* Whether or not we've processed PHP in the output filters yet. */ - int request_processed; -} php_struct; - -typedef struct _php_apr_bucket_brigade { - apr_bucket_brigade *bb; -} php_apr_bucket_brigade; - -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[]; - -static size_t php_apache_read_stream(void *, char *, size_t TSRMLS_DC); -static size_t php_apache_fsizer_stream(void * TSRMLS_DC); - -#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() }} - -/* fix for gcc4 visibility patch */ -#ifndef PHP_WIN32 -# undef AP_MODULE_DECLARE_DATA -# define AP_MODULE_DECLARE_DATA PHPAPI -#endif - -#endif /* PHP_APACHE_H */ diff --git a/sapi/apache2filter/php_functions.c b/sapi/apache2filter/php_functions.c deleted file mode 100644 index 3e8d8336e0..0000000000 --- a/sapi/apache2filter/php_functions.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 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> | - +----------------------------------------------------------------------+ - */ - -/* $Id$ */ - - -#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS - -#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->f->r, ctx->f->next); -} - -/* {{{ proto bool virtual(string uri) - Perform an apache sub-request */ -PHP_FUNCTION(virtual) -{ - char *filename; - int filename_len; - request_rec *rr; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) { - return; - } - - if (!(rr = php_apache_lookup_uri(filename TSRMLS_CC))) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - URI lookup failed", 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", 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", filename); - ap_destroy_sub_req(rr); - RETURN_FALSE; -} -/* }}} */ - -#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, 1) - -PHP_FUNCTION(apache_lookup_uri) -{ - request_rec *rr; - char *filename; - int filename_len; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) { - return; - } - - if (!(rr = php_apache_lookup_uri(filename TSRMLS_CC))) { - php_error_docref(NULL TSRMLS_CC, 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 TSRMLS_CC, E_WARNING, "Unable to include '%s' - error finding URI", 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->f->r->headers_in); - - APR_ARRAY_FOREACH_OPEN(arr, key, val) - if (!val) val = ""; - 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->f->r->headers_out); - - APR_ARRAY_FOREACH_OPEN(arr, key, val) - if (!val) val = ""; - 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; - char *note_name, *note_val = NULL; - int note_name_len, note_val_len; - char *old_note_val=NULL; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", ¬e_name, ¬e_name_len, ¬e_val, ¬e_val_len) == FAILURE) { - return; - } - - 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, 1); - } - - RETURN_FALSE; -} -/* }}} */ - - -/* {{{ proto bool apache_setenv(string variable, string value [, bool walk_to_top]) - Set an Apache subprocess_env variable */ -PHP_FUNCTION(apache_setenv) -{ - php_struct *ctx; - char *variable=NULL, *string_val=NULL; - int variable_len, string_val_len; - zend_bool walk_to_top = 0; - int arg_count = ZEND_NUM_ARGS(); - - if (zend_parse_parameters(arg_count TSRMLS_CC, "ss|b", &variable, &variable_len, &string_val, &string_val_len, &walk_to_top) == FAILURE) { - return; - } - - ctx = SG(server_context); - - if (arg_count == 3 && walk_to_top) { - while(ctx->f->r->prev) { - ctx->f->r = ctx->f->r->prev; - } - } - - apr_table_set(ctx->r->subprocess_env, variable, string_val); - - RETURN_TRUE; -} -/* }}} */ - -/* {{{ proto bool apache_getenv(string variable [, bool walk_to_top]) - Get an Apache subprocess_env variable */ -PHP_FUNCTION(apache_getenv) -{ - php_struct *ctx; - char *variable=NULL; - int variable_len; - zend_bool walk_to_top = 0; - int arg_count = ZEND_NUM_ARGS(); - char *env_val=NULL; - - if (zend_parse_parameters(arg_count TSRMLS_CC, "s|b", &variable, &variable_len, &walk_to_top) == FAILURE) { - return; - } - - ctx = SG(server_context); - - if (arg_count == 2 && walk_to_top) { - while(ctx->f->r->prev) { - ctx->f->r = ctx->f->r->prev; - } - } - - env_val = (char*) apr_table_get(ctx->r->subprocess_env, variable); - if (env_val != NULL) { - RETURN_STRING(env_val, 1); - } - - 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 -} - -/* {{{ 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(); -} - -/* {{{ arginfo */ -ZEND_BEGIN_ARG_INFO_EX(arginfo_apache2filter_lookup_uri, 0, 0, 1) - ZEND_ARG_INFO(0, filename) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_apache2filter_virtual, 0, 0, 1) - ZEND_ARG_INFO(0, uri) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_apache2filter_getallheaders, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_apache2filter_response_headers, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_apache2filter_note, 0, 0, 1) - ZEND_ARG_INFO(0, note_name) - ZEND_ARG_INFO(0, note_value) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_apache2filter_setenv, 0, 0, 2) - ZEND_ARG_INFO(0, variable) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, walk_to_top) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_apache2filter_getenv, 0, 0, 1) - ZEND_ARG_INFO(0, variable) - ZEND_ARG_INFO(0, walk_to_top) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_apache2filter_get_version, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_apache2filter_get_modules, 0) -ZEND_END_ARG_INFO() -/* }}} */ - -static const zend_function_entry apache_functions[] = { - PHP_FE(apache_lookup_uri, arginfo_apache2filter_lookup_uri) - PHP_FE(virtual, arginfo_apache2filter_virtual) - PHP_FE(apache_request_headers, arginfo_apache2filter_getallheaders) - PHP_FE(apache_response_headers, arginfo_apache2filter_response_headers) - PHP_FE(apache_setenv, arginfo_apache2filter_setenv) - PHP_FE(apache_getenv, arginfo_apache2filter_getenv) - PHP_FE(apache_note, arginfo_apache2filter_note) - PHP_FE(apache_get_version, arginfo_apache2filter_get_version) - PHP_FE(apache_get_modules, arginfo_apache2filter_get_modules) - PHP_FALIAS(getallheaders, apache_request_headers, arginfo_apache2filter_getallheaders) - {NULL, NULL, NULL} -}; - -zend_module_entry php_apache_module = { - STANDARD_MODULE_HEADER, - "apache2filter", - 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 - */ diff --git a/sapi/apache2filter/sapi_apache2.c b/sapi/apache2filter/sapi_apache2.c deleted file mode 100644 index a8f043ef06..0000000000 --- a/sapi/apache2filter/sapi_apache2.c +++ /dev/null @@ -1,761 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 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 | - +----------------------------------------------------------------------+ - */ - -/* $Id$ */ - -#include <fcntl.h> - -#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS - -#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 "apr_buckets.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 and Netware 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 - -/* 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; - ap_filter_t *f; /* remaining output filters */ - php_struct *ctx; - - ctx = SG(server_context); - f = ctx->f; - - if (str_length == 0) return 0; - - ba = f->c->bucket_alloc; - bb = apr_brigade_create(ctx->r->pool, ba); - - b = apr_bucket_transient_create(str, str_length, ba); - APR_BRIGADE_INSERT_TAIL(bb, b); - - if (ap_pass_brigade(f->next, bb) != APR_SUCCESS || ctx->r->connection->aborted) { - 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 TSRMLS_DC) -{ - 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) { - sapi_free_header(sapi_header); - return 0; - } - ptr = val; - - *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 (!strcasecmp(sapi_header->header, "content-length")) - ap_set_content_length(ctx->r, strtol(val, (char **)NULL, 10)); - 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 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) -{ - apr_size_t len; - php_struct *ctx = SG(server_context); - apr_bucket_brigade *brigade; - apr_bucket *partition; - - brigade = ctx->post_data; - len = count_bytes; - - switch (apr_brigade_partition(ctx->post_data, count_bytes, &partition)) { - case APR_SUCCESS: - apr_brigade_flatten(ctx->post_data, buf, &len); - brigade = apr_brigade_split(ctx->post_data, partition); - apr_brigade_destroy(ctx->post_data); - ctx->post_data = brigade; - break; - case APR_INCOMPLETE: - apr_brigade_flatten(ctx->post_data, buf, &len); - apr_brigade_cleanup(ctx->post_data); - break; - } - - return len; -} -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_dev = ctx->r->finfo.device; - ctx->finfo.st_ino = ctx->r->finfo.inode; -#ifdef NETWARE - ctx->finfo.st_atime.tv_sec = apr_time_sec(ctx->r->finfo.atime); - ctx->finfo.st_mtime.tv_sec = apr_time_sec(ctx->r->finfo.mtime); - ctx->finfo.st_ctime.tv_sec = apr_time_sec(ctx->r->finfo.ctime); -#else - 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); -#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; - unsigned int 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 TSRMLS_CC)) { - php_register_variable_safe(key, val, new_val_len, track_vars_array TSRMLS_CC); - } - APR_ARRAY_FOREACH_CLOSE() - - php_register_variable("PHP_SELF", ctx->r->uri, track_vars_array TSRMLS_CC); - if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &ctx->r->uri, strlen(ctx->r->uri), &new_val_len TSRMLS_CC)) { - php_register_variable_safe("PHP_SELF", ctx->r->uri, new_val_len, track_vars_array TSRMLS_CC); - } -} - -static void -php_apache_sapi_flush(void *server_context) -{ - php_struct *ctx; - apr_bucket_brigade *bb; - apr_bucket_alloc_t *ba; - apr_bucket *b; - ap_filter_t *f; /* output filters */ - TSRMLS_FETCH(); - - ctx = server_context; - - /* If we haven't registered a server_context yet, - * then don't bother flushing. */ - if (!server_context) - return; - - sapi_send_headers(TSRMLS_C); - - ctx->r->status = SG(sapi_headers).http_response_code; - SG(headers_sent) = 1; - - f = ctx->f; - - /* 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->r->connection->bucket_alloc; - bb = apr_brigade_create(ctx->r->pool, ba); - b = apr_bucket_flush_create(ba); - APR_BRIGADE_INSERT_TAIL(bb, b); - if (ap_pass_brigade(f->next, bb) != APR_SUCCESS || ctx->r->connection->aborted) { - php_handle_aborted_connection(); - } -} - -static void php_apache_sapi_log_message(char *msg TSRMLS_DC) -{ - php_struct *ctx; - - ctx = SG(server_context); - - 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_error(APLOG_MARK, APLOG_ERR, 0, ctx->r->server, "%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; -} - -static double php_apache_sapi_get_request_time(TSRMLS_D) -{ - php_struct *ctx = SG(server_context); - return ((double) apr_time_as_msec(ctx->r->request_time)) / 1000.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 = { - "apache2filter", - "Apache 2.0 Filter", - - 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, /* Get Request Time */ - NULL, /* Child terminate */ - - STANDARD_SAPI_MODULE_PROPERTIES -}; - -static int php_input_filter(ap_filter_t *f, apr_bucket_brigade *bb, - ap_input_mode_t mode, apr_read_type_e block, apr_off_t readbytes) -{ - php_struct *ctx; - apr_status_t rv; - TSRMLS_FETCH(); - - if (f->r->proxyreq) { - return ap_get_brigade(f->next, bb, mode, block, readbytes); - } - - ctx = SG(server_context); - if (ctx == NULL) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, - "php failed to get server context"); - return HTTP_INTERNAL_SERVER_ERROR; - } - - if ((rv = ap_get_brigade(f->next, bb, mode, block, readbytes)) != APR_SUCCESS) { - return rv; - } - - if (!ctx->post_data) { - ctx->post_data = apr_brigade_create(f->r->pool, f->c->bucket_alloc); - } - if ((rv = ap_save_brigade(f, &ctx->post_data, &bb, f->r->pool)) != APR_SUCCESS) { - return rv; - } - apr_brigade_cleanup(bb); - APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_eos_create(bb->bucket_alloc)); - - return APR_SUCCESS; -} - -static void php_apache_request_ctor(ap_filter_t *f, php_struct *ctx TSRMLS_DC) -{ - char *content_type; - char *content_length; - const char *auth; - - PG(during_request_startup) = 0; - SG(sapi_headers).http_response_code = !f->r->status ? HTTP_OK : f->r->status; - SG(request_info).content_type = apr_table_get(f->r->headers_in, "Content-Type"); -#undef safe_strdup -#define safe_strdup(x) ((x)?strdup((x)):NULL) - SG(request_info).query_string = safe_strdup(f->r->args); - SG(request_info).request_method = f->r->method; - SG(request_info).proto_num = f->r->proto_num; - SG(request_info).request_uri = safe_strdup(f->r->uri); - SG(request_info).path_translated = safe_strdup(f->r->filename); - f->r->no_local_copy = 1; - content_type = sapi_get_default_content_type(TSRMLS_C); - f->r->content_type = apr_pstrdup(f->r->pool, content_type); - - efree(content_type); - - content_length = (char *) apr_table_get(f->r->headers_in, "Content-Length"); - SG(request_info).content_length = (content_length ? atol(content_length) : 0); - - apr_table_unset(f->r->headers_out, "Content-Length"); - apr_table_unset(f->r->headers_out, "Last-Modified"); - apr_table_unset(f->r->headers_out, "Expires"); - apr_table_unset(f->r->headers_out, "ETag"); - - auth = apr_table_get(f->r->headers_in, "Authorization"); - php_handle_auth_data(auth TSRMLS_CC); - - if (SG(request_info).auth_user == NULL && f->r->user) { - SG(request_info).auth_user = estrdup(f->r->user); - } - - ctx->r->user = apr_pstrdup(ctx->r->pool, SG(request_info).auth_user); - - php_request_startup(TSRMLS_C); -} - -static void php_apache_request_dtor(ap_filter_t *f TSRMLS_DC) -{ - php_apr_bucket_brigade *pbb = (php_apr_bucket_brigade *)f->ctx; - - php_request_shutdown(NULL); - - if (SG(request_info).query_string) { - free(SG(request_info).query_string); - } - if (SG(request_info).request_uri) { - free(SG(request_info).request_uri); - } - if (SG(request_info).path_translated) { - free(SG(request_info).path_translated); - } - - apr_brigade_destroy(pbb->bb); -} - -static int php_output_filter(ap_filter_t *f, apr_bucket_brigade *bb) -{ - php_struct *ctx; - void *conf = ap_get_module_config(f->r->per_dir_config, &php5_module); - char *p = get_php_config(conf, "engine", sizeof("engine")); - zend_file_handle zfd; - php_apr_bucket_brigade *pbb; - apr_bucket *b; - TSRMLS_FETCH(); - - if (f->r->proxyreq) { - zend_try { - zend_ini_deactivate(TSRMLS_C); - } zend_end_try(); - return ap_pass_brigade(f->next, bb); - } - - /* handle situations where user turns the engine off */ - if (*p == '0') { - zend_try { - zend_ini_deactivate(TSRMLS_C); - } zend_end_try(); - return ap_pass_brigade(f->next, bb); - } - - if(f->ctx) { - pbb = (php_apr_bucket_brigade *)f->ctx; - } else { - pbb = f->ctx = apr_palloc(f->r->pool, sizeof(*pbb)); - pbb->bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc); - } - - if(ap_save_brigade(NULL, &pbb->bb, &bb, f->r->pool) != APR_SUCCESS) { - /* Bad */ - } - - apr_brigade_cleanup(bb); - - /* Check to see if the last bucket in this brigade, it not - * we have to wait until then. */ - if(!APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(pbb->bb))) { - return 0; - } - - /* Setup the CGI variables if this is the main request.. */ - if (f->r->main == NULL || - /* .. or if the sub-request envinronment differs from the main-request. */ - f->r->subprocess_env != f->r->main->subprocess_env - ) { - /* setup standard CGI variables */ - ap_add_common_vars(f->r); - ap_add_cgi_vars(f->r); - } - - ctx = SG(server_context); - if (ctx == NULL) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, - "php failed to get server context"); - zend_try { - zend_ini_deactivate(TSRMLS_C); - } zend_end_try(); - return HTTP_INTERNAL_SERVER_ERROR; - } - - ctx->f = f->next; /* save whatever filters are after us in the chain. */ - - if (ctx->request_processed) { - zend_try { - zend_ini_deactivate(TSRMLS_C); - } zend_end_try(); - return ap_pass_brigade(f->next, bb); - } - - apply_config(conf); - php_apache_request_ctor(f, ctx TSRMLS_CC); - - /* It'd be nice if we could highlight based of a zend_file_handle here.... - * ...but we can't. */ - - zfd.type = ZEND_HANDLE_STREAM; - - zfd.handle.stream.handle = pbb; - zfd.handle.stream.reader = php_apache_read_stream; - zfd.handle.stream.closer = NULL; - zfd.handle.stream.fsizer = php_apache_fsizer_stream; - zfd.handle.stream.isatty = 0; - - zfd.filename = f->r->filename; - zfd.opened_path = NULL; - zfd.free_filename = 0; - - php_execute_script(&zfd TSRMLS_CC); - - apr_table_set(ctx->r->notes, "mod_php_memory_usage", - apr_psprintf(ctx->r->pool, "%lu", (unsigned long) zend_memory_peak_usage(1 TSRMLS_CC))); - - php_apache_request_dtor(f TSRMLS_CC); - - if (!f->r->main) { - ctx->request_processed = 1; - } - - b = apr_bucket_eos_create(f->c->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(pbb->bb, b); - - /* Pass whatever is left on the brigade. */ - return ap_pass_brigade(f->next, pbb->bb); -} - -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 = "apache2filter_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, - 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 void php_insert_filter(request_rec *r) -{ - int content_type_len = strlen("application/x-httpd-php"); - - if (r->content_type && !strncmp(r->content_type, "application/x-httpd-php", content_type_len-1)) { - if (r->content_type[content_type_len] == '\0' || !strncmp(r->content_type+content_type_len, "-source", sizeof("-source"))) { - php_add_filter(r, r->output_filters); - php_add_filter(r, r->input_filters); - } - } -} - -static apr_status_t php_server_context_cleanup(void *data_) -{ - void **data = data_; - *data = NULL; - return APR_SUCCESS; -} - -static int php_post_read_request(request_rec *r) -{ - php_struct *ctx; - TSRMLS_FETCH(); - - /* 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); - - /* Save the entire request, so we can get the input or output - * filters if we need them. */ - ctx->r = r; - - return OK; -} - -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_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); -} - -static size_t php_apache_read_stream(void *handle, char *buf, size_t wantlen TSRMLS_DC) -{ - php_apr_bucket_brigade *pbb = (php_apr_bucket_brigade *)handle; - apr_bucket_brigade *rbb; - apr_size_t readlen; - apr_bucket *b = NULL; - - rbb = pbb->bb; - - if((apr_brigade_partition(pbb->bb, wantlen, &b) == APR_SUCCESS) && b){ - pbb->bb = apr_brigade_split(rbb, b); - } - - readlen = wantlen; - apr_brigade_flatten(rbb, buf, &readlen); - apr_brigade_cleanup(rbb); - - return readlen; -} - -static size_t php_apache_fsizer_stream(void *handle TSRMLS_DC) -{ - php_apr_bucket_brigade *pbb = (php_apr_bucket_brigade *)handle; - apr_off_t actual = 0; - - if (apr_brigade_length(pbb->bb, 1, &actual) == APR_SUCCESS) { - return actual; - } - - return 0; -} - -AP_MODULE_DECLARE_DATA module php5_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 - */ diff --git a/sapi/apache2handler/apache_config.c b/sapi/apache2handler/apache_config.c index 0b4866182f..38ff99aa7b 100644 --- a/sapi/apache2handler/apache_config.c +++ b/sapi/apache2handler/apache_config.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -60,17 +60,17 @@ static const char *real_value_hnd(cmd_parms *cmd, void *dummy, const char *name, 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_update(&d->config, (char *) name, strlen(name) + 1, &e, sizeof(e), NULL); + zend_hash_str_update_mem(&d->config, (char *) name, strlen(name), &e, sizeof(e)); return NULL; } @@ -117,11 +117,12 @@ static const char *php_apache_phpini_set(cmd_parms *cmd, void *mconfig, const ch return NULL; } -static zend_bool should_overwrite_per_dir_entry(HashTable *target_ht, php_dir_entry *new_per_dir_entry, zend_hash_key *hash_key, void *pData) +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 (zend_hash_find(target_ht, hash_key->arKey, hash_key->nKeyLength, (void **) &orig_per_dir_entry)==FAILURE) { + 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 */ } @@ -134,38 +135,25 @@ static zend_bool should_overwrite_per_dir_entry(HashTable *target_ht, php_dir_en } } +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; -#if STAS_0 - php_dir_entry *pe; - php_dir_entry *data; - char *str; - uint str_len; - ulong num_index; -#endif n = create_php_config(p, "merge_php_config"); /* copy old config */ - zend_hash_copy(&n->config, &d->config, NULL, NULL, sizeof(php_dir_entry)); + zend_hash_copy(&n->config, &d->config, config_entry_ctor); /* merge new config */ phpapdebug((stderr, "Merge dir (%p)+(%p)=(%p)\n", base_conf, new_conf, n)); - zend_hash_merge_ex(&n->config, &e->config, NULL, sizeof(php_dir_entry), (merge_checker_func_t) should_overwrite_per_dir_entry, NULL); -#if STAS_0 - 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(&n->config, str, str_len, (void **) &pe) == SUCCESS) { - if (pe->status >= data->status) continue; - } - phpapdebug((stderr, "ADDING/OVERWRITING %s (%d vs. %d)\n", str, data->status, pe?pe->status:-1)); - zend_hash_update(&n->config, str, str_len, data, sizeof(*data), NULL); - } -#endif + zend_hash_merge_ex(&n->config, &e->config, config_entry_ctor, should_overwrite_per_dir_entry, NULL); return n; } @@ -173,8 +161,8 @@ 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) { + + if ((pe = zend_hash_str_find_ptr(&d->config, name, name_len)) != NULL) { return pe->value; } @@ -184,21 +172,15 @@ char *get_php_config(void *conf, char *name, size_t name_len) void apply_config(void *dummy) { php_conf_rec *d = dummy; - char *str; - uint str_len; + zend_string *str; 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)) { - if (zend_hash_get_current_data(&d->config, (void **) &data) == SUCCESS) { - phpapdebug((stderr, "APPLYING (%s)(%s)\n", str, data->value)); - if (zend_alter_ini_entry(str, str_len, 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_STR_KEY_PTR(&d->config, str, data) { + phpapdebug((stderr, "APPLYING (%s)(%s)\n", 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[] = @@ -215,18 +197,23 @@ static apr_status_t destroy_php_config(void *data) { php_conf_rec *d = data; - phpapdebug((stderr, "Destroying config %p\n", 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, NULL, 1); + 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; } diff --git a/sapi/apache2handler/config.m4 b/sapi/apache2handler/config.m4 index 02f8a0b3ad..2e64b215e5 100644 --- a/sapi/apache2handler/config.m4 +++ b/sapi/apache2handler/config.m4 @@ -56,7 +56,7 @@ if test "$PHP_APXS2" != "no"; then esac done - APACHE_CFLAGS="$APACHE_CPPFLAGS -I$APXS_INCLUDEDIR $APR_CFLAGS $APU_CFLAGS" + APACHE_CFLAGS="$APACHE_CPPFLAGS -I$APXS_INCLUDEDIR $APR_CFLAGS $APU_CFLAGS -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1" # Test that we're trying to configure with apache 2.x PHP_AP_EXTRACT_VERSION($APXS_HTTPD) @@ -70,20 +70,20 @@ if test "$PHP_APXS2" != "no"; then if test -z `$APXS -q SYSCONFDIR`; then INSTALL_IT="\$(mkinstalldirs) '$APXS_LIBEXECDIR' && \ $APXS -S LIBEXECDIR='$APXS_LIBEXECDIR' \ - -i -n php5" + -i -n php7" 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 php5" + -i -a -n php7" fi case $host_alias in *aix*) EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-brtl -Wl,-bI:$APXS_LIBEXECDIR/httpd.exp" - PHP_SELECT_SAPI(apache2handler, shared, mod_php5.c sapi_apache2.c apache_config.c php_functions.c, $APACHE_CFLAGS) + PHP_SELECT_SAPI(apache2handler, shared, mod_php7.c sapi_apache2.c apache_config.c php_functions.c, $APACHE_CFLAGS) INSTALL_IT="$INSTALL_IT $SAPI_LIBTOOL" ;; *darwin*) @@ -99,19 +99,19 @@ if test "$PHP_APXS2" != "no"; then fi MH_BUNDLE_FLAGS="-bundle -bundle_loader $APXS_HTTPD $MH_BUNDLE_FLAGS" PHP_SUBST(MH_BUNDLE_FLAGS) - PHP_SELECT_SAPI(apache2handler, bundle, mod_php5.c sapi_apache2.c apache_config.c php_functions.c, $APACHE_CFLAGS) - SAPI_SHARED=libs/libphp5.so + PHP_SELECT_SAPI(apache2handler, bundle, mod_php7.c sapi_apache2.c apache_config.c php_functions.c, $APACHE_CFLAGS) + SAPI_SHARED=libs/libphp7.so INSTALL_IT="$INSTALL_IT $SAPI_SHARED" ;; *beos*) if test -f _APP_; then `rm _APP_`; fi `ln -s $APXS_BINDIR/httpd _APP_` EXTRA_LIBS="$EXTRA_LIBS _APP_" - PHP_SELECT_SAPI(apache2handler, shared, mod_php5.c sapi_apache2.c apache_config.c php_functions.c, $APACHE_CFLAGS) + PHP_SELECT_SAPI(apache2handler, shared, mod_php7.c sapi_apache2.c apache_config.c php_functions.c, $APACHE_CFLAGS) INSTALL_IT="$INSTALL_IT $SAPI_LIBTOOL" ;; *) - PHP_SELECT_SAPI(apache2handler, shared, mod_php5.c sapi_apache2.c apache_config.c php_functions.c, $APACHE_CFLAGS) + PHP_SELECT_SAPI(apache2handler, shared, mod_php7.c sapi_apache2.c apache_config.c php_functions.c, $APACHE_CFLAGS) INSTALL_IT="$INSTALL_IT $SAPI_LIBTOOL" ;; esac diff --git a/sapi/apache2handler/config.w32 b/sapi/apache2handler/config.w32 index a7547514d8..8ea1305d4f 100644 --- a/sapi/apache2handler/config.w32 +++ b/sapi/apache2handler/config.w32 @@ -11,9 +11,9 @@ if (PHP_APACHE2HANDLER != "no") { CHECK_LIB("libapr.lib", "apache2handler", PHP_PHP_BUILD + "\\lib\\apache2") && CHECK_LIB("libaprutil.lib", "apache2handler", PHP_PHP_BUILD + "\\lib\\apache2") ) { - SAPI('apache2handler', 'mod_php5.c sapi_apache2.c apache_config.c php_functions.c', + SAPI('apache2handler', 'mod_php7.c sapi_apache2.c apache_config.c php_functions.c', 'php' + PHP_VERSION + 'apache2.dll', - '/D PHP_APACHE2_EXPORTS /I win32'); + '/D PHP_APACHE2_EXPORTS /I win32 /DZEND_ENABLE_STATIC_TSRMLS_CACHE=1'); } else { WARNING("Could not find apache2 libraries/headers"); } @@ -29,9 +29,9 @@ if (PHP_APACHE2_2HANDLER != "no") { 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_php5.c sapi_apache2.c apache_config.c php_functions.c', + SAPI('apache2_2handler', 'mod_php7.c sapi_apache2.c apache_config.c php_functions.c', 'php' + PHP_VERSION + 'apache2_2.dll', - '/D PHP_APACHE2_EXPORTS /I win32', + '/D PHP_APACHE2_EXPORTS /I win32 /DZEND_ENABLE_STATIC_TSRMLS_CACHE=1', 'sapi\\apache2_2handler'); } else { WARNING("Could not find apache2.2 libraries/headers"); @@ -47,9 +47,9 @@ if (PHP_APACHE2_4HANDLER != "no") { 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_php5.c sapi_apache2.c apache_config.c php_functions.c', + SAPI('apache2_4handler', 'mod_php7.c sapi_apache2.c apache_config.c php_functions.c', 'php' + PHP_VERSION + 'apache2_4.dll', - '/D PHP_APACHE2_EXPORTS /I win32', + '/D PHP_APACHE2_EXPORTS /I win32 /DZEND_ENABLE_STATIC_TSRMLS_CACHE=1', 'sapi\\apache2handler'); } else { WARNING("Could not find apache 2.4 libraries/headers"); diff --git a/sapi/apache2handler/mod_php5.c b/sapi/apache2handler/mod_php7.c index 64c669762c..fd7185f856 100644 --- a/sapi/apache2handler/mod_php5.c +++ b/sapi/apache2handler/mod_php7.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -25,7 +25,7 @@ #include "php.h" #include "php_apache.h" -AP_MODULE_DECLARE_DATA module php5_module = { +AP_MODULE_DECLARE_DATA module php7_module = { STANDARD20_MODULE_STUFF, create_php_config, /* create per-directory config structure */ merge_php_config, /* merge per-directory config structures */ diff --git a/sapi/apache2handler/php.sym b/sapi/apache2handler/php.sym index 9ad0f0a0ad..1469b0314d 100644 --- a/sapi/apache2handler/php.sym +++ b/sapi/apache2handler/php.sym @@ -1 +1 @@ -php5_module +php7_module diff --git a/sapi/apache2handler/php5apache2.dsp b/sapi/apache2handler/php5apache2.dsp deleted file mode 100644 index 40cd58cb92..0000000000 --- a/sapi/apache2handler/php5apache2.dsp +++ /dev/null @@ -1,146 +0,0 @@ -# Microsoft Developer Studio Project File - Name="php5apache2" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=php5apache2 - 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 "php5apache2.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 "php5apache2.mak" CFG="php5apache2 - Win32 Debug_TS"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "php5apache2 - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "php5apache2 - Win32 Release_TS_inline" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "php5apache2 - 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)" == "php5apache2 - 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 "PHP_APACHE2_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" /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 php5ts.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)" == "php5apache2 - 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 "PHP_APACHE2_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" /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 php5ts.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/php5apache2.dll" /libpath:"..\..\Release_TS_inline" /libpath:"..\..\TSRM\Release_TS_inline" /libpath:"..\..\Zend\Release_TS_inline"
-
-!ELSEIF "$(CFG)" == "php5apache2 - 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 "PHP_APACHE2_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" /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 php5ts_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 "php5apache2 - Win32 Release_TS"
-# Name "php5apache2 - Win32 Release_TS_inline"
-# Name "php5apache2 - 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=.\mod_php5.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
diff --git a/sapi/apache2handler/php_apache.h b/sapi/apache2handler/php_apache.h index 54eb2565e8..c1c52f5697 100644 --- a/sapi/apache2handler/php_apache.h +++ b/sapi/apache2handler/php_apache.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -25,8 +25,11 @@ #include "http_config.h" #include "http_core.h" +#include "php.h" +#include "main/php_streams.h" + /* Declare this so we can get to it from outside the sapi_apache2.c file */ -extern module AP_MODULE_DECLARE_DATA php5_module; +extern module AP_MODULE_DECLARE_DATA php7_module; /* A way to specify the location of the php.ini dir in an apache directive */ extern char *apache2_php_ini_path_override; @@ -40,7 +43,7 @@ typedef struct php_struct { #if defined(NETWARE) && defined(CLIB_STAT_PATCH) struct stat_libc finfo; #else - struct stat finfo; + zend_stat_t finfo; #endif /* Whether or not we've processed PHP in the output filters yet. */ int request_processed; @@ -67,16 +70,17 @@ void php_ap2_register_hook(apr_pool_t *p); #define APR_ARRAY_FOREACH_CLOSE() }} typedef struct { - long engine; - long xbithack; - long last_modified; + 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) TSRMG(php_apache2_info_id, php_apache2_info_struct *, v) +#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) diff --git a/sapi/apache2handler/php_functions.c b/sapi/apache2handler/php_functions.c index 1969cd9248..9ba09da66e 100644 --- a/sapi/apache2handler/php_functions.c +++ b/sapi/apache2handler/php_functions.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -21,7 +21,7 @@ #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS #include "php.h" -#include "ext/standard/php_smart_str.h" +#include "zend_smart_str.h" #include "ext/standard/info.h" #include "ext/standard/head.h" #include "php_ini.h" @@ -56,10 +56,10 @@ php_apache2_info_struct php_apache2_info; #define SECTION(name) PUTS("<h2>" name "</h2>\n") -static request_rec *php_apache_lookup_uri(char *filename TSRMLS_DC) +static request_rec *php_apache_lookup_uri(char *filename) { php_struct *ctx = SG(server_context); - + if (!filename || !ctx || !ctx->r) { return NULL; } @@ -72,34 +72,34 @@ static request_rec *php_apache_lookup_uri(char *filename TSRMLS_DC) PHP_FUNCTION(virtual) { char *filename; - int filename_len; + size_t filename_len; request_rec *rr; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &filename, &filename_len) == FAILURE) { return; } - if (!(rr = php_apache_lookup_uri(filename TSRMLS_CC))) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - URI lookup failed", filename); + 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 TSRMLS_CC, E_WARNING, "Unable to include '%s' - error finding URI", filename); + 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(TSRMLS_C); - php_header(TSRMLS_C); + 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 TSRMLS_CC, E_WARNING, "Unable to include '%s' - request execution failed", filename); + php_error_docref(NULL, E_WARNING, "Unable to include '%s' - request execution failed", filename); ap_destroy_sub_req(rr); RETURN_FALSE; } @@ -113,23 +113,23 @@ PHP_FUNCTION(virtual) #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, 1) + if (rr->name) add_property_string(return_value, #name, (char *) rr->name) PHP_FUNCTION(apache_lookup_uri) { request_rec *rr; char *filename; - int filename_len; + size_t filename_len; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &filename, &filename_len) == FAILURE) { return; } - if (!(rr = php_apache_lookup_uri(filename TSRMLS_CC))) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - URI lookup failed", filename); + 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); @@ -162,8 +162,8 @@ PHP_FUNCTION(apache_lookup_uri) ap_destroy_sub_req(rr); return; } - - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - error finding URI", filename); + + php_error_docref(NULL, E_WARNING, "Unable to include '%s' - error finding URI", filename); ap_destroy_sub_req(rr); RETURN_FALSE; } @@ -181,13 +181,13 @@ PHP_FUNCTION(apache_request_headers) } 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, 1); + add_assoc_string(return_value, key, val); APR_ARRAY_FOREACH_CLOSE() } /* }}} */ @@ -205,13 +205,13 @@ PHP_FUNCTION(apache_response_headers) } 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, 1); + add_assoc_string(return_value, key, val); APR_ARRAY_FOREACH_CLOSE() } /* }}} */ @@ -222,10 +222,10 @@ PHP_FUNCTION(apache_note) { php_struct *ctx; char *note_name, *note_val = NULL; - int note_name_len, note_val_len; + size_t note_name_len, note_val_len; char *old_note_val=NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", ¬e_name, ¬e_name_len, ¬e_val, ¬e_val_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s", ¬e_name, ¬e_name_len, ¬e_val, ¬e_val_len) == FAILURE) { return; } @@ -238,7 +238,7 @@ PHP_FUNCTION(apache_note) } if (old_note_val) { - RETURN_STRING(old_note_val, 1); + RETURN_STRING(old_note_val); } RETURN_FALSE; @@ -254,12 +254,12 @@ PHP_FUNCTION(apache_setenv) { php_struct *ctx; char *variable=NULL, *string_val=NULL; - int variable_len, string_val_len; + 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 TSRMLS_CC, "ss|b", &variable, &variable_len, &string_val, &string_val_len, &walk_to_top) == FAILURE) { + if (zend_parse_parameters(arg_count, "ss|b", &variable, &variable_len, &string_val, &string_val_len, &walk_to_top) == FAILURE) { return; } @@ -288,14 +288,14 @@ PHP_FUNCTION(apache_setenv) PHP_FUNCTION(apache_getenv) { php_struct *ctx; - char *variable=NULL; - int variable_len; + 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 TSRMLS_CC, "s|b", &variable, &variable_len, &walk_to_top) == FAILURE) { + if (zend_parse_parameters(arg_count, "s|b", &variable, &variable_len, &walk_to_top) == FAILURE) { return; } @@ -313,7 +313,7 @@ PHP_FUNCTION(apache_getenv) env_val = (char*) apr_table_get(r->subprocess_env, variable); if (env_val != NULL) { - RETURN_STRING(env_val, 1); + RETURN_STRING(env_val); } RETURN_FALSE; @@ -336,7 +336,7 @@ PHP_FUNCTION(apache_get_version) char *apv = php_apache_get_version(); if (apv && *apv) { - RETURN_STRING(apv, 1); + RETURN_STRING(apv); } else { RETURN_FALSE; } @@ -349,15 +349,15 @@ 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); + add_next_index_stringl(return_value, s, (p - s)); } else { - add_next_index_string(return_value, s, 1); + add_next_index_string(return_value, s); } } } @@ -378,7 +378,7 @@ PHP_MINFO_FUNCTION(apache) 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, '.'))) { @@ -388,24 +388,28 @@ PHP_MINFO_FUNCTION(apache) } smart_str_appendc(&tmp1, ' '); } - if ((tmp1.len - 1) >= 0) { - tmp1.c[tmp1.len - 1] = '\0'; + 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); - + #if !defined(WIN32) && !defined(WINNT) && !defined(NETWARE) #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); @@ -420,25 +424,25 @@ PHP_MINFO_FUNCTION(apache) 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, + "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.c); + 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_start(); php_info_print_table_header(2, "Variable", "Value"); APR_ARRAY_FOREACH_OPEN(arr, key, val) if (!val) { @@ -446,14 +450,14 @@ PHP_MINFO_FUNCTION(apache) } php_info_print_table_row(2, key, val); APR_ARRAY_FOREACH_CLOSE() - - php_info_print_table_end(); - + + 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) { @@ -470,7 +474,7 @@ PHP_MINFO_FUNCTION(apache) } php_info_print_table_row(2, key, val); APR_ARRAY_FOREACH_CLOSE() - + php_info_print_table_end(); } } @@ -515,7 +519,7 @@ ZEND_END_ARG_INFO() static const zend_function_entry apache_functions[] = { PHP_FE(apache_lookup_uri, arginfo_apache2handler_lookup_uri) - PHP_FE(virtual, arginfo_apache2handler_virtual) + PHP_FE(virtual, arginfo_apache2handler_virtual) PHP_FE(apache_request_headers, arginfo_apache2handler_getallheaders) PHP_FE(apache_response_headers, arginfo_apache2handler_response_headers) PHP_FE(apache_setenv, arginfo_apache2handler_setenv) @@ -528,9 +532,9 @@ static const zend_function_entry apache_functions[] = { }; PHP_INI_BEGIN() - STD_PHP_INI_ENTRY("xbithack", "0", PHP_INI_ALL, OnUpdateLong, xbithack, php_apache2_info_struct, php_apache2_info) - STD_PHP_INI_ENTRY("engine", "1", PHP_INI_ALL, OnUpdateLong, engine, php_apache2_info_struct, php_apache2_info) - STD_PHP_INI_ENTRY("last_modified", "0", PHP_INI_ALL, OnUpdateLong, last_modified, php_apache2_info_struct, php_apache2_info) + STD_PHP_INI_ENTRY("xbithack", "0", PHP_INI_ALL, OnUpdateBool, xbithack, php_apache2_info_struct, php_apache2_info) + STD_PHP_INI_ENTRY("engine", "1", PHP_INI_ALL, OnUpdateBool, engine, php_apache2_info_struct, php_apache2_info) + STD_PHP_INI_ENTRY("last_modified", "0", PHP_INI_ALL, OnUpdateBool, last_modified, php_apache2_info_struct, php_apache2_info) PHP_INI_END() static PHP_MINIT_FUNCTION(apache) @@ -555,7 +559,7 @@ zend_module_entry php_apache_module = { PHP_MINIT(apache), PHP_MSHUTDOWN(apache), NULL, - NULL, + NULL, PHP_MINFO(apache), NULL, STANDARD_MODULE_PROPERTIES diff --git a/sapi/apache2handler/sapi_apache2.c b/sapi/apache2handler/sapi_apache2.c index 6fa2521c38..456b9719fa 100644 --- a/sapi/apache2handler/sapi_apache2.c +++ b/sapi/apache2handler/sapi_apache2.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -30,7 +30,7 @@ #include <fcntl.h> -#include "ext/standard/php_smart_str.h" +#include "zend_smart_str.h" #ifndef NETWARE #include "ext/standard/php_standard.h" #else @@ -53,12 +53,6 @@ #include "php_apache.h" -#ifdef PHP_WIN32 -# if _MSC_VER <= 1300 -# include "win32/php_strtoi64.h" -# endif -#endif - /* UnixWare and Netware 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.K @@ -67,13 +61,16 @@ #define PHP_MAGIC_TYPE "application/x-httpd-php" #define PHP_SOURCE_MAGIC_TYPE "application/x-httpd-php-source" -#define PHP_SCRIPT "php5-script" +#define PHP_SCRIPT "php7-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 int -php_apache_sapi_ub_write(const char *str, uint str_length TSRMLS_DC) +static size_t +php_apache_sapi_ub_write(const char *str, size_t str_length) { request_rec *r; php_struct *ctx; @@ -89,7 +86,7 @@ php_apache_sapi_ub_write(const char *str, uint str_length TSRMLS_DC) } static int -php_apache_sapi_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC) +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; @@ -151,7 +148,7 @@ php_apache_sapi_header_handler(sapi_header_struct *sapi_header, sapi_header_op_e } static int -php_apache_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) +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; @@ -171,7 +168,7 @@ php_apache_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) /* 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(TSRMLS_C); + 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); @@ -180,8 +177,8 @@ php_apache_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) return SAPI_HEADER_SENT_SUCCESSFULLY; } -static int -php_apache_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC) +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); @@ -212,13 +209,18 @@ php_apache_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC) return tlen; } -static struct stat* -php_apache_sapi_get_stat(TSRMLS_D) +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; #if defined(NETWARE) && defined(CLIB_STAT_PATCH) @@ -238,7 +240,7 @@ php_apache_sapi_get_stat(TSRMLS_D) } static char * -php_apache_sapi_read_cookies(TSRMLS_D) +php_apache_sapi_read_cookies(void) { php_struct *ctx = SG(server_context); const char *http_cookie; @@ -250,7 +252,7 @@ php_apache_sapi_read_cookies(TSRMLS_D) } static char * -php_apache_sapi_getenv(char *name, size_t name_len TSRMLS_DC) +php_apache_sapi_getenv(char *name, size_t name_len) { php_struct *ctx = SG(server_context); const char *env_var; @@ -265,24 +267,24 @@ php_apache_sapi_getenv(char *name, size_t name_len TSRMLS_DC) } static void -php_apache_sapi_register_variables(zval *track_vars_array TSRMLS_DC) +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; - int new_val_len; + 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), (unsigned int *)&new_val_len TSRMLS_CC)) { - php_register_variable_safe(key, val, new_val_len, track_vars_array TSRMLS_CC); + 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), (unsigned int *)&new_val_len TSRMLS_CC)) { - php_register_variable_safe("PHP_SELF", ctx->r->uri, new_val_len, track_vars_array TSRMLS_CC); + 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); } } @@ -291,7 +293,6 @@ php_apache_sapi_flush(void *server_context) { php_struct *ctx; request_rec *r; - TSRMLS_FETCH(); ctx = server_context; @@ -303,7 +304,7 @@ php_apache_sapi_flush(void *server_context) r = ctx->r; - sapi_send_headers(TSRMLS_C); + sapi_send_headers(); r->status = SG(sapi_headers).http_response_code; SG(headers_sent) = 1; @@ -313,7 +314,7 @@ php_apache_sapi_flush(void *server_context) } } -static void php_apache_sapi_log_message(char *msg TSRMLS_DC) +static void php_apache_sapi_log_message(char *msg) { php_struct *ctx; @@ -326,16 +327,16 @@ static void php_apache_sapi_log_message(char *msg TSRMLS_DC) } } -static void php_apache_sapi_log_message_ex(char *msg, request_rec *r TSRMLS_DC) +static void php_apache_sapi_log_message_ex(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 TSRMLS_CC); + php_apache_sapi_log_message(msg); } } -static double php_apache_sapi_get_request_time(TSRMLS_D) +static double php_apache_sapi_get_request_time(void) { php_struct *ctx = SG(server_context); return ((double) apr_time_as_msec(ctx->r->request_time)) / 1000.0; @@ -404,7 +405,6 @@ static apr_status_t php_apache_child_shutdown(void *tmp) static void php_apache_add_version(apr_pool_t *p) { - TSRMLS_FETCH(); if (PG(expose_php)) { ap_add_version_component(p, "PHP/" PHP_VERSION); } @@ -452,7 +452,14 @@ php_apache_server_startup(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp } #ifdef ZTS tsrm_startup(1, 1, 0, NULL); + (void)ts_resource(0); + ZEND_TSRMLS_CACHE_UPDATE(); #endif + +#ifdef ZEND_SIGNALS + zend_signal_startup(); +#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); @@ -468,7 +475,7 @@ static apr_status_t php_server_context_cleanup(void *data_) return APR_SUCCESS; } -static int php_apache_request_ctor(request_rec *r, php_struct *ctx TSRMLS_DC) +static int php_apache_request_ctor(request_rec *r, php_struct *ctx) { char *content_length; const char *auth; @@ -483,7 +490,11 @@ static int php_apache_request_ctor(request_rec *r, php_struct *ctx TSRMLS_DC) r->no_local_copy = 1; content_length = (char *) apr_table_get(r->headers_in, "Content-Length"); - SG(request_info).content_length = (content_length ? atol(content_length) : 0); + 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"); @@ -491,7 +502,7 @@ static int php_apache_request_ctor(request_rec *r, php_struct *ctx TSRMLS_DC) apr_table_unset(r->headers_out, "ETag"); auth = apr_table_get(r->headers_in, "Authorization"); - php_handle_auth_data(auth TSRMLS_CC); + php_handle_auth_data(auth); if (SG(request_info).auth_user == NULL && r->user) { SG(request_info).auth_user = estrdup(r->user); @@ -499,32 +510,28 @@ static int php_apache_request_ctor(request_rec *r, php_struct *ctx TSRMLS_DC) ctx->r->user = apr_pstrdup(ctx->r->pool, SG(request_info).auth_user); - return php_request_startup(TSRMLS_C); + return php_request_startup(); } -static void php_apache_request_dtor(request_rec *r TSRMLS_DC) +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 TSRMLS_DC) +static void php_apache_ini_dtor(request_rec *r, request_rec *p) { if (strcmp(r->protocol, "INCLUDED")) { - zend_try { zend_ini_deactivate(TSRMLS_C); } zend_end_try(); + zend_try { zend_ini_deactivate(); } zend_end_try(); } else { typedef struct { HashTable config; } php_conf_rec; - char *str; - uint str_len; - php_conf_rec *c = ap_get_module_config(r->per_dir_config, &php5_module); - - for (zend_hash_internal_pointer_reset(&c->config); - zend_hash_get_current_key_ex(&c->config, &str, &str_len, NULL, 0, NULL) == HASH_KEY_IS_STRING; - zend_hash_move_forward(&c->config) - ) { - zend_restore_ini_entry(str, str_len, ZEND_INI_STAGE_SHUTDOWN); - } + zend_string *str; + php_conf_rec *c = ap_get_module_config(r->per_dir_config, &php7_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; @@ -541,11 +548,15 @@ static int php_handler(request_rec *r) apr_bucket *bucket; apr_status_t rv; request_rec * volatile parent_req = NULL; - TSRMLS_FETCH(); +#ifdef ZTS + /* initial resource fetch */ + (void)ts_resource(0); + ZEND_TSRMLS_CACHE_UPDATE(); +#endif -#define PHPAP_INI_OFF php_apache_ini_dtor(r, parent_req TSRMLS_CC); +#define PHPAP_INI_OFF php_apache_ini_dtor(r, parent_req); - conf = ap_get_module_config(r->per_dir_config, &php5_module); + conf = ap_get_module_config(r->per_dir_config, &php7_module); /* apply_config() needs r in some cases, so allocate server_context early */ ctx = SG(server_context); @@ -588,12 +599,12 @@ normal: } if (r->finfo.filetype == 0) { - php_apache_sapi_log_message_ex("script '%s' not found or unable to stat", r TSRMLS_CC); + 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 TSRMLS_CC); + php_apache_sapi_log_message_ex("attempt to invoke directory '%s' as script", r); PHPAP_INI_OFF; return HTTP_FORBIDDEN; } @@ -615,7 +626,7 @@ zend_first_try { ctx = SG(server_context); ctx->brigade = brigade; - if (php_apache_request_ctor(r, ctx TSRMLS_CC)!=SUCCESS) { + if (php_apache_request_ctor(r, ctx)!=SUCCESS) { zend_bailout(); } } else { @@ -626,7 +637,7 @@ zend_first_try { 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 TSRMLS_CC)!=SUCCESS) { + if (php_apache_request_ctor(r, ctx)!=SUCCESS) { zend_bailout(); } } @@ -654,7 +665,7 @@ zend_first_try { 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 TSRMLS_CC); + highlight_file((char *)r->filename, &syntax_highlighter_ini); } else { zend_file_handle zfd; @@ -664,19 +675,19 @@ zend_first_try { zfd.opened_path = NULL; if (!parent_req) { - php_execute_script(&zfd TSRMLS_CC); + php_execute_script(&zfd); } else { - zend_execute_scripts(ZEND_INCLUDE TSRMLS_CC, NULL, 1, &zfd); + 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 TSRMLS_CC))); + 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 TSRMLS_CC); + php_apache_request_dtor(r); ctx->request_processed = 1; bucket = apr_bucket_eos_create(r->connection->bucket_alloc); APR_BRIGADE_INSERT_TAIL(brigade, bucket); @@ -706,6 +717,9 @@ 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(zend_signal_init, NULL, NULL, APR_HOOK_MIDDLE); +#endif ap_hook_child_init(php_apache_child_init, NULL, NULL, APR_HOOK_MIDDLE); } diff --git a/sapi/apache_hooks/CREDITS b/sapi/apache_hooks/CREDITS deleted file mode 100644 index 86ac27d0b7..0000000000 --- a/sapi/apache_hooks/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -Apache 1.3 (apache_hooks) -Rasmus Lerdorf, Zeev Suraski, Stig Bakken, David Sklar, George Schlossnagle, Lukas Schroeder diff --git a/sapi/apache_hooks/README b/sapi/apache_hooks/README deleted file mode 100644 index 9a5a3e2b64..0000000000 --- a/sapi/apache_hooks/README +++ /dev/null @@ -1,206 +0,0 @@ -This is very beta documentation. Clearly better stuff can and will follow. - -INTRO: - -apache_hooks is a full super-set enhancement of the apache 1.3 sapi that allows for -php code to be run on the apache request object at every stage of the apache -request. It supports all of the apache 1.3 sapi commands and configurations, and -additionally supports the following httpd.conf directives: - - -HTTPD.CONF DIRECTIEVS: - -phpRequire /path/to/file = requires a file at the beginning of an -initial apache request - -phpUriHandler /path/to/file = registers a hook that will run the -specified file at the uri translation stage of the apache request -phpUriHandler Class::Method = registers a hook to run Class::Method at -the uri translation stage of the apache request - -phpPostReadHandler /path/to/file = hook for post-read phase -phpPostReadHandlerMethod Class::Method - -phpHeaderHandler = hook for header parsing phase -phpHeaderHandlerMethod - -phpAuthHandler = hook for authentication phase -phpAuthHandlerMethod - -phpAccessHandler = hook for access control phase -phpAccessHandlerMethod - -phpTypeHandler = hook for Type Checking phase -phpTypeHandlerMethod - -phpFixupHandler = hook for 'fixup' phase -phpFixupHandlerMethod - -phpLoggerHandler = hook for logging phase -phpLoggerHandlerMethod - -AddHandler php-script = set's up a special type handler -phpResponseHandler /path/to/file = sets file to be called to handle -response phase -phpResponseHandlerMethod Class::Method - - -All handlers may be stacked, i.e. you can list multiple handler directives -in a single scope and they will be run in order. - - -EXAMPLES: - -So, to set up a 'hello world' location handler (so that any request to -/hello/* returns hello world) you can: - -phpRequire /tmp/setup.php -<Location /hello> -AddHandler php-script -phpResponseHandlerMethod Hello::World -</Location> - -with -#/tmp/setup.php -<? -class Hello { - function World() { - global $request; - $request->send_http_header(); - echo "Hello World"; - } -} -?> - -$request is the apache request. It is instantiated at all stages -automatically. The methods of that class are: - -getallheaders -args -boundary -content_encoding -content_type -filename -handler -hostname -method -path_info -protocol -status_line -the_request -unparsed_uri -uri -allowed -bytes_sent -chunked -content_length -header_only -method_number -mtime -no_cache -no_local_copy -proto_num -proxyreq -read_body -remaining -request_time -status -headers_in -headers_out -err_headers_out -auth_name -auth_type -basic_auth_pw -discard_request_body -is_initial_req -meets_conditions -remote_host -satisfies -server_port -set_etag -set_last_modified -some_auth_required -update_mtime -send_http_header -basic_http_header -send_header_field -send_http_trace -send_http_options -send_error_response -set_content_length -set_keepalive -rputs -log_error -lookup_uri -lookup_file -method_uri -run -internal_redirect - - -These all wrap the ap_* apache EXPORT_API functions using the same -semantics (and are also the same as the Apache::Request methods in -mod_perl if you are familiar with that) - -So, a uri handler to redirect all non-local traffic to /404.php (an -error page) would be - -phpUriHandler /tmp/uri.php - -#/tmp/uri.php -<? - if($REMOTE_ADDR != '127.0.0.1') { - $request->uri('/404.php'); - } - return OK; -?> - -It's important to note that since this is called from the uri -translations phase, this validation is performed for every request to -the server, not just for php pages. - -Also, scope is shared between all the hooks. So in the above, we could -merge the two and do something like: - -#/tmp/uri.php -<? - if($REMOTE_ADDR != '127.0.0.1') { - $whoami = 'Stranger'; - } - else { - $whoami = 'Friend'; - } - return DECLINED; # because we're not redirecting, just messing around -?> - -and then: - -#/tmp/setup.php -<? -class Hello { - function World() { - global $request; - global $whoami; - $request->send_http_header(); - echo "Hello $whoami"; - } -} -?> - -These variables are also in the same scope as a script if your script is -being handled by the standard application/x-httpd-php handler. - -This allows you to make decisions and pass data between your handlers -and scripts at all stages. - -The above are clearly trite examples, but hopefully give you a starting -point. - -One note: all handlers can be validly re-entered 'in sub-requests'. -For this reason you should not define functions/classes here without -anti-redefinition guards (I would just recommend putting them in an -include and using include_one). This is not true for phpRequire, which -is only entered once, at the main request, and so it is safe to make -function/class declarations there (in fact that's what it's for). - -Hope that helps! diff --git a/sapi/apache_hooks/apMakefile.libdir b/sapi/apache_hooks/apMakefile.libdir deleted file mode 100644 index 7b5254013a..0000000000 --- a/sapi/apache_hooks/apMakefile.libdir +++ /dev/null @@ -1,4 +0,0 @@ -This is a place-holder which indicates to Configure that it shouldn't -provide the default targets when building the Makefile in this directory. -Instead it'll just prepend all the important variable definitions, and -copy the Makefile.tmpl onto the end. diff --git a/sapi/apache_hooks/apMakefile.tmpl b/sapi/apache_hooks/apMakefile.tmpl deleted file mode 100644 index 4054e8e119..0000000000 --- a/sapi/apache_hooks/apMakefile.tmpl +++ /dev/null @@ -1,77 +0,0 @@ -## -## Apache 1.3 Makefile template for PHP 4.0 Module -## [src/modules/php5/Makefile.tmpl] -## - -# the parametrized target -LIB=libphp5.$(LIBEXT) - -# objects for building the static library -OBJS=mod_php5.o -OBJS_LIB=libmodphp5.a - -# objects for building the shared object library -SHLIB_OBJS=mod_php5.so-o -SHLIB_OBJS_LIB=libmodphp5.a - -# the general targets -all: lib -lib: $(LIB) - -# build the static library by merging the object files -libphp5.a: $(OBJS) $(OBJS_LIB) - cp $(OBJS_LIB) $@ - ar r $@ $(OBJS) - $(RANLIB) $@ - -# ugly hack to support older Apache-1.3 betas that don't set $LIBEXT -libphp5.: $(OBJS) $(OBJS_LIB) - cp $(OBJS_LIB) $@ - ar r $@ $(OBJS) - $(RANLIB) $@ - cp libphp5. libphp5.a - -# build the shared object library by linking the object files -libphp5.so: $(SHLIB_OBJS) $(SHLIB_OBJS_LIB) - rm -f $@ - $(LD_SHLIB) $(LDFLAGS_SHLIB) -o $@ $(SHLIB_OBJS) $(SHLIB_OBJS_LIB) $(LIBS) $(PHP_LIBS) - -# 1. extension .o for shared objects cannot be used here because -# first these files aren't still shared objects and second we -# have to use a different name to trigger the different -# implicit Make rule -# 2. extension -so.o (as used elsewhere) cannot be used because -# the suffix feature of Make really wants just .x, so we use -# extension .so-o -.SUFFIXES: .o .so-o -.c.o: - $(CC) -c $(INCLUDES) $(CFLAGS) $(PHP_CFLAGS) $(CPPFLAGS) $(SPACER) $< -.c.so-o: - $(CC) -c $(INCLUDES) $(CFLAGS) $(CFLAGS_SHLIB) $(PHP_CFLAGS) $(CPPFLAGS) $(SPACER) $< && mv $*.o $*.so-o - -# cleanup -clean: - -rm -f $(OBJS) $(SHLIB_OBJS) $(LIB) - -# We really don't expect end users to use this rule. It works only with -# gcc, and rebuilds Makefile.tmpl. You have to re-run Configure after -# using it. -depend: - cp Makefile.tmpl Makefile.tmpl.bak \ - && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \ - && gcc -MM $(INCLUDES) $(CFLAGS) $(PHP_CFLAGS) $(CPPFLAGS) *.c >> Makefile.new \ - && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' Makefile.new \ - > Makefile.tmpl \ - && rm Makefile.new - -#Dependencies - -$(OBJS): Makefile - -# DO NOT REMOVE -mod_php5.o: mod_php5.c $(INCDIR)/httpd.h $(INCDIR)/conf.h \ - $(INCDIR)/buff.h \ - $(INCDIR)/http_config.h \ - $(INCDIR)/http_core.h $(INCDIR)/http_main.h \ - $(INCDIR)/http_protocol.h $(INCDIR)/http_request.h \ - $(INCDIR)/http_log.h $(INCDIR)/util_script.h mod_php5.h diff --git a/sapi/apache_hooks/config.m4 b/sapi/apache_hooks/config.m4 deleted file mode 100644 index e2c71b4274..0000000000 --- a/sapi/apache_hooks/config.m4 +++ /dev/null @@ -1,275 +0,0 @@ -dnl -dnl $Id$ -dnl -AC_DEFUN([PHP_APACHE_FD_CHECK], [ -AC_CACHE_CHECK([for member fd in BUFF *],ac_cv_php_fd_in_buff,[ - save=$CPPFLAGS - if test -n "$APXS_INCLUDEDIR"; then - CPPFLAGS="$CPPFLAGS -I$APXS_INCLUDEDIR" - else - CPPFLAGS="$CPPFLAGS $APACHE_INCLUDE" - fi - AC_TRY_COMPILE([#include <httpd.h>],[conn_rec *c; int fd = c->client->fd;],[ - ac_cv_php_fd_in_buff=yes],[ac_cv_php_fd_in_buff=no],[ac_cv_php_fd_in_buff=no]) - CPPFLAGS=$save -]) -if test "$ac_cv_php_fd_in_buff" = "yes"; then - AC_DEFINE(PHP_APACHE_HAVE_CLIENT_FD,1,[ ]) -fi -]) - -dnl Apache 1.x shared module -PHP_ARG_WITH(apache-hooks,, -[ --with-apache-hooks[=FILE] - EXPERIMENTAL: Build shared Apache 1.x module. FILE is the optional - pathname to the Apache apxs tool [apxs]], no, no) - -AC_MSG_CHECKING([for Apache 1.x (hooks) module support via DSO through APXS]) - -if test "$PHP_APACHE_HOOKS" != "no"; then - if test "$PHP_APACHE_HOOKS" = "yes"; then - APXS=apxs - $APXS -q CFLAGS >/dev/null 2>&1 - if test "$?" != "0" && test -x /usr/sbin/apxs; then #SUSE 6.x - APXS=/usr/sbin/apxs - fi - else - PHP_EXPAND_PATH($PHP_APACHE_HOOKS, APXS) - fi - - $APXS -q CFLAGS >/dev/null 2>&1 - if test "$?" != "0"; then - AC_MSG_RESULT() - AC_MSG_RESULT() - AC_MSG_RESULT([Sorry, I was not able to successfully run APXS. Possible reasons:]) - AC_MSG_RESULT() - AC_MSG_RESULT([1. Perl is not installed;]) - AC_MSG_RESULT([2. Apache was not compiled with DSO support (--enable-module=so);]) - AC_MSG_RESULT([3. 'apxs' is not in your path. Try to use --with-apxs=/path/to/apxs]) - AC_MSG_RESULT([The output of $APXS follows]) - $APXS -q CFLAGS - AC_MSG_ERROR([Aborting]) - fi - - APXS_LDFLAGS="@SYBASE_LFLAGS@ @SYBASE_LIBS@ @SYBASE_CT_LFLAGS@ @SYBASE_CT_LIBS@" - APXS_INCLUDEDIR=`$APXS -q INCLUDEDIR` - APXS_CFLAGS=`$APXS -q CFLAGS` - APXS_HTTPD=`$APXS -q SBINDIR`/`$APXS -q TARGET` - APACHE_INCLUDE=-I$APXS_INCLUDEDIR - - # Test that we're trying to configure with apache 1.x - PHP_AP_EXTRACT_VERSION($APXS_HTTPD) - if test "$APACHE_VERSION" -ge 2000000; then - AC_MSG_ERROR([You have enabled Apache 1.3 support while your server is Apache 2. Please use the appropriate switch --with-apxs2]) - fi - - for flag in $APXS_CFLAGS; do - case $flag in - -D*) APACHE_CPPFLAGS="$APACHE_CPPFLAGS $flag";; - esac - done - - case $host_alias in - *aix*) - APXS_LIBEXECDIR=`$APXS -q LIBEXECDIR` - EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-brtl -Wl,-bI:$APXS_LIBEXECDIR/httpd.exp" - PHP_AIX_LDFLAGS="-Wl,-brtl" - build_type=shared - ;; - *darwin*) - MH_BUNDLE_FLAGS="-dynamic -twolevel_namespace -bundle -bundle_loader $APXS_HTTPD" - PHP_SUBST(MH_BUNDLE_FLAGS) - SAPI_SHARED=libs/libphp5.so - build_type=bundle - ;; - *) - build_type=shared - ;; - esac - - PHP_SELECT_SAPI(apache_hooks, $build_type, sapi_apache.c mod_php5.c php_apache.c, $APACHE_CPPFLAGS -I$APXS_INCLUDEDIR) - - # Test whether apxs support -S option - $APXS -q -S CFLAGS="$APXS_CFLAGS" CFLAGS >/dev/null 2>&1 - - if test "$?" != "0"; then - APACHE_HOOKS_INSTALL="$APXS -i -a -n php5 $SAPI_SHARED" # Old apxs does not have -S option - else - APXS_LIBEXECDIR='$(INSTALL_ROOT)'`$APXS -q LIBEXECDIR` - if test -z `$APXS -q SYSCONFDIR`; then - APACHE_HOOKS_INSTALL="\$(mkinstalldirs) '$APXS_LIBEXECDIR' && \ - $APXS -S LIBEXECDIR='$APXS_LIBEXECDIR' \ - -i -n php5 $SAPI_SHARED" - else - APXS_SYSCONFDIR='$(INSTALL_ROOT)'`$APXS -q SYSCONFDIR` - APACHE_HOOKS_INSTALL="\$(mkinstalldirs) '$APXS_LIBEXECDIR' && \ - \$(mkinstalldirs) '$APXS_SYSCONFDIR' && \ - $APXS -S LIBEXECDIR='$APXS_LIBEXECDIR' \ - -S SYSCONFDIR='$APXS_SYSCONFDIR' \ - -i -a -n php5 $SAPI_SHARED" - fi - fi - - if test -z "`$APXS -q LD_SHLIB`" || test "`$APXS -q LIBEXECDIR`" = "modules"; then - PHP_APXS_BROKEN=yes - fi - STRONGHOLD= - AC_DEFINE(HAVE_AP_CONFIG_H,1,[ ]) - AC_DEFINE(HAVE_AP_COMPAT_H,1,[ ]) - AC_DEFINE(HAVE_APACHE_HOOKS,1,[ ]) - AC_MSG_RESULT(yes) -else - AC_MSG_RESULT(no) -fi - -dnl Apache 1.x static module -PHP_ARG_WITH(apache-hooks-static,, -[ --with-apache-hooks-static[=DIR] - EXPERIMENTAL: Build Apache 1.x module. DIR is the top-level Apache - build directory [/usr/local/apache]], no, no) - -AC_MSG_CHECKING(for Apache 1.x (hooks) module support) - -if test "$PHP_SAPI" != "apache" && test "$PHP_SAPI" != "apache_hooks" && test "$PHP_APACHE_HOOKS_STATIC" != "no"; then - - if test "$PHP_APACHE_HOOKS_STATIC" = "yes"; then - # Apache's default directory - PHP_APACHE_HOOKS_STATIC=/usr/local/apache - fi - - APACHE_HOOKS_INSTALL_FILES="\$(srcdir)/sapi/apache_hooks/mod_php5.* sapi/apache_hooks/libphp5.module" - - AC_DEFINE(HAVE_APACHE,1,[ ]) - APACHE_HOOKS_MODULE=yes - PHP_EXPAND_PATH($PHP_APACHE_HOOKS_STATIC, PHP_APACHE_HOOKS_STATIC) - # For Apache 1.2.x - if test -f $PHP_APACHE_HOOKS_STATIC/src/httpd.h; then - APACHE_INCLUDE=-I$PHP_APACHE_HOOKS_STATIC/src - APACHE_TARGET=$PHP_APACHE_HOOKS_STATIC/src - PHP_SELECT_SAPI(apache_hooks, static, sapi_apache.c mod_php5.c php_apache.c, $APACHE_INCLUDE) - APACHE_HOOKS_INSTALL="mkdir -p $APACHE_TARGET; cp $SAPI_STATIC $APACHE_HOOKS_INSTALL_FILES $APACHE_TARGET" - PHP_LIBS="-L. -lphp3" - AC_MSG_RESULT([yes - Apache 1.2.x]) - STRONGHOLD= - if test -f $PHP_APACHE_HOOKS_STATIC/src/ap_config.h; then - AC_DEFINE(HAVE_AP_CONFIG_H,1,[ ]) - fi - # For Apache 2.0.x - elif test -f $PHP_APACHE_HOOKS_STATIC/include/httpd.h && test -f $PHP_APACHE_HOOKS_STATIC/srclib/apr/include/apr_general.h ; then - AC_MSG_ERROR([Use --with-apxs2 with Apache 2.x!]) - # For Apache 1.3.x - elif test -f $PHP_APACHE_HOOKS_STATIC/src/main/httpd.h; then - APACHE_HAS_REGEX=1 - APACHE_INCLUDE="-I$PHP_APACHE_HOOKS_STATIC/src/main -I$PHP_APACHE_HOOKS_STATIC/src/os/unix -I$PHP_APACHE_HOOKS_STATIC/src/ap" - APACHE_TARGET=$PHP_APACHE_HOOKS_STATIC/src/modules/php5 - if test ! -d $APACHE_TARGET; then - mkdir $APACHE_TARGET - fi - PHP_SELECT_SAPI(apache_hooks, static, sapi_apache.c mod_php5.c php_apache.c, $APACHE_INCLUDE) - APACHE_HOOKS_INSTALL="mkdir -p $APACHE_TARGET; cp $SAPI_STATIC $APACHE_TARGET/libmodphp5.a; cp $APACHE_HOOKS_INSTALL_FILES $APACHE_TARGET; cp $srcdir/sapi/apache_hooks/apMakefile.tmpl $APACHE_TARGET/Makefile.tmpl; cp $srcdir/sapi/apache_hooks/apMakefile.libdir $APACHE_TARGET/Makefile.libdir" - PHP_LIBS="-Lmodules/php5 -L../modules/php5 -L../../modules/php5 -lmodphp5" - AC_MSG_RESULT([yes - Apache 1.3.x]) - STRONGHOLD= - if test -f $PHP_APACHE_HOOKS_STATIC/src/include/ap_config.h; then - AC_DEFINE(HAVE_AP_CONFIG_H, 1, [ ]) - fi - if test -f $PHP_APACHE_HOOKS_STATIC/src/include/ap_compat.h; then - AC_DEFINE(HAVE_AP_COMPAT_H, 1, [ ]) - if test ! -f $PHP_APACHE_HOOKS_STATIC/src/include/ap_config_auto.h; then - AC_MSG_ERROR([Please run Apache\'s configure or src/Configure program once and try again]) - fi - elif test -f $PHP_APACHE_HOOKS_STATIC/src/include/compat.h; then - AC_DEFINE(HAVE_OLD_COMPAT_H, 1, [ ]) - fi - # Also for Apache 1.3.x - elif test -f $PHP_APACHE_HOOKS_STATIC/src/include/httpd.h; then - APACHE_HAS_REGEX=1 - APACHE_INCLUDE="-I$PHP_APACHE_HOOKS_STATIC/src/include -I$PHP_APACHE_HOOKS_STATIC/src/os/unix" - APACHE_TARGET=$PHP_APACHE_HOOKS_STATIC/src/modules/php5 - if test ! -d $APACHE_TARGET; then - mkdir $APACHE_TARGET - fi - PHP_SELECT_SAPI(apache_hooks, static, sapi_apache.c mod_php5.c php_apache.c, $APACHE_INCLUDE) - PHP_LIBS="-Lmodules/php5 -L../modules/php5 -L../../modules/php5 -lmodphp5" - APACHE_HOOKS_INSTALL="mkdir -p $APACHE_TARGET; cp $SAPI_STATIC $APACHE_TARGET/libmodphp5.a; cp $APACHE_HOOKS_INSTALL_FILES $APACHE_TARGET; cp $srcdir/sapi/apache_hooks/apMakefile.tmpl $APACHE_TARGET/Makefile.tmpl; cp $srcdir/sapi/apache_hooks/apMakefile.libdir $APACHE_TARGET/Makefile.libdir" - AC_MSG_RESULT([yes - Apache 1.3.x]) - STRONGHOLD= - if test -f $PHP_APACHE_HOOKS_STATIC/src/include/ap_config.h; then - AC_DEFINE(HAVE_AP_CONFIG_H, 1, [ ]) - fi - if test -f $PHP_APACHE_HOOKS_STATIC/src/include/ap_compat.h; then - AC_DEFINE(HAVE_AP_COMPAT_H, 1, [ ]) - if test ! -f $PHP_APACHE_HOOKS_STATIC/src/include/ap_config_auto.h; then - AC_MSG_ERROR([Please run Apache\'s configure or src/Configure program once and try again]) - fi - elif test -f $PHP_APACHE_HOOKS_STATIC/src/include/compat.h; then - AC_DEFINE(HAVE_OLD_COMPAT_H, 1, [ ]) - fi - # For StrongHold 2.2 - elif test -f $PHP_APACHE_HOOKS_STATIC/apache/httpd.h; then - APACHE_INCLUDE="-I$PHP_APACHE_HOOKS_STATIC/apache -I$PHP_APACHE_HOOKS_STATIC/ssl/include" - APACHE_TARGET=$PHP_APACHE_HOOKS_STATIC/apache - PHP_SELECT_SAPI(apache_hooks, static, sapi_apache.c mod_php5.c php_apache.c, $APACHE_INCLUDE) - PHP_LIBS="-Lmodules/php5 -L../modules/php5 -L../../modules/php5 -lmodphp5" - APACHE_HOOKS_INSTALL="mkdir -p $APACHE_TARGET; cp $SAPI_STATIC $APACHE_TARGET/libmodphp5.a; cp $APACHE_HOOKS_INSTALL_FILES $APACHE_TARGET" - STRONGHOLD=-DSTRONGHOLD=1 - AC_MSG_RESULT([yes - StrongHold]) - if test -f $PHP_APACHE_HOOKS_STATIC/apache/ap_config.h; then - AC_DEFINE(HAVE_AP_CONFIG_H, 1, [ ]) - fi - if test -f $PHP_APACHE_HOOKS_STATIC/src/ap_compat.h; then - AC_DEFINE(HAVE_AP_COMPAT_H, 1, [ ]) - if test ! -f $PHP_APACHE_HOOKS_STATIC/src/include/ap_config_auto.h; then - AC_MSG_ERROR([Please run Apache\'s configure or src/Configure program once and try again]) - fi - elif test -f $PHP_APACHE_HOOKS_STATIC/src/compat.h; then - AC_DEFINE(HAVE_OLD_COMPAT_H, 1, [ ]) - fi - else - AC_MSG_RESULT(no) - AC_MSG_ERROR([Invalid Apache directory - unable to find httpd.h under $PHP_APACHE_HOOKS_STATIC]) - fi -else - AC_MSG_RESULT(no) -fi - -# compatibility -if test -z "$enable_mod_charset" && test "$with_mod_charset"; then - enable_mod_charset=$with_mod_charset -fi - -PHP_ARG_ENABLE(mod-charset, whether to enable Apache charset compatibility option, -[ --enable-mod-charset APACHE (hooks): Enable transfer tables for mod_charset (Rus Apache)], no, no) - -if test "$PHP_MOD_CHARSET" = "yes"; then - AC_DEFINE(USE_TRANSFER_TABLES, 1, [ ]) -fi - -dnl Build as static module -if test "$APACHE_HOOKS_MODULE" = "yes"; then - PHP_TARGET_RDYNAMIC - $php_shtool mkdir -p sapi/apache_hooks - PHP_OUTPUT(sapi/apache_hooks/libphp5.module) -fi - -dnl General -if test -n "$APACHE_HOOKS_INSTALL"; then - if test "x$APXS" != "x" -a "`uname -sv`" = "AIX 4" -a "$GCC" != "yes"; then - APXS_EXP=-bE:sapi/apache_hooks/mod_php5.exp - fi - - PHP_APACHE_FD_CHECK - INSTALL_IT=$APACHE_HOOKS_INSTALL - - PHP_SUBST(APXS_EXP) - PHP_SUBST(APACHE_INCLUDE) - PHP_SUBST(APACHE_TARGET) - PHP_SUBST(APXS) - PHP_SUBST(APXS_LDFLAGS) - PHP_SUBST(APACHE_HOOKS_INSTALL) - PHP_SUBST(STRONGHOLD) -fi - -dnl ## Local Variables: -dnl ## tab-width: 4 -dnl ## End: diff --git a/sapi/apache_hooks/config.w32 b/sapi/apache_hooks/config.w32 deleted file mode 100644 index 85dc624d60..0000000000 --- a/sapi/apache_hooks/config.w32 +++ /dev/null @@ -1,21 +0,0 @@ -// vim:ft=javascript -// $Id$ - -ARG_WITH('apache-hooks', 'Build Apache 1.3.x (hooks) version of PHP', 'no'); - -if (PHP_APACHE_HOOKS != "no") { - if (CHECK_HEADER_ADD_INCLUDE("httpd.h", "CFLAGS_APACHE_HOOKS", php_usual_include_suspects + - ";" + PROGRAM_FILES + "\\Apache Group\\Apache\\include" + - ";" + PHP_PHP_BUILD + "\\apache\\src\\include") && - CHECK_LIB("ApacheCore.lib", "apache_hooks", php_usual_lib_suspects + - ';' + PROGRAM_FILES + '\\Apache Group\\Apache\\libexec' + - ";" + PHP_PHP_BUILD + "\\apache\\src\\corer")) { - // We need to play tricks to get our readdir.h used by apache - // headers - SAPI('apache_hooks', 'mod_php5.c sapi_apache.c php_apache.c', - 'php' + PHP_VERSION + 'apache_hooks.dll', - '/D APACHEPHP5_EXPORTS /D APACHE_READDIR_H /I win32'); - } else { - WARNING("Could not find apache libraries/headers"); - } -} diff --git a/sapi/apache_hooks/libphp5.module.in b/sapi/apache_hooks/libphp5.module.in deleted file mode 100644 index 8488181897..0000000000 --- a/sapi/apache_hooks/libphp5.module.in +++ /dev/null @@ -1,11 +0,0 @@ -Name: php5_module -ConfigStart - RULE_WANTHSREGEX=no - RULE_HIDE=yes - PHP_LIBS="@NATIVE_RPATHS@ @PHP_LDFLAGS@ @PHP_LIBS@ @EXTRA_LIBS@ $LIBS" - PHP_CFLAGS="$CFLAGS @OPENSSL_INCDIR_OPT@ -I@php_abs_top_builddir@/main -I@php_abs_top_builddir@/Zend -I@php_abs_top_builddir@/TSRM -I@php_abs_top_srcdir@ -I@php_abs_top_srcdir@/sapi/apache -I@php_abs_top_srcdir@/main -I@php_abs_top_srcdir@/Zend -I@php_abs_top_srcdir@/TSRM" - my_outfile="Makefile.config" - echo "PHP_CFLAGS=$PHP_CFLAGS" >>$my_outfile - echo "PHP_LIBS=$PHP_LIBS" >>$my_outfile - LIBS=$PHP_LIBS -ConfigEnd diff --git a/sapi/apache_hooks/mod_php5.c b/sapi/apache_hooks/mod_php5.c deleted file mode 100644 index 039e145f93..0000000000 --- a/sapi/apache_hooks/mod_php5.c +++ /dev/null @@ -1,1493 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 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 at through the world-wide-web at | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Rasmus Lerdorf <rasmus@php.net> | - | (with helpful hints from Dean Gaudet <dgaudet@arctic.org> | - | PHP 4.0 patches by Zeev Suraski <zeev@zend.com> | - +----------------------------------------------------------------------+ - */ -/* $Id$ */ - -#include "php_apache_http.h" - -#ifdef NETWARE -#define SIGPIPE SIGINT -#endif - -#undef shutdown - -/* {{{ Prototypes - */ -int apache_php_module_main(request_rec *r, int display_source_mode TSRMLS_DC); -static void php_save_umask(void); -static void php_restore_umask(void); -static int sapi_apache_read_post(char *buffer, uint count_bytes TSRMLS_DC); -static char *sapi_apache_read_cookies(TSRMLS_D); -static int sapi_apache_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC); -static int sapi_apache_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC); -static int send_php(request_rec *r, int display_source_mode, char *filename); -static int send_parsed_php(request_rec * r); -static int send_parsed_php_source(request_rec * r); -static int php_xbithack_handler(request_rec * r); -static void php_init_handler(server_rec *s, pool *p); -/* }}} */ - -#if MODULE_MAGIC_NUMBER >= 19970728 -static void php_child_exit_handler(server_rec *s, pool *p); -#endif - -#if MODULE_MAGIC_NUMBER > 19961007 -#define CONST_PREFIX const -#else -#define CONST_PREFIX -#endif - - -typedef struct _sapi_stack { - int top, max, persistent; - void **elements; -} sapi_stack; - -typedef struct _php_per_dir_config { - HashTable *ini_settings; - sapi_stack headers_handlers; - sapi_stack auth_handlers; - sapi_stack access_handlers; - sapi_stack type_handlers; - sapi_stack fixup_handlers; - sapi_stack logger_handlers; - sapi_stack post_read_handlers; - sapi_stack response_handlers; -} php_per_dir_config; - -typedef struct _php_per_server_config { - sapi_stack uri_handlers; - sapi_stack requires; -} php_per_server_config; - - -static CONST_PREFIX char *php_apache_value_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode); -static CONST_PREFIX char *php_apache_value_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2); -static CONST_PREFIX char *php_apache_admin_value_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2); -static CONST_PREFIX char *php_apache_flag_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2); -static CONST_PREFIX char *php_apache_flag_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode); -static CONST_PREFIX char *php_apache_admin_flag_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2); - -/* ### these should be defined in mod_php5.h or somewhere else */ -#define USE_PATH 1 -#define IGNORE_URL 2 - -module MODULE_VAR_EXPORT php5_module; - -int saved_umask; -/* static int setup_env = 0; */ -static unsigned char apache_php_initialized; - -typedef struct _php_per_dir_entry { - char *key; - char *value; - uint key_length; - uint value_length; - int type; -} php_per_dir_entry; - -/* some systems are missing these from their header files */ - -/* {{{ zend stack utility functions - */ - -/* This code is ripped part and parcel from zend_stack.[ch]. Assuming that the - patch supporting zend_stack_init_ex is applied, all but the bottom two - module-specific iterators will be removed - */ - -int sapi_stack_init_ex(sapi_stack *stack, int persistent) -{ - stack->top = 0; - stack->persistent = persistent; - stack->elements = (void **) pemalloc(sizeof(void **) * STACK_BLOCK_SIZE, persistent); - if (!stack->elements) { - return FAILURE; - } else { - stack->max = STACK_BLOCK_SIZE; - return SUCCESS; - } -} -int sapi_stack_push(sapi_stack *stack, void *element) -{ - if (stack->top >= stack->max) { /* we need to allocate more memory */ - stack->elements = (void **) perealloc(stack->elements, - (sizeof(void **) * (stack->max += STACK_BLOCK_SIZE)), stack->persistent); - if (!stack->elements) { - return FAILURE; - } - } - stack->elements[stack->top] = (void *) element; - return stack->top++; -} -void* sapi_stack_pop(sapi_stack *stack) { - if(stack->top == 0) { - return NULL; - } - else { - return stack->elements[--stack->top]; - } -} - -int sapi_stack_destroy(sapi_stack *stack) -{ - return SUCCESS; -} - -int sapi_stack_apply_with_argument_all(sapi_stack *stack, int type, int (*apply_function)(void *element, void *arg), void *arg) -{ - int i, retval; - - switch (type) { - case ZEND_STACK_APPLY_TOPDOWN: - for (i=stack->top-1; i>=0; i--) { - retval = apply_function(stack->elements[i], arg); - } - break; - case ZEND_STACK_APPLY_BOTTOMUP: - for (i=0; i<stack->top; i++) { - retval = apply_function(stack->elements[i], arg); - } - break; - } - return retval; -} - - -int sapi_stack_apply_with_argument_stop_if_equals(sapi_stack *stack, int type, int (*apply_function)(void *element, void *arg), void *arg, int stopval) -{ - int i; - int ret = DECLINED; - switch (type) { - case ZEND_STACK_APPLY_TOPDOWN: - for (i=stack->top-1; i>=0; i--) { - if ((ret = apply_function(stack->elements[i], arg)) == stopval) { - break; - } - } - break; - case ZEND_STACK_APPLY_BOTTOMUP: - for (i=0; i<stack->top; i++) { - if ((ret = apply_function(stack->elements[i], arg)) == stopval) { - break; - } - } - break; - } - return ret; -} - -int sapi_stack_apply_with_argument_stop_if_http_error(sapi_stack *stack, int type, int (*apply_function)(void *element, void *arg), void *arg) -{ - int i; - int ret = DECLINED; - switch (type) { - case ZEND_STACK_APPLY_TOPDOWN: - for (i=stack->top-1; i>=0; i--) { - if ((ret = apply_function(stack->elements[i], arg)) > 0) { - break; - } - } - break; - case ZEND_STACK_APPLY_BOTTOMUP: - for (i=0; i<stack->top; i++) { - if ((ret = apply_function(stack->elements[i], arg)) > 0) { - break; - } - } - break; - } - return ret; -} - -void php_handler_stack_destroy(sapi_stack *stack) -{ - php_handler *ph; - while((ph = (php_handler *)sapi_stack_pop(stack)) != NULL) { - free(ph->name); - free(ph); - } -} -/* }}} */ - -/* {{{ php_save_umask - */ -static void php_save_umask(void) -{ - saved_umask = umask(077); - umask(saved_umask); -} -/* }}} */ - -/* {{{ sapi_apache_ub_write - */ -static int sapi_apache_ub_write(const char *str, uint str_length TSRMLS_DC) -{ - int ret=0; - - if (SG(server_context)) { - ret = rwrite(str, str_length, (request_rec *) SG(server_context)); - } - if (ret != str_length) { - php_handle_aborted_connection(); - } - return ret; -} -/* }}} */ - -/* {{{ sapi_apache_flush - */ -static void sapi_apache_flush(void *server_context) -{ - if (server_context) { -#if MODULE_MAGIC_NUMBER > 19970110 - rflush((request_rec *) server_context); -#else - bflush((request_rec *) server_context->connection->client); -#endif - } -} -/* }}} */ - -/* {{{ sapi_apache_read_post - */ -static int sapi_apache_read_post(char *buffer, uint count_bytes TSRMLS_DC) -{ - uint total_read_bytes=0, read_bytes; - request_rec *r = (request_rec *) SG(server_context); - void (*handler)(int); - - /* - * This handles the situation where the browser sends a Expect: 100-continue header - * and needs to receive confirmation from the server on whether or not it can send - * the rest of the request. RFC 2616 - * - */ - if (!SG(read_post_bytes) && !ap_should_client_block(r)) { - return total_read_bytes; - } - - handler = signal(SIGPIPE, SIG_IGN); - while (total_read_bytes<count_bytes) { - hard_timeout("Read POST information", r); /* start timeout timer */ - read_bytes = get_client_block(r, buffer+total_read_bytes, count_bytes-total_read_bytes); - reset_timeout(r); - if (read_bytes<=0) { - break; - } - total_read_bytes += read_bytes; - } - signal(SIGPIPE, handler); - return total_read_bytes; -} -/* }}} */ - -/* {{{ sapi_apache_read_cookies - */ -static char *sapi_apache_read_cookies(TSRMLS_D) -{ - return (char *) table_get(((request_rec *) SG(server_context))->subprocess_env, "HTTP_COOKIE"); -} -/* }}} */ - -/* {{{ sapi_apache_header_handler - */ -static int sapi_apache_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - char *header_name, *header_content, *p; - request_rec *r = (request_rec *) SG(server_context); - if(!r) { - return 0; - } - - switch(op) { - case SAPI_HEADER_DELETE_ALL: - clear_table(r->headers_out); - return 0; - - case SAPI_HEADER_DELETE: - table_unset(r->headers_out, sapi_header->header); - return 0; - - case SAPI_HEADER_ADD: - case SAPI_HEADER_REPLACE: - header_name = sapi_header->header; - - header_content = p = strchr(header_name, ':'); - if (!p) { - return 0; - } - - *p = 0; - do { - header_content++; - } while (*header_content==' '); - - if (!strcasecmp(header_name, "Content-Type")) { - r->content_type = pstrdup(r->pool, header_content); - } else if (!strcasecmp(header_name, "Set-Cookie")) { - table_add(r->headers_out, header_name, header_content); - } else if (op == SAPI_HEADER_REPLACE) { - table_set(r->headers_out, header_name, header_content); - } else { - table_add(r->headers_out, header_name, header_content); - } - - *p = ':'; /* a well behaved header handler shouldn't change its original arguments */ - - return SAPI_HEADER_ADD; - - default: - return 0; - } -} -/* }}} */ - -/* {{{ sapi_apache_send_headers - */ -static int sapi_apache_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - if(SG(server_context) == NULL) { /* server_context is not here anymore */ - return SAPI_HEADER_SEND_FAILED; - } - - ((request_rec *) SG(server_context))->status = SG(sapi_headers).http_response_code; - /* check that we haven't sent headers already, we use our own - * headers_sent since we may send headers at anytime - */ - if(!AP(headers_sent)) { - send_http_header((request_rec *) SG(server_context)); - AP(headers_sent) = 1; - } - return SAPI_HEADER_SENT_SUCCESSFULLY; -} -/* }}} */ - -/* {{{ sapi_apache_register_server_variables - */ -static void sapi_apache_register_server_variables(zval *track_vars_array TSRMLS_DC) -{ - register int i; - array_header *arr = table_elts(((request_rec *) SG(server_context))->subprocess_env); - table_entry *elts = (table_entry *) arr->elts; - zval **path_translated; - HashTable *symbol_table; - - for (i = 0; i < arr->nelts; i++) { - char *val; - - if (elts[i].val) { - val = elts[i].val; - } else { - val = ""; - } - php_register_variable(elts[i].key, val, track_vars_array TSRMLS_CC); - } - - /* If PATH_TRANSLATED doesn't exist, copy it from SCRIPT_FILENAME */ - if (track_vars_array) { - symbol_table = track_vars_array->value.ht; - } else { - symbol_table = NULL; - } - if (symbol_table - && !zend_hash_exists(symbol_table, "PATH_TRANSLATED", sizeof("PATH_TRANSLATED")) - && zend_hash_find(symbol_table, "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME"), (void **) &path_translated)==SUCCESS) { - php_register_variable("PATH_TRANSLATED", Z_STRVAL_PP(path_translated), track_vars_array TSRMLS_CC); - } - - php_register_variable("PHP_SELF", ((request_rec *) SG(server_context))->uri, track_vars_array TSRMLS_CC); -} -/* }}} */ - -/* {{{ php_apache_startup - */ -static int php_apache_startup(sapi_module_struct *sapi_module) -{ - if (php_module_startup(sapi_module, &apache_module_entry, 1) == FAILURE) { - return FAILURE; - } else { - return SUCCESS; - } -} -/* }}} */ - -/* {{{ php_apache_log_message - */ -static void php_apache_log_message(char *message TSRMLS_DC) -{ - if (SG(server_context)) { -#if MODULE_MAGIC_NUMBER >= 19970831 - aplog_error(NULL, 0, APLOG_ERR | APLOG_NOERRNO, ((request_rec *) SG(server_context))->server, "%s", message); -#else - log_error(message, ((request_rec *) SG(server_context))->server); -#endif - } else { - fprintf(stderr, "%s", message); - fprintf(stderr, "\n"); - } -} -/* }}} */ - -/* {{{ php_apache_request_shutdown - */ -static void php_apache_request_shutdown(void *dummy) -{ - TSRMLS_FETCH(); - AP(current_hook) = AP_CLEANUP; - php_output_set_status(PHP_OUTPUT_DISABLED TSRMLS_CC); - SG(server_context) = NULL; /* The server context (request) is invalid by the time run_cleanups() is called */ - if(SG(sapi_started)) { - php_request_shutdown(dummy); - SG(sapi_started) = 0; - } - AP(in_request) = 0; - if(AP(setup_env)) { - AP(setup_env) = 0; - } - AP(current_hook) = AP_WAITING_FOR_REQUEST; - AP(headers_sent) = 0; -} -/* }}} */ - -/* {{{ php_apache_sapi_activate - */ -static int php_apache_sapi_activate(TSRMLS_D) -{ - request_rec *r = (request_rec *) SG(server_context); - - /* - * For the Apache module version, this bit of code registers a cleanup - * function that gets triggered when our request pool is destroyed. - * We need this because at any point in our code we can be interrupted - * and that may happen before we have had time to free our memory. - * The php_request_shutdown function needs to free all outstanding allocated - * memory. - */ - block_alarms(); - register_cleanup(r->pool, NULL, php_apache_request_shutdown, php_request_shutdown_for_exec); - AP(in_request)=1; - unblock_alarms(); - - /* Override the default headers_only value - sometimes "GET" requests should actually only - * send headers. - */ - SG(request_info).headers_only = r->header_only; - return SUCCESS; -} -/* }}} */ - -/* {{{ php_apache_get_stat - */ -static struct stat *php_apache_get_stat(TSRMLS_D) -{ - return &((request_rec *) SG(server_context))->finfo; -} -/* }}} */ - -/* {{{ php_apache_getenv - */ -static char *php_apache_getenv(char *name, size_t name_len TSRMLS_DC) -{ - return (char *) table_get(((request_rec *) SG(server_context))->subprocess_env, name); -} -/* }}} */ - -/* {{{ sapi_module_struct apache_sapi_module - */ -static sapi_module_struct apache_sapi_module = { - "apache", /* name */ - "Apache", /* pretty name */ - - php_apache_startup, /* startup */ - php_module_shutdown_wrapper, /* shutdown */ - - php_apache_sapi_activate, /* activate */ - NULL, /* deactivate */ - - sapi_apache_ub_write, /* unbuffered write */ - sapi_apache_flush, /* flush */ - php_apache_get_stat, /* get uid */ - php_apache_getenv, /* getenv */ - - php_error, /* error handler */ - - sapi_apache_header_handler, /* header handler */ - sapi_apache_send_headers, /* send headers handler */ - NULL, /* send header handler */ - - sapi_apache_read_post, /* read POST data */ - sapi_apache_read_cookies, /* read Cookies */ - - sapi_apache_register_server_variables, /* register server variables */ - php_apache_log_message, /* Log message */ - NULL, /* Get request time */ - NULL, /* child terminate */ - - NULL, /* php.ini path override */ - -#ifdef PHP_WIN32 - NULL, - NULL, -#else - block_alarms, /* Block interruptions */ - unblock_alarms, /* Unblock interruptions */ -#endif - - NULL, /* default post reader */ - NULL, /* treat data */ - NULL, /* exe location */ - 0, /* ini ignore */ - NULL - -}; -/* }}} */ - -/* {{{ php_restore_umask - */ -static void php_restore_umask(void) -{ - umask(saved_umask); -} -/* }}} */ - -/* {{{ init_request_info - */ -static void init_request_info(TSRMLS_D) -{ - request_rec *r = ((request_rec *) SG(server_context)); - char *content_length = (char *) table_get(r->subprocess_env, "CONTENT_LENGTH"); - const char *authorization=NULL; - char *tmp, *tmp_user; - - SG(request_info).query_string = r->args; - SG(request_info).path_translated = r->filename; - SG(request_info).request_uri = r->uri; - SG(request_info).request_method = (char *)r->method; - SG(request_info).proto_num = r->proto_num; - SG(request_info).content_type = (char *) table_get(r->subprocess_env, "CONTENT_TYPE"); - SG(request_info).content_length = (content_length ? atol(content_length) : 0); - SG(sapi_headers).http_response_code = r->status; - - if (r->headers_in) { - authorization = table_get(r->headers_in, "Authorization"); - } - - SG(request_info).auth_user = NULL; - SG(request_info).auth_password = NULL; - - if (authorization && !auth_type(r)) { - if (!strcasecmp(getword(r->pool, &authorization, ' '), "Basic")) { - tmp = uudecode(r->pool, authorization); - tmp_user = getword_nulls_nc(r->pool, &tmp, ':'); - if (tmp_user) { - r->connection->user = pstrdup(r->connection->pool, tmp_user); - r->connection->ap_auth_type = "Basic"; - SG(request_info).auth_user = estrdup(tmp_user); - } - if (tmp) { - SG(request_info).auth_password = estrdup(tmp); - } - } else if (!strcasecmp(getword(r->pool, &authorization, ' '), "Digest")) { - r->connection->ap_auth_type = "Digest"; - SG(request_info).auth_digest = estrdup(authorization); - } - } -} -/* }}} */ - -/* {{{ php_apache_alter_ini_entries - */ -static int php_apache_alter_ini_entries(php_per_dir_entry *per_dir_entry TSRMLS_DC) -{ - zend_alter_ini_entry(per_dir_entry->key, per_dir_entry->key_length+1, per_dir_entry->value, per_dir_entry->value_length, per_dir_entry->type, PHP_INI_STAGE_ACTIVATE); - return 0; -} -/* }}} */ - -/* {{{ php_apache_get_default_mimetype - */ -static char *php_apache_get_default_mimetype(request_rec *r TSRMLS_DC) -{ - - char *mimetype; - if (SG(default_mimetype) || SG(default_charset)) { - /* Assume output will be of the default MIME type. Individual - scripts may change this later. */ - char *tmpmimetype; - tmpmimetype = sapi_get_default_content_type(TSRMLS_C); - mimetype = pstrdup(r->pool, tmpmimetype); - efree(tmpmimetype); - } else { - mimetype = SAPI_DEFAULT_MIMETYPE "; charset=" SAPI_DEFAULT_CHARSET; - } - return mimetype; -} -/* }}} */ - -/* {{{ send_php - */ -static int send_php(request_rec *r, int display_source_mode, char *filename) -{ - int retval; - php_per_dir_config *per_dir_conf; - TSRMLS_FETCH(); - if (AP(in_request)) { - zend_file_handle fh; - - fh.filename = r->filename; - fh.opened_path = NULL; - fh.free_filename = 0; - fh.type = ZEND_HANDLE_FILENAME; - - zend_execute_scripts(ZEND_INCLUDE TSRMLS_CC, NULL, 1, &fh); - return OK; - } - - zend_first_try { - - /* Make sure file exists */ - if (filename == NULL && r->finfo.st_mode == 0) { - return DECLINED; - } - - per_dir_conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module); - if (per_dir_conf) { - zend_hash_apply((HashTable *) per_dir_conf->ini_settings, (apply_func_t) php_apache_alter_ini_entries TSRMLS_CC); - } - - /* If PHP parser engine has been turned off with an "engine off" - * directive, then decline to handle this request - */ - if (!AP(engine)) { - r->content_type = php_apache_get_default_mimetype(r TSRMLS_CC); - r->allowed |= (1 << METHODS) - 1; - zend_try { - zend_ini_deactivate(TSRMLS_C); - } zend_end_try(); - return DECLINED; - } - if (filename == NULL) { - filename = r->filename; - } - - /* Apache 1.2 has a more complex mechanism for reading POST data */ -#if MODULE_MAGIC_NUMBER > 19961007 - if ((retval = setup_client_block(r, REQUEST_CHUNKED_ERROR))) { - zend_try { - zend_ini_deactivate(TSRMLS_C); - } zend_end_try(); - return retval; - } -#endif - - if (AP(last_modified)) { -#if MODULE_MAGIC_NUMBER < 19970912 - if ((retval = set_last_modified(r, r->finfo.st_mtime))) { - zend_try { - zend_ini_deactivate(TSRMLS_C); - } zend_end_try(); - return retval; - } -#else - update_mtime (r, r->finfo.st_mtime); - set_last_modified(r); - set_etag(r); -#endif - } - /* Assume output will be of the default MIME type. Individual - scripts may change this later in the request. */ - r->content_type = php_apache_get_default_mimetype(r TSRMLS_CC); - - /* Init timeout */ - hard_timeout("send", r); - - SG(server_context) = r; - - php_save_umask(); - if(!AP(setup_env)) { - AP(setup_env) = 1; - add_common_vars(r); - add_cgi_vars(r); - } - init_request_info(TSRMLS_C); - apache_php_module_main(r, display_source_mode TSRMLS_CC); - - /* Done, restore umask, turn off timeout, close file and return */ - php_restore_umask(); - kill_timeout(r); - } zend_end_try(); - - return OK; -} -/* }}} */ - -/* {{{ send_parsed_php - */ -static int send_parsed_php(request_rec * r) -{ - int result = send_php(r, 0, NULL); - TSRMLS_FETCH(); - - ap_table_setn(r->notes, "mod_php_memory_usage", - ap_psprintf(r->pool, "%u", zend_memory_peak_usage(1 TSRMLS_CC))); - - return result; -} -/* }}} */ - -/* {{{ send_parsed_php_source - */ -static int send_parsed_php_source(request_rec * r) -{ - return send_php(r, 1, NULL); -} -/* }}} */ - - -/* {{{ destroy_per_dir_entry - */ -static void destroy_per_dir_entry(php_per_dir_entry *per_dir_entry) -{ - free(per_dir_entry->key); - free(per_dir_entry->value); -} -/* }}} */ - -/* {{{ copy_per_dir_entry - */ -static void copy_per_dir_entry(php_per_dir_entry *per_dir_entry) -{ - php_per_dir_entry tmp = *per_dir_entry; - - per_dir_entry->key = (char *) malloc(tmp.key_length+1); - memcpy(per_dir_entry->key, tmp.key, tmp.key_length); - per_dir_entry->key[per_dir_entry->key_length] = 0; - - per_dir_entry->value = (char *) malloc(tmp.value_length+1); - memcpy(per_dir_entry->value, tmp.value, tmp.value_length); - per_dir_entry->value[per_dir_entry->value_length] = 0; -} -/* }}} */ - -/* {{{ should_overwrite_per_dir_entry; - - */ -static zend_bool should_overwrite_per_dir_entry(HashTable *target_ht, php_per_dir_entry *orig_per_dir_entry, zend_hash_key *hash_key, void *pData) -{ - php_per_dir_entry *new_per_dir_entry; - - if (zend_hash_find(target_ht, hash_key->arKey, hash_key->nKeyLength, (void **) &new_per_dir_entry)==FAILURE) { - return 1; /* does not exist in dest, copy from source */ - } - - if (new_per_dir_entry->type==PHP_INI_SYSTEM - && orig_per_dir_entry->type!=PHP_INI_SYSTEM) { - return 1; - } else { - return 0; - } -} -/* }}} */ -/* {{{ php_destroy_per_server_info - */ -static void php_destroy_per_server_info(php_per_server_config *conf) -{ - php_handler_stack_destroy(&conf->requires); - php_handler_stack_destroy(&conf->uri_handlers); -} -/* }}} */ - -/* {{{ php_destroy_per_dir_info - */ -static void php_destroy_per_dir_info(php_per_dir_config *conf) -{ - zend_hash_destroy(conf->ini_settings); - php_handler_stack_destroy(&conf->response_handlers); - php_handler_stack_destroy(&conf->auth_handlers); - php_handler_stack_destroy(&conf->access_handlers); - php_handler_stack_destroy(&conf->type_handlers); - php_handler_stack_destroy(&conf->fixup_handlers); - php_handler_stack_destroy(&conf->logger_handlers); - php_handler_stack_destroy(&conf->post_read_handlers); - php_handler_stack_destroy(&conf->headers_handlers); - free(conf->ini_settings); -} -/* }}} */ - -/* {{{ php_create_server - */ -static void *php_create_server(pool *p, char *dummy) -{ - php_per_server_config *conf; - conf = (php_per_server_config *) malloc(sizeof(php_per_server_config)); - register_cleanup(p, (void *) conf, (void (*)(void *)) php_destroy_per_server_info, (void (*)(void *)) php_destroy_per_server_info); - - sapi_stack_init_ex(&conf->requires, 1); - sapi_stack_init_ex(&conf->uri_handlers, 1); - return conf; -} - -/* }}} */ - - -/* {{{ php_create_dir - */ -static void *php_create_dir(pool *p, char *dummy) -{ - php_per_dir_config *conf; - conf = (php_per_dir_config *) malloc(sizeof(php_per_dir_config)); - conf->ini_settings = (HashTable *) malloc(sizeof(HashTable)); - zend_hash_init_ex(conf->ini_settings, 5, NULL, (void (*)(void *)) destroy_per_dir_entry, 1, 0); - sapi_stack_init_ex(&conf->response_handlers, 1); - sapi_stack_init_ex(&conf->headers_handlers, 1); - sapi_stack_init_ex(&conf->auth_handlers, 1); - sapi_stack_init_ex(&conf->access_handlers, 1); - sapi_stack_init_ex(&conf->type_handlers, 1); - sapi_stack_init_ex(&conf->fixup_handlers, 1); - sapi_stack_init_ex(&conf->logger_handlers, 1); - sapi_stack_init_ex(&conf->post_read_handlers, 1); - register_cleanup(p, (void *) conf, (void (*)(void *)) php_destroy_per_dir_info, (void (*)(void *)) php_destroy_per_dir_info); - - return conf; -} - -/* }}} */ - -/* {{{ php_merge_dir - */ -static void *php_merge_dir(pool *p, void *basev, void *addv) -{ - php_per_dir_config *a = (php_per_dir_config *) addv; - php_per_dir_config *b = (php_per_dir_config *) basev; - /* This function *must* return addv, and not modify basev */ - zend_hash_merge_ex((HashTable *) a->ini_settings, (HashTable *) b->ini_settings, (copy_ctor_func_t) copy_per_dir_entry, sizeof(php_per_dir_entry), (merge_checker_func_t) should_overwrite_per_dir_entry, NULL); - a->headers_handlers = (a->headers_handlers.top)?a->headers_handlers:b->headers_handlers; - a->auth_handlers = (a->auth_handlers.top)?a->auth_handlers:b->auth_handlers; - a->access_handlers = (a->access_handlers.top)?a->access_handlers:b->access_handlers; - a->type_handlers = (a->type_handlers.top)?a->type_handlers:b->type_handlers; - a->fixup_handlers = (a->fixup_handlers.top)?a->fixup_handlers:b->fixup_handlers; - a->logger_handlers = (a->logger_handlers.top)?a->logger_handlers:b->logger_handlers; - a->post_read_handlers = (a->post_read_handlers.top)?a->post_read_handlers:b->post_read_handlers; - a->response_handlers = (a->response_handlers.top)?a->response_handlers:b->response_handlers; - return a; -} -/* }}} */ - -/* {{{ php_apache_value_handler_ex - */ -static CONST_PREFIX char *php_apache_value_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode) -{ - php_per_dir_entry per_dir_entry; - - if (!apache_php_initialized) { - apache_php_initialized = 1; -#ifdef ZTS - tsrm_startup(1, 1, 0, NULL); -#endif - sapi_startup(&apache_sapi_module); - php_apache_startup(&apache_sapi_module); - } - per_dir_entry.type = mode; - - if (strcasecmp(arg2, "none") == 0) { - arg2 = ""; - } - - per_dir_entry.key_length = strlen(arg1); - per_dir_entry.value_length = strlen(arg2); - - per_dir_entry.key = (char *) malloc(per_dir_entry.key_length+1); - memcpy(per_dir_entry.key, arg1, per_dir_entry.key_length); - per_dir_entry.key[per_dir_entry.key_length] = 0; - - per_dir_entry.value = (char *) malloc(per_dir_entry.value_length+1); - memcpy(per_dir_entry.value, arg2, per_dir_entry.value_length); - per_dir_entry.value[per_dir_entry.value_length] = 0; - - zend_hash_update(conf, per_dir_entry.key, per_dir_entry.key_length, &per_dir_entry, sizeof(php_per_dir_entry), NULL); - return NULL; -} -/* }}} */ - -static CONST_PREFIX char *php_set_server_handler(server_rec *s, char *arg1, long handler_stage, long handler_type) -{ - php_per_server_config *conf; - php_handler *handler; - handler = (php_handler *) malloc(sizeof(php_handler)); - handler->type = handler_type; - handler->stage = handler_stage; - handler->name = strdup(arg1); - conf = get_module_config(s->module_config, &php5_module); - switch(handler_stage) { - case AP_URI_TRANS: - sapi_stack_push(&conf->uri_handlers, handler); - break; - default: - sapi_stack_push(&conf->requires, handler); - break; - } - return NULL; -} - -static CONST_PREFIX char *php_set_dir_handler(php_per_dir_config *conf, char *arg1, long handler_stage, long handler_type) -{ - php_handler *handler; - handler = (php_handler *) malloc(sizeof(php_handler)); - handler->type = handler_type; - handler->stage = handler_stage; - handler->name = strdup(arg1); - switch(handler_stage) { - case AP_POST_READ: - sapi_stack_push(&conf->post_read_handlers, handler); - break; - case AP_HEADER_PARSE: - sapi_stack_push(&conf->headers_handlers, handler); - break; - case AP_ACCESS_CONTROL: - sapi_stack_push(&conf->access_handlers, handler); - break; - case AP_AUTHENTICATION: - sapi_stack_push(&conf->auth_handlers, handler); - break; - case AP_AUTHORIZATION: - break; - case AP_TYPE_CHECKING: - sapi_stack_push(&conf->type_handlers, handler); - break; - case AP_FIXUP: - sapi_stack_push(&conf->fixup_handlers, handler); - break; - case AP_RESPONSE: - sapi_stack_push(&conf->response_handlers, handler); - break; - case AP_LOGGING: - sapi_stack_push(&conf->logger_handlers, handler); - break; - default: - break; - } - return NULL; -} - -/* {{{ php_set_uri_handler - */ -static CONST_PREFIX char *php_set_uri_handler(cmd_parms *cmd, void *dummy, char *arg1) -{ - return php_set_server_handler(cmd->server, arg1, AP_URI_TRANS, AP_HANDLER_TYPE_FILE); -} -/* }}} */ - -/* {{{ php_set_uri_handler_code */ -static CONST_PREFIX char *php_set_uri_handler_code(cmd_parms *cmd, void *dummy, char *arg1) -{ - return php_set_server_handler(cmd->server, arg1, AP_URI_TRANS, AP_HANDLER_TYPE_METHOD); -} -/* }}} */ - -/* {{{ php_set_header_handler - */ -static CONST_PREFIX char *php_set_header_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1) -{ - return php_set_dir_handler(conf, arg1, AP_HEADER_PARSE, AP_HANDLER_TYPE_FILE); -} -static CONST_PREFIX char *php_set_header_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1) -{ - return php_set_dir_handler(conf, arg1, AP_HEADER_PARSE, AP_HANDLER_TYPE_METHOD); -} -/* }}} */ - -/* {{{ php_set_auth_handler - */ -static CONST_PREFIX char *php_set_auth_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1) -{ - return php_set_dir_handler(conf, arg1, AP_AUTHENTICATION, AP_HANDLER_TYPE_FILE); -} -static CONST_PREFIX char *php_set_auth_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1) -{ - return php_set_dir_handler(conf, arg1, AP_AUTHENTICATION, AP_HANDLER_TYPE_METHOD); -} - -/* }}} */ - -/* {{{ php_set_access_handler - */ -static CONST_PREFIX char *php_set_access_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1) -{ - return php_set_dir_handler(conf, arg1, AP_ACCESS_CONTROL, AP_HANDLER_TYPE_FILE); -} -static CONST_PREFIX char *php_set_access_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1) -{ - return php_set_dir_handler(conf, arg1, AP_ACCESS_CONTROL, AP_HANDLER_TYPE_METHOD); -} - -/* }}} */ - -/* {{{ php_set_type_handler - */ -static CONST_PREFIX char *php_set_type_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1) -{ - return php_set_dir_handler(conf, arg1, AP_TYPE_CHECKING, AP_HANDLER_TYPE_FILE); -} -static CONST_PREFIX char *php_set_type_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1) -{ - return php_set_dir_handler(conf, arg1, AP_TYPE_CHECKING, AP_HANDLER_TYPE_METHOD); -} - -/* }}} */ - -/* {{{ php_set_fixup_handler - */ -static CONST_PREFIX char *php_set_fixup_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1) -{ - return php_set_dir_handler(conf, arg1, AP_FIXUP, AP_HANDLER_TYPE_FILE); -} -static CONST_PREFIX char *php_set_fixup_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1) -{ - return php_set_dir_handler(conf, arg1, AP_FIXUP, AP_HANDLER_TYPE_METHOD); -} -/* }}} */ - -/* {{{ php_set_logger_handler - */ -static CONST_PREFIX char *php_set_logger_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1) -{ - return php_set_dir_handler(conf, arg1, AP_LOGGING, AP_HANDLER_TYPE_FILE); -} -static CONST_PREFIX char *php_set_logger_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1) -{ - return php_set_dir_handler(conf, arg1, AP_LOGGING, AP_HANDLER_TYPE_METHOD); -} - -/* }}} */ - -/* {{{ php_set_post_read_handler - */ -static CONST_PREFIX char *php_set_post_read_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1) -{ - return php_set_dir_handler(conf, arg1, AP_POST_READ, AP_HANDLER_TYPE_FILE); -} -static CONST_PREFIX char *php_set_post_read_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1) -{ - return php_set_dir_handler(conf, arg1, AP_POST_READ, AP_HANDLER_TYPE_METHOD); -} - - -/* }}} */ - -/* {{{ php_set_require - */ - -static CONST_PREFIX char *php_set_require(cmd_parms *cmd, void *dummy, char *arg1) -{ - return php_set_server_handler(cmd->server, arg1, 0, AP_HANDLER_TYPE_FILE); -} -/* }}} */ - -/* {{{ php_set_response_handler - */ -static CONST_PREFIX char *php_set_response_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1) -{ - return php_set_dir_handler(conf, arg1, AP_RESPONSE, AP_HANDLER_TYPE_FILE); -} -static CONST_PREFIX char *php_set_response_handler_code(cmd_parms *cmd, php_per_dir_config *conf, char *arg1) -{ - return php_set_dir_handler(conf, arg1, AP_RESPONSE, AP_HANDLER_TYPE_METHOD); -} -/* }}} */ - -/* {{{ php_apache_value_handler - */ -static CONST_PREFIX char *php_apache_value_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2) -{ - return php_apache_value_handler_ex(cmd, conf->ini_settings, arg1, arg2, PHP_INI_PERDIR); -} -/* }}} */ - -/* {{{ php_apache_admin_value_handler - */ -static CONST_PREFIX char *php_apache_admin_value_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2) -{ - return php_apache_value_handler_ex(cmd, conf->ini_settings, arg1, arg2, PHP_INI_SYSTEM); -} -/* }}} */ - -/* {{{ php_apache_flag_handler_ex - */ -static CONST_PREFIX char *php_apache_flag_handler_ex(cmd_parms *cmd, HashTable *conf, char *arg1, char *arg2, int mode) -{ - char bool_val[2]; - - if (!strcasecmp(arg2, "On")) { - bool_val[0] = '1'; - } else { - bool_val[0] = '0'; - } - bool_val[1] = 0; - - return php_apache_value_handler_ex(cmd, conf, arg1, bool_val, mode); -} -/* }}} */ - -/* {{{ php_apache_flag_handler - */ -static CONST_PREFIX char *php_apache_flag_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2) -{ - return php_apache_flag_handler_ex(cmd, conf->ini_settings, arg1, arg2, PHP_INI_PERDIR); -} -/* }}} */ - -/* {{{ php_apache_admin_flag_handler - */ -static CONST_PREFIX char *php_apache_admin_flag_handler(cmd_parms *cmd, php_per_dir_config *conf, char *arg1, char *arg2) -{ - return php_apache_flag_handler_ex(cmd, conf->ini_settings, arg1, arg2, PHP_INI_SYSTEM); -} -/* }}} */ - -/* {{{ php_apache_phpini_set - */ -static CONST_PREFIX char *php_apache_phpini_set(cmd_parms *cmd, HashTable *conf, char *arg) -{ - if (apache_sapi_module.php_ini_path_override) { - return "Only first PHPINIDir directive honored per configuration tree - subsequent ones ignored"; - } - apache_sapi_module.php_ini_path_override = ap_server_root_relative(cmd->pool, arg); - return NULL; -} -/* }}} */ - -/* {{{ int php_xbithack_handler(request_rec * r) - */ -static int php_xbithack_handler(request_rec * r) -{ - php_per_dir_config *conf; - TSRMLS_FETCH(); - - if (!(r->finfo.st_mode & S_IXUSR)) { - r->allowed |= (1 << METHODS) - 1; - return DECLINED; - } - conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module); - if (conf) { - zend_hash_apply((HashTable *) conf->ini_settings, (apply_func_t) php_apache_alter_ini_entries TSRMLS_CC); - } - if(!AP(xbithack)) { - r->allowed |= (1 << METHODS) - 1; - zend_try { - zend_ini_deactivate(TSRMLS_C); - } zend_end_try(); - return DECLINED; - } - return send_parsed_php(r); -} -/* }}} */ - -/* {{{ apache_php_module_shutdown_wrapper - */ -static void apache_php_module_shutdown_wrapper(void) -{ - apache_php_initialized = 0; - apache_sapi_module.shutdown(&apache_sapi_module); - -#if MODULE_MAGIC_NUMBER >= 19970728 - /* This function is only called on server exit if the apache API - * child_exit handler exists, so shutdown globally - */ - sapi_shutdown(); -#endif - -#ifdef ZTS - tsrm_shutdown(); -#endif -} -/* }}} */ - -#if MODULE_MAGIC_NUMBER >= 19970728 -/* {{{ php_child_exit_handler - */ -static void php_child_exit_handler(server_rec *s, pool *p) -{ -/* apache_php_initialized = 0; */ - apache_sapi_module.shutdown(&apache_sapi_module); - -#ifdef ZTS - tsrm_shutdown(); -#endif -} -/* }}} */ -#endif - -/* {{{ void php_init_handler(server_rec *s, pool *p) - */ -static void php_init_handler(server_rec *s, pool *p) -{ - register_cleanup(p, NULL, (void (*)(void *))apache_php_module_shutdown_wrapper, (void (*)(void *))php_module_shutdown_for_exec); - if (!apache_php_initialized) { - apache_php_initialized = 1; -#ifdef ZTS - tsrm_startup(1, 1, 0, NULL); -#endif - sapi_startup(&apache_sapi_module); - php_apache_startup(&apache_sapi_module); - } -#if MODULE_MAGIC_NUMBER >= 19980527 - { - TSRMLS_FETCH(); - if (PG(expose_php)) { - ap_add_version_component("PHP/" PHP_VERSION); - } - } -#endif -} -/* }}} */ - -static int php_run_hook(php_handler *handler, request_rec *r) -{ - zval *ret = NULL; - php_per_dir_config *conf; - - TSRMLS_FETCH(); - - if(!AP(apache_config_loaded)) { - conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module); - if (conf) - zend_hash_apply((HashTable *)conf->ini_settings, (apply_func_t) php_apache_alter_ini_entries TSRMLS_CC); - AP(apache_config_loaded) = 1; - } - if (!handler->name) { - return DECLINED; - } - php_save_umask(); - if (!AP(setup_env)) { - AP(setup_env) = 1; - add_common_vars(r); - add_cgi_vars(r); - } - SG(server_context) = r; - init_request_info(TSRMLS_C); - apache_php_module_hook(r, handler, &ret TSRMLS_CC); - php_restore_umask(); - kill_timeout(r); - if (ret) { - convert_to_long(ret); - return Z_LVAL_P(ret); - } - return HTTP_INTERNAL_SERVER_ERROR; -} - - -static int php_uri_translation(request_rec *r) -{ - php_per_server_config *conf; - TSRMLS_FETCH(); - AP(current_hook) = AP_URI_TRANS; - conf = (php_per_server_config *) get_module_config(r->server->module_config, &php5_module); - return sapi_stack_apply_with_argument_stop_if_equals(&conf->uri_handlers, - ZEND_STACK_APPLY_BOTTOMUP, - (int (*)(void *element, void *)) php_run_hook, r, OK); -} - -static int php_header_hook(request_rec *r) -{ - php_per_dir_config *conf; - TSRMLS_FETCH(); - AP(current_hook) = AP_HEADER_PARSE; - conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module); - return sapi_stack_apply_with_argument_stop_if_http_error(&conf->headers_handlers, - ZEND_STACK_APPLY_BOTTOMUP, - (int (*)(void *element, void *)) php_run_hook, r); -} - -static int php_auth_hook(request_rec *r) -{ - php_per_dir_config *conf; - TSRMLS_FETCH(); - AP(current_hook) = AP_AUTHENTICATION; - conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module); - return sapi_stack_apply_with_argument_stop_if_equals(&conf->auth_handlers, - ZEND_STACK_APPLY_BOTTOMUP, - (int (*)(void *element, void *)) php_run_hook, r, OK); -} - -static int php_access_hook(request_rec *r) -{ - php_per_dir_config *conf; - int status = DECLINED; - TSRMLS_FETCH(); - AP(current_hook) = AP_ACCESS_CONTROL; - conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module); - status = sapi_stack_apply_with_argument_stop_if_http_error(&conf->access_handlers, - ZEND_STACK_APPLY_BOTTOMUP, - (int (*)(void *element, void *)) php_run_hook, r); - return status; - -} - -static int php_type_hook(request_rec *r) -{ - php_per_dir_config *conf; - TSRMLS_FETCH(); - AP(current_hook) = AP_TYPE_CHECKING; - conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module); - return sapi_stack_apply_with_argument_stop_if_equals(&conf->type_handlers, - ZEND_STACK_APPLY_BOTTOMUP, - (int (*)(void *element, void *)) php_run_hook, - r, OK); -} - -static int php_fixup_hook(request_rec *r) -{ - php_per_dir_config *conf; - TSRMLS_FETCH(); - AP(current_hook) = AP_FIXUP; - conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module); - return sapi_stack_apply_with_argument_stop_if_http_error(&conf->fixup_handlers, - ZEND_STACK_APPLY_BOTTOMUP, - (int (*)(void *element, void *)) php_run_hook, - r); -} - -static int php_logger_hook(request_rec *r) -{ - php_per_dir_config *conf; - TSRMLS_FETCH(); - AP(current_hook) = AP_LOGGING; - conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module); - return sapi_stack_apply_with_argument_stop_if_http_error(&conf->logger_handlers, - ZEND_STACK_APPLY_BOTTOMUP, - (int (*)(void *element, void *)) php_run_hook, - r); -} - -static int php_post_read_hook(request_rec *r) -{ - php_per_dir_config *conf; - php_per_server_config *svr; - TSRMLS_FETCH(); - AP(current_hook) = AP_POST_READ; - svr = get_module_config(r->server->module_config, &php5_module); - if(ap_is_initial_req(r)) { - sapi_stack_apply_with_argument_all(&svr->requires, ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *element, void *)) php_run_hook, r); - } - conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module); - return sapi_stack_apply_with_argument_stop_if_http_error(&conf->post_read_handlers, - ZEND_STACK_APPLY_BOTTOMUP, - (int (*)(void *element, void *)) php_run_hook, r); -} - -static int php_response_handler(request_rec *r) -{ - php_per_dir_config *conf; - TSRMLS_FETCH(); - AP(current_hook) = AP_RESPONSE; - conf = (php_per_dir_config *) get_module_config(r->per_dir_config, &php5_module); - return sapi_stack_apply_with_argument_all(&conf->response_handlers, ZEND_STACK_APPLY_BOTTOMUP, (int (*)(void *element, void *)) php_run_hook, r); -} - -/* {{{ handler_rec php_handlers[] - */ -handler_rec php_handlers[] = -{ - {"application/x-httpd-php", send_parsed_php}, - {"application/x-httpd-php-source", send_parsed_php_source}, - {"text/html", php_xbithack_handler}, - {"php-script", php_response_handler}, - {NULL} -}; -/* }}} */ - -/* {{{ command_rec php_commands[] - */ -command_rec php_commands[] = -{ - {"php_value", php_apache_value_handler, NULL, OR_OPTIONS, TAKE2, "PHP Value Modifier"}, - {"phpUriHandler", php_set_uri_handler, NULL, RSRC_CONF, TAKE1, "PHP Value Modifier"}, - {"phpUriHandlerMethod", php_set_uri_handler_code, NULL, RSRC_CONF, TAKE1, "PHP Value Modifier"}, -#if MODULE_MAGIC_NUMBER >= 19970103 - {"phpHeaderHandler", php_set_header_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"}, - {"phpHeaderHandlerMethod", php_set_header_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"}, -#endif - {"phpAuthHandler", php_set_auth_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"}, - {"phpAuthHandlerMethod", php_set_auth_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"}, - {"phpAccessHandler", php_set_access_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"}, - {"phpAccessHandlerMethod", php_set_access_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"}, - {"phpTypeHandler", php_set_type_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"}, - {"phpTypeHandlerMethod", php_set_type_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"}, - {"phpFixupHandler", php_set_fixup_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"}, - {"phpFixupHandlerMethod", php_set_fixup_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"}, - {"phpLoggerHandler", php_set_logger_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"}, - {"phpLoggerHandlerMethod", php_set_logger_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"}, -#if MODULE_MAGIC_NUMBER >= 19970902 - {"phpPostReadHandler", php_set_post_read_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"}, - {"phpPostReadHandlerMethod", php_set_post_read_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"}, - {"phpRequire", php_set_require, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"}, - {"phpResponseHandler", php_set_response_handler, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"}, - {"phpResponseHandlerMethod", php_set_response_handler_code, NULL, OR_OPTIONS, TAKE1, "PHP Value Modifier"}, -#endif - {"php_flag", php_apache_flag_handler, NULL, OR_OPTIONS, TAKE2, "PHP Flag Modifier"}, - {"php_admin_value", php_apache_admin_value_handler, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "PHP Value Modifier (Admin)"}, - {"php_admin_flag", php_apache_admin_flag_handler, NULL, ACCESS_CONF|RSRC_CONF, TAKE2, "PHP Flag Modifier (Admin)"}, - {"PHPINIDir", php_apache_phpini_set, NULL, RSRC_CONF, TAKE1, "Directory containing the php.ini file"}, - {NULL} -}; -/* }}} */ - -/* {{{ module MODULE_VAR_EXPORT php5_module - */ -module MODULE_VAR_EXPORT php5_module = -{ - STANDARD_MODULE_STUFF, - php_init_handler, /* initializer */ - php_create_dir, /* per-directory config creator */ - php_merge_dir, /* dir merger */ - php_create_server, /* per-server config creator */ - NULL, /* merge server config */ - php_commands, /* command table */ - php_handlers, /* handlers */ - php_uri_translation, /* filename translation */ - NULL, /* check_user_id */ - php_auth_hook, /* check auth */ - php_access_hook, /* check access */ - php_type_hook, /* type_checker */ - php_fixup_hook, /* fixups */ - php_logger_hook /* logger */ -#if MODULE_MAGIC_NUMBER >= 19970103 - , php_header_hook /* header parser */ -#endif -#if MODULE_MAGIC_NUMBER >= 19970719 - , NULL /* child_init */ -#endif -#if MODULE_MAGIC_NUMBER >= 19970728 - , php_child_exit_handler /* child_exit */ -#endif -#if MODULE_MAGIC_NUMBER >= 19970902 - , php_post_read_hook /* post read-request */ -#endif -}; -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/sapi/apache_hooks/mod_php5.exp b/sapi/apache_hooks/mod_php5.exp deleted file mode 100644 index 9ad0f0a0ad..0000000000 --- a/sapi/apache_hooks/mod_php5.exp +++ /dev/null @@ -1 +0,0 @@ -php5_module diff --git a/sapi/apache_hooks/mod_php5.h b/sapi/apache_hooks/mod_php5.h deleted file mode 100644 index d1aad3a7a0..0000000000 --- a/sapi/apache_hooks/mod_php5.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 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: Rasmus Lerdorf <rasmus@php.net> | - +----------------------------------------------------------------------+ - */ -/* $Id$ */ - -#ifndef MOD_PHP5_H -#define MOD_PHP5_H - -#if !defined(WIN32) && !defined(WINNT) -#ifndef MODULE_VAR_EXPORT -#define MODULE_VAR_EXPORT -#endif -#endif - -typedef struct { - long engine; - long last_modified; - long xbithack; - long terminate_child; - long setup_env; - long current_hook; - zend_bool in_request; - zend_bool apache_config_loaded; - zend_bool headers_sent; -} php_apache_info_struct; - -typedef struct _php_handler { - long type; - long stage; - char *name; -} php_handler; - -#define AP_HANDLER_TYPE_FILE 0 -#define AP_HANDLER_TYPE_METHOD 1 - -extern zend_module_entry apache_module_entry; - -#ifdef ZTS -extern int php_apache_info_id; -#define AP(v) TSRMG(php_apache_info_id, php_apache_info_struct *, v) -#else -extern php_apache_info_struct php_apache_info; -#define AP(v) (php_apache_info.v) -#endif - -/* defines for the various stages of the apache request */ -#define AP_WAITING_FOR_REQUEST 0 -#define AP_POST_READ 1 -#define AP_URI_TRANS 2 -#define AP_HEADER_PARSE 3 -#define AP_ACCESS_CONTROL 4 -#define AP_AUTHENTICATION 5 -#define AP_AUTHORIZATION 6 -#define AP_TYPE_CHECKING 7 -#define AP_FIXUP 8 -#define AP_RESPONSE 9 -#define AP_LOGGING 10 -#define AP_CLEANUP 11 - - -/* fix for gcc4 visibility patch */ -#ifndef PHP_WIN32 -# undef MODULE_VAR_EXPORT -# define MODULE_VAR_EXPORT PHPAPI -#endif - -#endif /* MOD_PHP5_H */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - */ diff --git a/sapi/apache_hooks/php.sym b/sapi/apache_hooks/php.sym deleted file mode 100644 index 9ad0f0a0ad..0000000000 --- a/sapi/apache_hooks/php.sym +++ /dev/null @@ -1 +0,0 @@ -php5_module diff --git a/sapi/apache_hooks/php5apache_hooks.dsp b/sapi/apache_hooks/php5apache_hooks.dsp deleted file mode 100755 index cc60f4b3b1..0000000000 --- a/sapi/apache_hooks/php5apache_hooks.dsp +++ /dev/null @@ -1,151 +0,0 @@ -# Microsoft Developer Studio Project File - Name="php5apache_hooks" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=php5apache_hooks - Win32 Release_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 "php5apache_hooks.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 "php5apache_hooks.mak" CFG="php5apache_hooks - Win32 Release_TS"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "php5apache_hooks - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "php5apache_hooks - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "php5apache_hooks - Win32 Release_TS_inline" (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)" == "php5apache_hooks - 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 "APACHEPHP5_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "...\..\include" /I "..\..\win32" /I "..\..\Zend" /I "..\..\regex" /I "..\.." /I "..\..\..\bindlib_w32" /I "..\..\..\php_build\apache\src\include" /I "..\..\main" /I "..\..\TSRM" /D ZEND_DEBUG=0 /D "NDEBUG" /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "_WINDOWS" /D "_USRDLL" /D "APACHEPHP5_EXPORTS" /D "WIN32" /D "_MBCS" /D "APACHE_READDIR_H" /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /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 php5ts.lib ApacheCore.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 /base:"0x60000000" /version:4.0 /dll /machine:I386 /libpath:"..\..\..\php_build\apache\src\corer" /libpath:"..\..\Release_TS" /libpath:"..\..\TSRM\Release_TS" /libpath:"..\..\Zend\Release_TS"
-
-!ELSEIF "$(CFG)" == "php5apache_hooks - Win32 Debug_TS"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Debug_TS"
-# PROP BASE Intermediate_Dir "Debug_TS"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "..\..\Debug_TS"
-# PROP Intermediate_Dir "Debug_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 "APACHEPHP5_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "...\..\include" /I "..\..\win32" /I "..\..\Zend" /I "..\..\regex" /I "..\.." /I "..\..\..\bindlib_w32" /I "..\..\..\php_build\apache\src\include" /I "..\..\main" /I "..\..\TSRM" /D "_DEBUG" /D ZEND_DEBUG=1 /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "_WINDOWS" /D "_USRDLL" /D "APACHEPHP5_EXPORTS" /D "WIN32" /D "_MBCS" /D "APACHE_READDIR_H" /FR /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /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 php5ts_debug.lib ApacheCore.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 /base:"0x60000000" /version:4.0 /dll /incremental:yes /debug /machine:I386 /out:"..\..\Debug_TS/php5apache_hooks.dll" /pdbtype:sept /libpath:"..\..\..\php_build\apache\src\cored" /libpath:"..\..\Debug_TS" /libpath:"..\..\TSRM\Debug_TS" /libpath:"..\..\Zend\Debug_TS"
-
-!ELSEIF "$(CFG)" == "php5apache_hooks - 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 "APACHEPHP5_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "...\..\include" /I "..\..\win32" /I "..\..\Zend" /I "..\..\regex" /I "..\.." /I "..\..\..\bindlib_w32" /I "..\..\..\php_build\apache\src\include" /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 "APACHEPHP5_EXPORTS" /D "WIN32" /D "_MBCS" /D "APACHE_READDIR_H" /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /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 php5ts.lib ApacheCore.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 /version:4.0 /dll /machine:I386 /libpath:"\apache\src\corer" /libpath:"..\..\Release_TS_inline" /libpath:"..\..\TSRM\Release_TS_inline" /libpath:"..\..\Zend\Release_TS_inline"
-
-!ENDIF
-
-# Begin Target
-
-# Name "php5apache_hooks - Win32 Release_TS"
-# Name "php5apache_hooks - Win32 Debug_TS"
-# Name "php5apache_hooks - Win32 Release_TS_inline"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\mod_php5.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\php_apache.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\sapi_apache.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=.\mod_php5.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\php_apache_http.h
-# End Source File
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/sapi/apache_hooks/php_apache.c b/sapi/apache_hooks/php_apache.c deleted file mode 100644 index 4b3febc396..0000000000 --- a/sapi/apache_hooks/php_apache.c +++ /dev/null @@ -1,1972 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> | - | Stig Sæther Bakken <ssb@php.net> | - | David Sklar <sklar@student.net> | - +----------------------------------------------------------------------+ - */ -/* $Id$ */ - -#include "php_apache_http.h" - -#if defined(PHP_WIN32) || defined(NETWARE) -#include "zend.h" -#include "ap_compat.h" -#else -#include <build-defs.h> -#endif - -#ifdef ZTS -int php_apache_info_id; -#else -php_apache_info_struct php_apache_info; -#endif - -#define SECTION(name) PUTS("<H2 align=\"center\">" name "</H2>\n") - -#undef offsetof -#define offsetof(s_type,field) ((size_t)&(((s_type*)0)->field)) - -extern module *top_module; -extern module **ap_loaded_modules; -static int le_apachereq; -static zend_class_entry *apacherequest_class_entry; - -static void apache_table_to_zval(table *, zval *return_value); - -PHP_FUNCTION(virtual); -PHP_FUNCTION(apache_request_headers); -PHP_FUNCTION(apache_response_headers); -PHP_FUNCTION(apachelog); -PHP_FUNCTION(apache_note); -PHP_FUNCTION(apache_lookup_uri); -PHP_FUNCTION(apache_child_terminate); -PHP_FUNCTION(apache_setenv); -PHP_FUNCTION(apache_get_version); -PHP_FUNCTION(apache_get_modules); - -PHP_MINFO_FUNCTION(apache); - -ZEND_BEGIN_ARG_INFO_EX(arginfo_apachehooks_virtual, 0, 0, 1) - ZEND_ARG_INFO(0, filename) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_apachehooks_setenv, 0, 0, 2) - ZEND_ARG_INFO(0, variable) - ZEND_ARG_INFO(0, value) - ZEND_ARG_INFO(0, walk_to_top) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_apachehooks_lookup_uri, 0, 0, 1) - ZEND_ARG_INFO(0, uri) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_apachehooks__void, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_apachehooks_note, 0, 0, 1) - ZEND_ARG_INFO(0, note_name) - ZEND_ARG_INFO(0, note_value) -ZEND_END_ARG_INFO() - -const zend_function_entry apache_functions[] = { - PHP_FE(virtual, arginfo_apachehooks_virtual) - PHP_FE(apache_request_headers, arginfo_apachehooks__void) - PHP_FE(apache_note, arginfo_apachehooks_note) - PHP_FE(apache_lookup_uri, arginfo_apachehooks_lookup_uri) - PHP_FE(apache_child_terminate, arginfo_apachehooks__void) - PHP_FE(apache_setenv, arginfo_apachehooks_setenv) - PHP_FE(apache_response_headers, arginfo_apachehooks__void) - PHP_FE(apache_get_version, arginfo_apachehooks__void) - PHP_FE(apache_get_modules, arginfo_apachehooks__void) - PHP_FALIAS(getallheaders, apache_request_headers, arginfo_apachehooks__void) - {NULL, NULL, NULL} -}; - -/* {{{ php_apache ini entries - */ -PHP_INI_BEGIN() - STD_PHP_INI_ENTRY("xbithack", "0", PHP_INI_ALL, OnUpdateLong, xbithack, php_apache_info_struct, php_apache_info) - STD_PHP_INI_ENTRY("engine", "1", PHP_INI_ALL, OnUpdateLong, engine, php_apache_info_struct, php_apache_info) - STD_PHP_INI_ENTRY("last_modified", "0", PHP_INI_ALL, OnUpdateLong, last_modified, php_apache_info_struct, php_apache_info) - STD_PHP_INI_ENTRY("child_terminate", "0", PHP_INI_ALL, OnUpdateLong, terminate_child, php_apache_info_struct, php_apache_info) -PHP_INI_END() -/* }}} */ - -static void php_apache_globals_ctor(php_apache_info_struct *apache_globals TSRMLS_DC) -{ - apache_globals->in_request = 0; -} - - -#define APREQ_GET_THIS(ZVAL) if (NULL == (ZVAL = getThis())) { \ - php_error(E_WARNING, "%s(): underlying ApacheRequest object missing", \ - get_active_function_name(TSRMLS_C)); \ - RETURN_FALSE; \ - } -#define APREQ_GET_REQUEST(ZVAL, R) APREQ_GET_THIS(ZVAL); \ - R = get_apache_request(ZVAL TSRMLS_CC) - -static void php_apache_request_free(zend_rsrc_list_entry *rsrc TSRMLS_DC) -{ - zval *z = (zval *)rsrc->ptr; -/* fprintf(stderr, "%s() %p\n", __FUNCTION__, z); */ - zval_ptr_dtor(&z); -} - -static request_rec *get_apache_request(zval *z TSRMLS_DC) -{ - request_rec *r; - zval **addr; - - if (NULL == z) { - php_error(E_WARNING, "get_apache_request() invalid wrapper passed"); - return NULL; - } - - if (Z_TYPE_P(z) != IS_OBJECT) { - php_error(E_WARNING, "%s(): wrapper is not an object", get_active_function_name(TSRMLS_C)); - return NULL; - } - - if (zend_hash_index_find(Z_OBJPROP_P(z), 0, (void **)&addr) == FAILURE) { - php_error(E_WARNING, "%s(): underlying object missing", get_active_function_name(TSRMLS_C)); - return NULL; - } - - r = (request_rec *)Z_LVAL_PP(addr); - if (!r) { - php_error(E_WARNING, "%s(): request_rec invalid", get_active_function_name(TSRMLS_C)); - return NULL; - } - - return r; -} - -/* {{{ php_apache_request_new(request_rec *r) - * create a new zval-instance for ApacheRequest that wraps request_rec - */ -zval *php_apache_request_new(request_rec *r) -{ - zval *req; - zval *addr; - - TSRMLS_FETCH(); - - MAKE_STD_ZVAL(addr); - Z_TYPE_P(addr) = IS_LONG; - Z_LVAL_P(addr) = (int) r; - - MAKE_STD_ZVAL(req); - object_init_ex(req, apacherequest_class_entry); - zend_hash_index_update(Z_OBJPROP_P(req), 0, &addr, sizeof(zval *), NULL); - - return req; -} -/* }}} */ - -/* {{{ apache_request_read_string_slot() - */ -static void apache_request_read_string_slot(int offset, INTERNAL_FUNCTION_PARAMETERS) -{ - zval *id; - request_rec *r; - char *s; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - s = *(char **)((char*)r + offset); - - if (s) { - RETURN_STRING(s, 1); - } - - RETURN_EMPTY_STRING(); -} -/* }}} */ - - -/* {{{ apache_request_string_slot() - */ -static void apache_request_string_slot(int offset, INTERNAL_FUNCTION_PARAMETERS) -{ - zval *id; - request_rec *r; - char *old_value, *new_value = NULL; - int new_value_len; - char **target; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &new_value, &new_value_len) == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - target = (char **)((char*)r + offset); - old_value = *target; - - if (new_value) { - *target = ap_pstrdup(r->pool, new_value); - } - - if (old_value) { - RETURN_STRING(old_value, 1); - } - - RETURN_EMPTY_STRING(); -} -/* }}} */ - -/* {{{ apache_request_read_int_slot() - */ -static void apache_request_read_int_slot(int offset, INTERNAL_FUNCTION_PARAMETERS) -{ - zval *id; - request_rec *r; - long l; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - l = *(long *)((char*)r + offset); - - RETURN_LONG(l); -} -/* }}} */ - -/* {{{ apache_request_int_slot() - */ -static void apache_request_int_slot(int offset, INTERNAL_FUNCTION_PARAMETERS) -{ - zval *id; - request_rec *r; - long old_value, new_value; - long *target; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &new_value) == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - target = (long *)((char*)r + offset); - old_value = *target; - - switch (ZEND_NUM_ARGS()) { - case 0: - break; - case 1: - *target = new_value; - break; - default: - WRONG_PARAM_COUNT; - break; - } - - RETURN_LONG(old_value); -} -/* }}} */ - - -/* {{{ access string slots of request rec - */ - -/* {{{ proto string ApacheRequest::filename([string new_filename]) - */ -PHP_FUNCTION(apache_request_filename) -{ - apache_request_string_slot(offsetof(request_rec, filename), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto string ApacheRequest::uri([string new_uri]) - */ -PHP_FUNCTION(apache_request_uri) -{ - apache_request_string_slot(offsetof(request_rec, uri), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto string ApacheRequest::unparsed_uri([string new_unparsed_uri]) - */ -PHP_FUNCTION(apache_request_unparsed_uri) -{ - apache_request_string_slot(offsetof(request_rec, unparsed_uri), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto string ApacheRequest::path_info([string new_path_info]) - */ -PHP_FUNCTION(apache_request_path_info) -{ - apache_request_string_slot(offsetof(request_rec, path_info), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto string ApacheRequest::args([string new_args]) - */ -PHP_FUNCTION(apache_request_args) -{ - apache_request_string_slot(offsetof(request_rec, args), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto string ApacheRequest::boundary() - */ -PHP_FUNCTION(apache_request_boundary) -{ - apache_request_read_string_slot(offsetof(request_rec, boundary), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - - -/* {{{ proto string ApacheRequest::content_type([string new_type]) - */ -PHP_FUNCTION(apache_request_content_type) -{ - apache_request_string_slot(offsetof(request_rec, content_type), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto string ApacheRequest::content_encoding([string new_encoding]) - */ -PHP_FUNCTION(apache_request_content_encoding) -{ - apache_request_string_slot(offsetof(request_rec, content_encoding), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto string ApacheRequest::handler([string new_handler]) - */ -PHP_FUNCTION(apache_request_handler) -{ - apache_request_string_slot(offsetof(request_rec, handler), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto string ApacheRequest::the_request() - */ -PHP_FUNCTION(apache_request_the_request) -{ - apache_request_read_string_slot(offsetof(request_rec, the_request), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto string ApacheRequest::protocol() - */ -PHP_FUNCTION(apache_request_protocol) -{ - apache_request_read_string_slot(offsetof(request_rec, protocol), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto string ApacheRequest::hostname() - */ -PHP_FUNCTION(apache_request_hostname) -{ - apache_request_read_string_slot(offsetof(request_rec, hostname), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto string ApacheRequest::status_line([string new_status_line]) - */ -PHP_FUNCTION(apache_request_status_line) -{ - apache_request_string_slot(offsetof(request_rec, status_line), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto string ApacheRequest::method() - */ -PHP_FUNCTION(apache_request_method) -{ - apache_request_read_string_slot(offsetof(request_rec, method), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* }}} access string slots of request rec */ - -/* {{{ access int slots of request_rec - */ - -/* {{{ proto int ApacheRequest::proto_num() - */ -PHP_FUNCTION(apache_request_proto_num) -{ - apache_request_read_int_slot(offsetof(request_rec, proto_num), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto int ApacheRequest::assbackwards() - */ -PHP_FUNCTION(apache_request_assbackwards) -{ - apache_request_read_int_slot(offsetof(request_rec, assbackwards), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - - -/* {{{ proto int ApacheRequest::proxyreq([int new_proxyreq]) - */ -PHP_FUNCTION(apache_request_proxyreq) -{ - apache_request_int_slot(offsetof(request_rec, proxyreq), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto int ApacheRequest::chunked() - */ -PHP_FUNCTION(apache_request_chunked) -{ - apache_request_read_int_slot(offsetof(request_rec, chunked), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - - -/* {{{ proto int ApacheRequest::header_only() - */ -PHP_FUNCTION(apache_request_header_only) -{ - apache_request_read_int_slot(offsetof(request_rec, header_only), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto int ApacheRequest::request_time() - */ -PHP_FUNCTION(apache_request_request_time) -{ - apache_request_read_int_slot(offsetof(request_rec, request_time), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto int ApacheRequest::status([int new_status]) - */ -PHP_FUNCTION(apache_request_status) -{ - apache_request_int_slot(offsetof(request_rec, status), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto int ApacheRequest::method_number([int method_number]) - */ -PHP_FUNCTION(apache_request_method_number) -{ - apache_request_read_int_slot(offsetof(request_rec, method_number), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto int ApacheRequest::allowed([int allowed]) - */ -PHP_FUNCTION(apache_request_allowed) -{ - apache_request_int_slot(offsetof(request_rec, allowed), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto int ApacheRequest::bytes_sent() - */ -PHP_FUNCTION(apache_request_bytes_sent) -{ - apache_request_read_int_slot(offsetof(request_rec, bytes_sent), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto int ApacheRequest::mtime() - */ -PHP_FUNCTION(apache_request_mtime) -{ - apache_request_read_int_slot(offsetof(request_rec, mtime), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto int ApacheRequest::content_length([int new_content_length]) - */ -PHP_FUNCTION(apache_request_content_length) -{ - zval *id; - long zlen; - request_rec *r; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &zlen) == FAILURE) { - return; - } - - if (ZEND_NUM_ARGS() == 0) { - apache_request_read_int_slot(offsetof(request_rec, clength), INTERNAL_FUNCTION_PARAM_PASSTHRU); - } else { - APREQ_GET_REQUEST(id, r); - - (void)ap_set_content_length(r, zlen); - RETURN_TRUE; - } -} -/* }}} */ - -/* {{{ proto int ApacheRequest::remaining() - */ -PHP_FUNCTION(apache_request_remaining) -{ - apache_request_read_int_slot(offsetof(request_rec, remaining), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto int ApacheRequest::no_cache() - */ -PHP_FUNCTION(apache_request_no_cache) -{ - apache_request_int_slot(offsetof(request_rec, no_cache), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto int ApacheRequest::no_local_copy() - */ -PHP_FUNCTION(apache_request_no_local_copy) -{ - apache_request_int_slot(offsetof(request_rec, no_local_copy), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - -/* {{{ proto int ApacheRequest::read_body() - */ -PHP_FUNCTION(apache_request_read_body) -{ - apache_request_int_slot(offsetof(request_rec, read_body), INTERNAL_FUNCTION_PARAM_PASSTHRU); -} -/* }}} */ - - -/* }}} access int slots of request_rec */ - - -/* {{{ proto array apache_request_headers_in() - * fetch all incoming request headers - */ -PHP_FUNCTION(apache_request_headers_in) -{ - zval *id; - request_rec *r; - - APREQ_GET_REQUEST(id, r); - - apache_table_to_zval(r->headers_in, return_value); -} -/* }}} */ - - -/* {{{ add_header_to_table -*/ -static void add_header_to_table(table *t, INTERNAL_FUNCTION_PARAMETERS) -{ - zval *first = NULL; - zval *second = NULL; - zval **entry, **value; - char *string_key; - uint string_key_len; - ulong num_key; - - zend_bool replace = 0; - HashPosition pos; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|zb", &first, &second, &replace) == FAILURE) { - RETURN_FALSE; - } - - if (Z_TYPE_P(first) == IS_ARRAY) { - switch(ZEND_NUM_ARGS()) { - case 1: - case 3: - zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(first), &pos); - while (zend_hash_get_current_data_ex(Z_ARRVAL_P(first), (void **)&entry, &pos) == SUCCESS) { - switch(zend_hash_get_current_key_ex(Z_ARRVAL_P(first), &string_key, &string_key_len, &num_key, 0, &pos)) { - case HASH_KEY_IS_STRING: - if (zend_hash_find(Z_ARRVAL_P(first), string_key, string_key_len, (void **)&value) == FAILURE) { - zend_hash_move_forward_ex(Z_ARRVAL_P(first), &pos); - continue; - } - if (!value) { - zend_hash_move_forward_ex(Z_ARRVAL_P(first), &pos); - continue; - } - - convert_to_string_ex(value); - if (replace) { - ap_table_set(t, string_key, Z_STRVAL_PP(value)); - } else { - ap_table_merge(t, string_key, Z_STRVAL_PP(value)); - } - break; - case HASH_KEY_IS_LONG: - default: - php_error(E_WARNING, "%s(): Can only add STRING keys to headers!", get_active_function_name(TSRMLS_C)); - break; - } - - zend_hash_move_forward_ex(Z_ARRVAL_P(first), &pos); - } - break; - default: - WRONG_PARAM_COUNT; - break; - } - } else if (Z_TYPE_P(first) == IS_STRING) { - switch(ZEND_NUM_ARGS()) { - case 2: - case 3: - convert_to_string_ex(&second); - if (replace) { - ap_table_set(t, Z_STRVAL_P(first), Z_STRVAL_P(second)); - } else { - ap_table_merge(t, Z_STRVAL_P(first), Z_STRVAL_P(second)); - } - break; - default: - WRONG_PARAM_COUNT; - break; - } - } else { - RETURN_FALSE; - } -} - -/* }}} */ - - -/* {{{ proto array apache_request_headers_out([{string name|array list} [, string value [, bool replace = false]]]) - * fetch all outgoing request headers - */ -PHP_FUNCTION(apache_request_headers_out) -{ - zval *id; - request_rec *r; - - APREQ_GET_REQUEST(id, r); - - if (ZEND_NUM_ARGS() > 0) { - add_header_to_table(r->headers_out, INTERNAL_FUNCTION_PARAM_PASSTHRU); - } - - apache_table_to_zval(r->headers_out, return_value); -} -/* }}} */ - - -/* {{{ proto array apache_request_err_headers_out([{string name|array list} [, string value [, bool replace = false]]]) - * fetch all headers that go out in case of an error or a subrequest - */ -PHP_FUNCTION(apache_request_err_headers_out) -{ - zval *id; - request_rec *r; - - APREQ_GET_REQUEST(id, r); - - if (ZEND_NUM_ARGS() > 0) { - add_header_to_table(r->err_headers_out, INTERNAL_FUNCTION_PARAM_PASSTHRU); - } - - apache_table_to_zval(r->err_headers_out, return_value); -} -/* }}} */ - - -/* {{{ proxy functions for the ap_* functions family - */ - -/* {{{ proto int apache_request_server_port() - */ -PHP_FUNCTION(apache_request_server_port) -{ - zval *id; - request_rec *r; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - RETURN_LONG(ap_get_server_port(r)); -} -/* }}} */ - -/* {{{ proto int apache_request_remote_host([int type]) - */ -PHP_FUNCTION(apache_request_remote_host) -{ - zval *id; - long type = 0; - request_rec *r; - char *res; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &type) == FAILURE) { - return; - } - - if (!type) { - type = REMOTE_NAME; - } - - APREQ_GET_REQUEST(id, r); - - res = (char *)ap_get_remote_host(r->connection, r->per_dir_config, (int)type); - - if (res) { - RETURN_STRING(res, 1); - } - - RETURN_EMPTY_STRING(); -} -/* }}} */ - -/* {{{ proto long apache_request_update_mtime([int dependency_mtime]) - */ -PHP_FUNCTION(apache_request_update_mtime) -{ - zval *id; - request_rec *r; - long mtime = 0; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &mtime) == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - RETURN_LONG(ap_update_mtime(r, (int) mtime)); -} -/* }}} */ - - -/* {{{ proto void apache_request_set_etag() - */ -PHP_FUNCTION(apache_request_set_etag) -{ - zval *id; - request_rec *r; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - ap_set_etag(r); - RETURN_TRUE; -} -/* }}} */ - -/* {{{ proto void apache_request_set_last_modified() - */ -PHP_FUNCTION(apache_request_set_last_modified) -{ - zval *id; - request_rec *r; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - ap_set_last_modified(r); - RETURN_TRUE; -} -/* }}} */ - -/* {{{ proto long apache_request_meets_conditions() - */ -PHP_FUNCTION(apache_request_meets_conditions) -{ - zval *id; - request_rec *r; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - RETURN_LONG(ap_meets_conditions(r)); -} -/* }}} */ - -/* {{{ proto long apache_request_discard_request_body() - */ -PHP_FUNCTION(apache_request_discard_request_body) -{ - zval *id; - request_rec *r; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - RETURN_LONG(ap_discard_request_body(r)); -} -/* }}} */ - -/* {{{ proto long apache_request_satisfies() - */ -PHP_FUNCTION(apache_request_satisfies) -{ - zval *id; - request_rec *r; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - RETURN_LONG(ap_satisfies(r)); -} -/* }}} */ - - -/* {{{ proto bool apache_request_is_initial_req() - */ -PHP_FUNCTION(apache_request_is_initial_req) -{ - zval *id; - request_rec *r; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - RETURN_BOOL(ap_is_initial_req(r)); -} -/* }}} */ - -/* {{{ proto bool apache_request_some_auth_required() - */ -PHP_FUNCTION(apache_request_some_auth_required) -{ - zval *id; - request_rec *r; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - RETURN_BOOL(ap_some_auth_required(r)); -} -/* }}} */ - -/* {{{ proto string apache_request_auth_type() - */ -PHP_FUNCTION(apache_request_auth_type) -{ - zval *id; - request_rec *r; - char *t; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - t = (char *)ap_auth_type(r); - if (!t) { - RETURN_NULL(); - } - - RETURN_STRING(t, 1); -} -/* }}} */ - -/* {{{ proto string apache_request_auth_name() - */ -PHP_FUNCTION(apache_request_auth_name) -{ - zval *id; - request_rec *r; - char *t; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - t = (char *)ap_auth_name(r); - if (!t) { - RETURN_NULL(); - } - - RETURN_STRING(t, 1); -} -/* }}} */ - -/* {{{ proto apache_request_basic_auth_pw() - */ -PHP_FUNCTION(apache_request_basic_auth_pw) -{ - zval *id, *zpw; - request_rec *r; - const char *pw; - long status; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zpw) == FAILURE) { - return; - } - - if (!PZVAL_IS_REF(zpw)) { - zend_error(E_WARNING, "Parameter wasn't passed by reference"); - RETURN_NULL(); - } - - APREQ_GET_REQUEST(id, r); - - pw = NULL; - status = ap_get_basic_auth_pw(r, &pw); - if (status == OK && pw) { - ZVAL_STRING(zpw, (char *)pw, 1); - } else { - ZVAL_NULL(zpw); - } - RETURN_LONG(status); -} -/* }}} */ - - -/* http_protocol.h */ - -PHP_FUNCTION(apache_request_send_http_header) -{ - zval *id; - request_rec *r; - char *type = NULL; - int typelen; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &type, &typelen) == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - if(type) { - r->content_type = pstrdup(r->pool, type); - } - ap_send_http_header(r); - SG(headers_sent) = 1; - AP(headers_sent) = 1; - RETURN_TRUE; -} - -PHP_FUNCTION(apache_request_basic_http_header) -{ - zval *id; - request_rec *r; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - ap_basic_http_header((request_rec *)SG(server_context)); - SG(headers_sent) = 1; - AP(headers_sent) = 1; - RETURN_TRUE; -} - -PHP_FUNCTION(apache_request_send_http_trace) -{ - zval *id; - request_rec *r; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - ap_send_http_trace((request_rec *)SG(server_context)); - SG(headers_sent) = 1; - AP(headers_sent) = 1; - RETURN_TRUE; -} - -PHP_FUNCTION(apache_request_send_http_options) -{ - zval *id; - request_rec *r; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - ap_send_http_options((request_rec *)SG(server_context)); - SG(headers_sent) = 1; - AP(headers_sent) = 1; - RETURN_TRUE; -} - -PHP_FUNCTION(apache_request_send_error_response) -{ - zval *id; - request_rec *r; - long rec = 0; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &rec) == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - ap_send_error_response(r, (int) rec); - RETURN_TRUE; -} - -PHP_FUNCTION(apache_request_set_content_length) -{ - long length; - zval *id; - request_rec *r; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &length) == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - ap_set_content_length(r, length); - RETURN_TRUE; -} - -PHP_FUNCTION(apache_request_set_keepalive) -{ - zval *id; - request_rec *r; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - ap_set_keepalive(r); - RETURN_TRUE; -} - -/* This stuff should use streams or however this is implemented now - -PHP_FUNCTION(apache_request_send_fd) -{ -} - -PHP_FUNCTION(apache_request_send_fd_length) -{ -} -*/ - -/* These are for overriding default output behaviour */ -PHP_FUNCTION(apache_request_rputs) -{ - char *buffer; - int buffer_len; - zval *id; - request_rec *r; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buffer, &buffer_len) == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - ap_rwrite(buffer, buffer_len, (request_rec*)SG(server_context)); -} - -/* This stuff would be useful for custom POST handlers, - which should be supported. Probably by not using - sapi_activate at all inside a phpResponseHandler - and instead using a builtin composed of the below - calls as a apache_read_request_body() and allow - people to custom craft their own. - -PHP_FUNCTION(apache_request_setup_client_block) -{ -} - -PHP_FUNCTION(apache_request_should_client_block) -{ -} - -PHP_FUNCTION(apache_request_get_client_block) -{ -} - -PHP_FUNCTION(apache_request_discard_request_body) -{ -} -*/ - -/* http_log.h */ - -/* {{{ proto boolean apache_request_log_error(string message, [long facility]) - */ -PHP_FUNCTION(apache_request_log_error) -{ - zval *id; - char *z_errstr; - int z_errstr_len; - long facility = APLOG_ERR; - request_rec *r; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &z_errstr, &z_errstr_len, &facility) == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - ap_log_error(APLOG_MARK, (int) facility, r->server, "%s", z_errstr); - RETURN_TRUE; -} -/* }}} */ -/* http_main.h */ - -/* {{{ proto object apache_request_sub_req_lookup_uri(string uri) - Returns sub-request for the specified uri. You would - need to run it yourself with run() -*/ -PHP_FUNCTION(apache_request_sub_req_lookup_uri) -{ - zval *id; - char *file; - int file_len; - request_rec *r, *sub_r; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &file_len) == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - sub_r = ap_sub_req_lookup_uri(file, r); - - if (!sub_r) { - RETURN_FALSE; - } - return_value = php_apache_request_new(sub_r); -} -/* }}} */ - -/* {{{ proto object apache_request_sub_req_lookup_file(string file) - Returns sub-request for the specified file. You would - need to run it yourself with run(). -*/ -PHP_FUNCTION(apache_request_sub_req_lookup_file) -{ - zval *id; - char *file; - int file_len; - request_rec *r, *sub_r; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &file_len) == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - sub_r = ap_sub_req_lookup_file(file, r); - - if (!sub_r) { - RETURN_FALSE; - } - return_value = php_apache_request_new(sub_r); -} -/* }}} */ - -/* {{{ proto object apache_request_sub_req_method_uri(string method, string uri) - Returns sub-request for the specified file. You would - need to run it yourself with run(). -*/ -PHP_FUNCTION(apache_request_sub_req_method_uri) -{ - zval *id; - char *file, *method; - int file_len, method_len; - request_rec *r, *sub_r; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &method, &method_len, &file, &file_len) == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - sub_r = ap_sub_req_method_uri(method, file, r); - - if (!sub_r) { - RETURN_FALSE; - } - return_value = php_apache_request_new(sub_r); -} -/* }}} */ - -/* {{{ proto long apache_request_run() - This is a wrapper for ap_sub_run_req and ap_destory_sub_req. It takes - sub_request, runs it, destroys it, and returns it's status. -*/ -PHP_FUNCTION(apache_request_run) -{ - zval *id; - request_rec *r; - int status; - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - if (!r || ap_is_initial_req(r)) { - RETURN_FALSE; - } - status = ap_run_sub_req(r); - ap_destroy_sub_req(r); - RETURN_LONG(status); -} -/* }}} */ - -PHP_FUNCTION(apache_request_internal_redirect) -{ - zval *id; - char *new_uri; - int new_uri_len; - request_rec *r; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &new_uri, &new_uri_len) == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - ap_internal_redirect(new_uri, r); -} - -PHP_FUNCTION(apache_request_send_header_field) -{ - char *fieldname, *fieldval; - int fieldname_len, fieldval_len; - zval *id; - request_rec *r; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &fieldname, &fieldname_len, &fieldval, &fieldval_len) == FAILURE) { - return; - } - - APREQ_GET_REQUEST(id, r); - - ap_send_header_field(r, fieldname, fieldval); - SG(headers_sent) = 1; - AP(headers_sent) = 1; -} - - - -/* }}} */ - -/* {{{ php_apache_request_class_functions - */ -const static zend_function_entry php_apache_request_class_functions[] = { - /* string slots */ - PHP_FALIAS(args, apache_request_args, NULL) - PHP_FALIAS(boundary, apache_request_boundary, NULL) - PHP_FALIAS(content_encoding, apache_request_content_encoding, NULL) - PHP_FALIAS(content_type, apache_request_content_type, NULL) - PHP_FALIAS(filename, apache_request_filename, NULL) - PHP_FALIAS(handler, apache_request_handler, NULL) - PHP_FALIAS(hostname, apache_request_hostname, NULL) - PHP_FALIAS(method, apache_request_method, NULL) - PHP_FALIAS(path_info, apache_request_path_info, NULL) - PHP_FALIAS(protocol, apache_request_protocol, NULL) - PHP_FALIAS(status_line, apache_request_status_line, NULL) - PHP_FALIAS(the_request, apache_request_the_request, NULL) - PHP_FALIAS(unparsed_uri, apache_request_unparsed_uri, NULL) - PHP_FALIAS(uri, apache_request_uri, NULL) - - /* int slots */ - PHP_FALIAS(allowed, apache_request_allowed, NULL) - PHP_FALIAS(bytes_sent, apache_request_bytes_sent, NULL) - PHP_FALIAS(chunked, apache_request_chunked, NULL) - PHP_FALIAS(content_length, apache_request_content_length, NULL) - PHP_FALIAS(header_only, apache_request_header_only, NULL) - PHP_FALIAS(method_number, apache_request_method_number, NULL) - PHP_FALIAS(mtime, apache_request_mtime, NULL) - PHP_FALIAS(no_cache, apache_request_no_cache, NULL) - PHP_FALIAS(no_local_copy, apache_request_no_local_copy, NULL) - PHP_FALIAS(proto_num, apache_request_proto_num, NULL) - PHP_FALIAS(proxyreq, apache_request_proxyreq, NULL) - PHP_FALIAS(read_body, apache_request_read_body, NULL) - PHP_FALIAS(remaining, apache_request_remaining, NULL) - PHP_FALIAS(request_time, apache_request_request_time, NULL) - PHP_FALIAS(status, apache_request_status, NULL) - - /* tables & arrays */ - PHP_FALIAS(headers_in, apache_request_headers_in, NULL) - PHP_FALIAS(headers_out, apache_request_headers_out, NULL) - PHP_FALIAS(err_headers_out, apache_request_err_headers_out, NULL) - - - /* proxy functions for the ap_* functions family */ -#undef auth_name -#undef auth_type -#undef discard_request_body -#undef is_initial_req -#undef meets_conditions -#undef satisfies -#undef set_etag -#undef set_last_modified -#undef some_auth_required -#undef update_mtime -#undef send_http_header -#undef send_header_field -#undef basic_http_header -#undef send_http_trace -#undef send_http_options -#undef send_error_response -#undef set_content_length -#undef set_keepalive -#undef rputs -#undef log_error -#undef lookup_uri -#undef lookup_file -#undef method_uri -#undef run -#undef internal_redirect - PHP_FALIAS(auth_name, apache_request_auth_name, NULL) - PHP_FALIAS(auth_type, apache_request_auth_type, NULL) - PHP_FALIAS(basic_auth_pw, apache_request_basic_auth_pw, NULL) - PHP_FALIAS(discard_request_body, apache_request_discard_request_body, NULL) - PHP_FALIAS(is_initial_req, apache_request_is_initial_req, NULL) - PHP_FALIAS(meets_conditions, apache_request_meets_conditions, NULL) - PHP_FALIAS(remote_host, apache_request_remote_host, NULL) - PHP_FALIAS(satisfies, apache_request_satisfies, NULL) - PHP_FALIAS(server_port, apache_request_server_port, NULL) - PHP_FALIAS(set_etag, apache_request_set_etag, NULL) - PHP_FALIAS(set_last_modified, apache_request_set_last_modified, NULL) - PHP_FALIAS(some_auth_required, apache_request_some_auth_required, NULL) - PHP_FALIAS(update_mtime, apache_request_update_mtime, NULL) - PHP_FALIAS(send_http_header, apache_request_send_http_header, NULL) - PHP_FALIAS(basic_http_header, apache_request_basic_http_header, NULL) - PHP_FALIAS(send_header_field, apache_request_send_header_field, NULL) - PHP_FALIAS(send_http_trace, apache_request_send_http_trace, NULL) - PHP_FALIAS(send_http_options, apache_request_send_http_trace, NULL) - PHP_FALIAS(send_error_response, apache_request_send_error_response, NULL) - PHP_FALIAS(set_content_length, apache_request_set_content_length, NULL) - PHP_FALIAS(set_keepalive, apache_request_set_keepalive, NULL) - PHP_FALIAS(rputs, apache_request_rputs, NULL) - PHP_FALIAS(log_error, apache_request_log_error, NULL) - PHP_FALIAS(lookup_uri, apache_request_sub_req_lookup_uri, NULL) - PHP_FALIAS(lookup_file, apache_request_sub_req_lookup_file, NULL) - PHP_FALIAS(method_uri, apache_request_sub_req_method_uri, NULL) - PHP_FALIAS(run, apache_request_run, NULL) - PHP_FALIAS(internal_redirect, apache_request_internal_redirect, NULL) - PHP_FE_END -}; -/* }}} */ - - -static PHP_MINIT_FUNCTION(apache) -{ - zend_class_entry ce; - -#ifdef ZTS - ts_allocate_id(&php_apache_info_id, sizeof(php_apache_info_struct), (ts_allocate_ctor) php_apache_globals_ctor, NULL); -#else - php_apache_globals_ctor(&php_apache_info TSRMLS_CC); -#endif - REGISTER_INI_ENTRIES(); - - - le_apachereq = zend_register_list_destructors_ex(php_apache_request_free, NULL, "ApacheRequest", module_number); - INIT_OVERLOADED_CLASS_ENTRY(ce, "ApacheRequest", php_apache_request_class_functions, NULL, NULL, NULL); - apacherequest_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC); - - REGISTER_LONG_CONSTANT("OK", OK, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("DECLINED", DECLINED, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("FORBIDDEN", FORBIDDEN, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("AUTH_REQUIRED", AUTH_REQUIRED, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("DONE", DONE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SERVER_ERROR", SERVER_ERROR, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("REDIRECT", REDIRECT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("BAD_REQUEST", BAD_REQUEST, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("NOT_FOUND", NOT_FOUND, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_CONTINUE", HTTP_CONTINUE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_SWITCHING_PROTOCOLS", HTTP_SWITCHING_PROTOCOLS, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_PROCESSING", HTTP_PROCESSING, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_OK", HTTP_OK, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_CREATED", HTTP_CREATED, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_ACCEPTED", HTTP_ACCEPTED, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_NON_AUTHORITATIVE", HTTP_NON_AUTHORITATIVE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_NO_CONTENT", HTTP_NO_CONTENT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_RESET_CONTENT", HTTP_RESET_CONTENT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_PARTIAL_CONTENT", HTTP_PARTIAL_CONTENT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_MULTI_STATUS", HTTP_MULTI_STATUS, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_MULTIPLE_CHOICES", HTTP_MULTIPLE_CHOICES, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_MOVED_PERMANENTLY", HTTP_MOVED_PERMANENTLY, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_MOVED_TEMPORARILY", HTTP_MOVED_TEMPORARILY, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_SEE_OTHER", HTTP_SEE_OTHER, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_NOT_MODIFIED", HTTP_NOT_MODIFIED, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_USE_PROXY", HTTP_USE_PROXY, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_TEMPORARY_REDIRECT", HTTP_TEMPORARY_REDIRECT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_BAD_REQUEST", HTTP_BAD_REQUEST, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_UNAUTHORIZED", HTTP_UNAUTHORIZED, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_PAYMENT_REQUIRED", HTTP_PAYMENT_REQUIRED, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_FORBIDDEN", HTTP_FORBIDDEN, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_NOT_FOUND", HTTP_NOT_FOUND, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_METHOD_NOT_ALLOWED", HTTP_METHOD_NOT_ALLOWED, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_NOT_ACCEPTABLE", HTTP_NOT_ACCEPTABLE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_PROXY_AUTHENTICATION_REQUIRED", HTTP_PROXY_AUTHENTICATION_REQUIRED, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_REQUEST_TIME_OUT", HTTP_REQUEST_TIME_OUT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_CONFLICT", HTTP_CONFLICT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_GONE", HTTP_GONE, CONST_CS | CONST_PERSISTENT);REGISTER_LONG_CONSTANT("HTTP_LENGTH_REQUIRED", HTTP_LENGTH_REQUIRED, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_PRECONDITION_FAILED", HTTP_PRECONDITION_FAILED, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_REQUEST_ENTITY_TOO_LARGE", HTTP_REQUEST_ENTITY_TOO_LARGE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_REQUEST_URI_TOO_LARGE", HTTP_REQUEST_URI_TOO_LARGE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_UNSUPPORTED_MEDIA_TYPE", HTTP_UNSUPPORTED_MEDIA_TYPE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_RANGE_NOT_SATISFIABLE", HTTP_RANGE_NOT_SATISFIABLE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_EXPECTATION_FAILED", HTTP_EXPECTATION_FAILED, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_UNPROCESSABLE_ENTITY", HTTP_UNPROCESSABLE_ENTITY, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_LOCKED", HTTP_LOCKED, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_FAILED_DEPENDENCY", HTTP_FAILED_DEPENDENCY, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_INTERNAL_SERVER_ERROR", HTTP_INTERNAL_SERVER_ERROR, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_NOT_IMPLEMENTED", HTTP_NOT_IMPLEMENTED, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_BAD_GATEWAY", HTTP_BAD_GATEWAY, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_SERVICE_UNAVAILABLE", HTTP_SERVICE_UNAVAILABLE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_GATEWAY_TIME_OUT", HTTP_GATEWAY_TIME_OUT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_VERSION_NOT_SUPPORTED", HTTP_VERSION_NOT_SUPPORTED, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_VARIANT_ALSO_VARIES", HTTP_VARIANT_ALSO_VARIES, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_INSUFFICIENT_STORAGE", HTTP_INSUFFICIENT_STORAGE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("HTTP_NOT_EXTENDED", HTTP_NOT_EXTENDED, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("APLOG_EMERG", APLOG_EMERG, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("APLOG_ALERT", APLOG_ALERT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("APLOG_CRIT", APLOG_CRIT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("APLOG_ERR", APLOG_ERR, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("APLOG_WARNING", APLOG_WARNING, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("APLOG_NOTICE", APLOG_NOTICE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("APLOG_INFO", APLOG_INFO, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("APLOG_DEBUG", APLOG_DEBUG, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("M_GET", M_GET, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("M_PUT", M_PUT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("M_POST", M_POST, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("M_DELETE", M_DELETE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("M_CONNECT", M_CONNECT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("M_OPTIONS", M_OPTIONS, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("M_TRACE", M_TRACE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("M_PATCH", M_PATCH, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("M_PROPFIND", M_PROPFIND, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("M_PROPPATCH", M_PROPPATCH, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("M_MKCOL", M_MKCOL, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("M_COPY", M_COPY, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("M_MOVE", M_MOVE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("M_LOCK", M_LOCK, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("M_UNLOCK", M_UNLOCK, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("M_INVALID", M_INVALID, CONST_CS | CONST_PERSISTENT); - - /* Possible values for request_rec.read_body (set by handling module): - * REQUEST_NO_BODY Send 413 error if message has any body - * REQUEST_CHUNKED_ERROR Send 411 error if body without Content-Length - * REQUEST_CHUNKED_DECHUNK If chunked, remove the chunks for me. - * REQUEST_CHUNKED_PASS Pass the chunks to me without removal. - */ - REGISTER_LONG_CONSTANT("REQUEST_NO_BODY", REQUEST_NO_BODY, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("REQUEST_CHUNKED_ERROR", REQUEST_CHUNKED_ERROR, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("REQUEST_CHUNKED_DECHUNK", REQUEST_CHUNKED_DECHUNK, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("REQUEST_CHUNKED_PASS", REQUEST_CHUNKED_PASS, CONST_CS | CONST_PERSISTENT); - - /* resolve types for remote_host() */ - REGISTER_LONG_CONSTANT("REMOTE_HOST", REMOTE_HOST, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("REMOTE_NAME", REMOTE_NAME, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("REMOTE_NOLOOKUP", REMOTE_NOLOOKUP, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("REMOTE_DOUBLE_REV", REMOTE_DOUBLE_REV, CONST_CS | CONST_PERSISTENT); - - return SUCCESS; -} - - -static PHP_MSHUTDOWN_FUNCTION(apache) -{ - UNREGISTER_INI_ENTRIES(); - return SUCCESS; -} - -zend_module_entry apache_module_entry = { - STANDARD_MODULE_HEADER, - "apache", - apache_functions, - PHP_MINIT(apache), - PHP_MSHUTDOWN(apache), - NULL, - NULL, - PHP_MINFO(apache), - NO_VERSION_YET, - STANDARD_MODULE_PROPERTIES -}; - -/* {{{ proto bool apache_child_terminate(void) - Terminate apache process after this request */ -PHP_FUNCTION(apache_child_terminate) -{ -#ifndef MULTITHREAD - if (AP(terminate_child)) { - ap_child_terminate( ((request_rec *)SG(server_context)) ); - RETURN_TRUE; - } else { /* tell them to get lost! */ - php_error(E_WARNING, "apache.child_terminate is disabled"); - RETURN_FALSE; - } -#else - php_error(E_WARNING, "apache_child_terminate() is not supported in this build"); - RETURN_FALSE; -#endif -} -/* }}} */ - -/* {{{ proto string apache_note(string note_name [, string note_value]) - Get and set Apache request notes */ -PHP_FUNCTION(apache_note) -{ - char *arg_name, *arg_val = NULL; - int arg_name_len, arg_val_len; - char *note_val; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &arg_name, &arg_name_len, &arg_val, &arg_val_len) == FAILURE) { - return; - } - - note_val = (char *) table_get(((request_rec *)SG(server_context))->notes, arg_name); - - if (arg_val) { - table_set(((request_rec *)SG(server_context))->notes, arg_name, arg_val); - } - - if (!note_val) { - RETURN_FALSE; - } - - RETURN_STRING(note_val, 1); -} -/* }}} */ - -/* {{{ PHP_MINFO_FUNCTION - */ -PHP_MINFO_FUNCTION(apache) -{ - module *modp = NULL; - char output_buf[128]; -#if !defined(WIN32) && !defined(WINNT) - char name[64]; - char modulenames[1024]; - char *p; -#endif - server_rec *serv; - extern char server_root[MAX_STRING_LEN]; - extern uid_t user_id; - extern char *user_name; - extern gid_t group_id; - extern int max_requests_per_child; - - serv = ((request_rec *) SG(server_context))->server; - - - php_info_print_table_start(); - -#ifdef PHP_WIN32 - php_info_print_table_row(1, "Apache for Windows 95/NT"); - php_info_print_table_end(); - php_info_print_table_start(); -#elif defined(NETWARE) - php_info_print_table_row(1, "Apache for NetWare"); - php_info_print_table_end(); - php_info_print_table_start(); -#else - php_info_print_table_row(2, "APACHE_INCLUDE", PHP_APACHE_INCLUDE); - php_info_print_table_row(2, "APACHE_TARGET", PHP_APACHE_TARGET); -#endif - - php_info_print_table_row(2, "Apache Version", SERVER_VERSION); - -#ifdef APACHE_RELEASE - snprintf(output_buf, sizeof(output_buf), "%d", APACHE_RELEASE); - php_info_print_table_row(2, "Apache Release", output_buf); -#endif - snprintf(output_buf, sizeof(output_buf), "%d", MODULE_MAGIC_NUMBER); - php_info_print_table_row(2, "Apache API Version", output_buf); - snprintf(output_buf, sizeof(output_buf), "%s:%u", serv->server_hostname, serv->port); - php_info_print_table_row(2, "Hostname:Port", output_buf); -#if !defined(WIN32) && !defined(WINNT) - snprintf(output_buf, sizeof(output_buf), "%s(%d)/%d", user_name, (int)user_id, (int)group_id); - php_info_print_table_row(2, "User/Group", output_buf); - snprintf(output_buf, sizeof(output_buf), "Per Child: %d - Keep Alive: %s - Max Per Connection: %d", max_requests_per_child, serv->keep_alive ? "on":"off", serv->keep_alive_max); - php_info_print_table_row(2, "Max Requests", output_buf); -#endif - snprintf(output_buf, sizeof(output_buf), "Connection: %d - Keep-Alive: %d", serv->timeout, serv->keep_alive_timeout); - php_info_print_table_row(2, "Timeouts", output_buf); -#if !defined(WIN32) && !defined(WINNT) -/* - This block seems to be working on NetWare; But it seems to be showing - all modules instead of just the loaded ones -*/ - php_info_print_table_row(2, "Server Root", server_root); - - strcpy(modulenames, ""); - for(modp = top_module; modp; modp = modp->next) { - strlcpy(name, modp->name, sizeof(name)); - if ((p = strrchr(name, '.'))) { - *p='\0'; /* Cut off ugly .c extensions on module names */ - } - strlcat(modulenames, name, sizeof(modulenames)); - if (modp->next) { - strlcat(modulenames, ", ", sizeof(modulenames)); - } - } - php_info_print_table_row(2, "Loaded Modules", modulenames); -#endif - - php_info_print_table_end(); - - DISPLAY_INI_ENTRIES(); - - { - register int i; - array_header *arr; - table_entry *elts; - request_rec *r; - - r = ((request_rec *) SG(server_context)); - arr = table_elts(r->subprocess_env); - elts = (table_entry *)arr->elts; - - SECTION("Apache Environment"); - php_info_print_table_start(); - php_info_print_table_header(2, "Variable", "Value"); - for (i=0; i < arr->nelts; i++) { - php_info_print_table_row(2, elts[i].key, elts[i].val); - } - php_info_print_table_end(); - } - - { - array_header *env_arr; - table_entry *env; - int i; - request_rec *r; - - r = ((request_rec *) SG(server_context)); - 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", r->the_request); - env_arr = table_elts(r->headers_in); - env = (table_entry *)env_arr->elts; - for (i = 0; i < env_arr->nelts; ++i) { - if (env[i].key) { - php_info_print_table_row(2, env[i].key, env[i].val); - } - } - php_info_print_table_colspan_header(2, "HTTP Response Headers"); - env_arr = table_elts(r->headers_out); - env = (table_entry *)env_arr->elts; - for(i = 0; i < env_arr->nelts; ++i) { - if (env[i].key) { - php_info_print_table_row(2, env[i].key, env[i].val); - } - } - php_info_print_table_end(); - } -} -/* }}} */ - -/* {{{ proto bool virtual(string filename) - Perform an Apache sub-request */ -/* This function is equivalent to <!--#include virtual...--> - * in mod_include. It does an Apache sub-request. It is useful - * for including CGI scripts or .shtml files, or anything else - * that you'd parse through Apache (for .phtml files, you'd probably - * want to use <?Include>. This only works when PHP is compiled - * as an Apache module, since it uses the Apache API for doing - * sub requests. - */ -PHP_FUNCTION(virtual) -{ - char *filename; - int filename_len; - request_rec *rr = NULL; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { - return; - } - - if (!(rr = sub_req_lookup_uri (filename, ((request_rec *) SG(server_context))))) { - php_error(E_WARNING, "Unable to include '%s' - URI lookup failed", filename); - if (rr) - destroy_sub_req (rr); - RETURN_FALSE; - } - - if (rr->status != 200) { - php_error(E_WARNING, "Unable to include '%s' - error finding URI", filename); - if (rr) - destroy_sub_req (rr); - RETURN_FALSE; - } - - php_output_end_all(TSRMLS_C); - php_header(TSRMLS_C); - - if (run_sub_req(rr)) { - php_error(E_WARNING, "Unable to include '%s' - request execution failed", filename); - if (rr) - destroy_sub_req (rr); - RETURN_FALSE; - } - - if (rr) - destroy_sub_req (rr); - RETURN_TRUE; -} -/* }}} */ - - -/* {{{ apache_table_to_zval(table *, zval *return_value) - Fetch all HTTP request headers */ -static void apache_table_to_zval(table *t, zval *return_value) -{ - array_header *env_arr; - table_entry *tenv; - int i; - - array_init(return_value); - env_arr = table_elts(t); - tenv = (table_entry *)env_arr->elts; - for (i = 0; i < env_arr->nelts; ++i) { - if (!tenv[i].key) { - continue; - } - if (add_assoc_string(return_value, tenv[i].key, (tenv[i].val==NULL) ? "" : tenv[i].val, 1)==FAILURE) { - RETURN_FALSE; - } - } - -} -/* }}} */ - - -/* {{{ proto array getallheaders(void) -*/ -/* Alias for apache_request_headers() */ -/* }}} */ - -/* {{{ proto array apache_request_headers(void) - Fetch all HTTP request headers */ -PHP_FUNCTION(apache_request_headers) -{ - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - apache_table_to_zval(((request_rec *)SG(server_context))->headers_in, return_value); -} -/* }}} */ - -/* {{{ proto array apache_response_headers(void) - Fetch all HTTP response headers */ -PHP_FUNCTION(apache_response_headers) -{ - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - apache_table_to_zval(((request_rec *) SG(server_context))->headers_out, return_value); -} -/* }}} */ - -/* {{{ proto bool apache_setenv(string variable, string value [, bool walk_to_top]) - Set an Apache subprocess_env variable */ -PHP_FUNCTION(apache_setenv) -{ - int var_len, val_len; - zend_bool top=0; - char *var = NULL, *val = NULL; - request_rec *r = (request_rec *) SG(server_context); - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &var, &var_len, &val, &val_len, &top) == FAILURE) { - RETURN_FALSE; - } - - while(top) { - if (r->prev) { - r = r->prev; - } - else break; - } - - ap_table_setn(r->subprocess_env, ap_pstrndup(r->pool, var, var_len), ap_pstrndup(r->pool, val, val_len)); - RETURN_TRUE; -} -/* }}} */ - -/* {{{ proto object apache_lookup_uri(string URI) - Perform a partial request of the given URI to obtain information about it */ -PHP_FUNCTION(apache_lookup_uri) -{ - char *filename; - int filename_len; - request_rec *rr=NULL; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { - return; - } - - if(!(rr = sub_req_lookup_uri(filename, ((request_rec *) SG(server_context))))) { - php_error(E_WARNING, "URI lookup failed", filename); - RETURN_FALSE; - } - - object_init(return_value); - add_property_long(return_value,"status", rr->status); - - if (rr->the_request) { - add_property_string(return_value,"the_request", rr->the_request, 1); - } - if (rr->status_line) { - add_property_string(return_value,"status_line", (char *)rr->status_line, 1); - } - if (rr->method) { - add_property_string(return_value,"method", (char *)rr->method, 1); - } - if (rr->content_type) { - add_property_string(return_value,"content_type", (char *)rr->content_type, 1); - } - if (rr->handler) { - add_property_string(return_value,"handler", (char *)rr->handler, 1); - } - if (rr->uri) { - add_property_string(return_value,"uri", rr->uri, 1); - } - if (rr->filename) { - add_property_string(return_value,"filename", rr->filename, 1); - } - if (rr->path_info) { - add_property_string(return_value,"path_info", rr->path_info, 1); - } - if (rr->args) { - add_property_string(return_value,"args", rr->args, 1); - } - if (rr->boundary) { - add_property_string(return_value,"boundary", rr->boundary, 1); - } - add_property_long(return_value,"no_cache", rr->no_cache); - add_property_long(return_value,"no_local_copy", rr->no_local_copy); - add_property_long(return_value,"allowed", rr->allowed); - add_property_long(return_value,"sent_bodyct", rr->sent_bodyct); - add_property_long(return_value,"bytes_sent", rr->bytes_sent); - add_property_long(return_value,"byterange", rr->byterange); - add_property_long(return_value,"clength", rr->clength); - -#if MODULE_MAGIC_NUMBER >= 19980324 - if (rr->unparsed_uri) { - add_property_string(return_value,"unparsed_uri", rr->unparsed_uri, 1); - } - if(rr->mtime) { - add_property_long(return_value,"mtime", rr->mtime); - } -#endif - if(rr->request_time) { - add_property_long(return_value,"request_time", rr->request_time); - } - - destroy_sub_req(rr); -} -/* }}} */ - - -#if 0 -/* -This function is most likely a bad idea. Just playing with it for now. -*/ - -PHP_FUNCTION(apache_exec_uri) -{ - zval **filename; - request_rec *rr=NULL; - - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &filename) == FAILURE) { - WRONG_PARAM_COUNT; - } - convert_to_string_ex(filename); - - if(!(rr = ap_sub_req_lookup_uri((*filename)->value.str.val, ((request_rec *) SG(server_context))))) { - php_error(E_WARNING, "URI lookup failed", (*filename)->value.str.val); - RETURN_FALSE; - } - RETVAL_LONG(ap_run_sub_req(rr)); - ap_destroy_sub_req(rr); -} -#endif - -/* {{{ proto string apache_get_version(void) - Fetch Apache version */ -PHP_FUNCTION(apache_get_version) -{ - char *apv = (char *) ap_get_server_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); - } - } -} -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/sapi/apache_hooks/php_apache_http.h b/sapi/apache_hooks/php_apache_http.h deleted file mode 100644 index 23cf7fea69..0000000000 --- a/sapi/apache_hooks/php_apache_http.h +++ /dev/null @@ -1,44 +0,0 @@ -#define NO_REGEX_EXTRA_H - -#ifdef WIN32 -#include <winsock2.h> -#include <stddef.h> -#endif - -#ifdef NETWARE -#include <netinet/in.h> -#endif - -#include "zend.h" -#include "zend_stack.h" -#include "ext/ereg/php_regex.h" - -#include "httpd.h" -#include "http_config.h" - -#if MODULE_MAGIC_NUMBER > 19980712 -# include "ap_compat.h" -#else -# if MODULE_MAGIC_NUMBER > 19980324 -# include "compat.h" -# endif -#endif - -#include "http_core.h" -#include "http_main.h" -#include "http_protocol.h" -#include "http_request.h" -#include "http_log.h" -#include "util_script.h" - -#include "php_variables.h" -#include "php_main.h" -#include "php_ini.h" -#include "ext/standard/php_standard.h" - -#include "mod_php5.h" - - -zval *php_apache_request_new(request_rec *r); - -int apache_php_module_hook(request_rec *r, php_handler *handler, zval **ret TSRMLS_DC); diff --git a/sapi/apache_hooks/sapi_apache.c b/sapi/apache_hooks/sapi_apache.c deleted file mode 100644 index f0030a5e22..0000000000 --- a/sapi/apache_hooks/sapi_apache.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Rasmus Lerdorf <rasmus@php.net> | - | (with helpful hints from Dean Gaudet <dgaudet@arctic.org> | - | PHP 4.0 patches by: | - | Zeev Suraski <zeev@zend.com> | - | Stig Bakken <ssb@php.net> | - +----------------------------------------------------------------------+ - */ -/* $Id$ */ - -#include "php_apache_http.h" - -/* {{{ apache_php_module_main - */ -int apache_php_module_main(request_rec *r, int display_source_mode TSRMLS_DC) -{ - zend_file_handle file_handle; - - if (php_request_startup(TSRMLS_C) == FAILURE) { - return FAILURE; - } - /* sending a file handle to another dll is not working - so let zend open it. */ - - if (display_source_mode) { - zend_syntax_highlighter_ini syntax_highlighter_ini; - - php_get_highlight_struct(&syntax_highlighter_ini); - if (highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini TSRMLS_CC)){ - return OK; - } else { - return NOT_FOUND; - } - } else { - file_handle.type = ZEND_HANDLE_FILENAME; - file_handle.handle.fd = 0; - file_handle.filename = SG(request_info).path_translated; - file_handle.opened_path = NULL; - file_handle.free_filename = 0; - (void) php_execute_script(&file_handle TSRMLS_CC); - } - AP(in_request) = 0; - - return (OK); -} -/* }}} */ - -/* {{{ apache_php_module_hook - */ -int apache_php_module_hook(request_rec *r, php_handler *handler, zval **ret TSRMLS_DC) -{ - zend_file_handle file_handle; - zval *req; - char *tmp; - -#if PHP_SIGCHILD - signal(SIGCHLD, sigchld_handler); -#endif - if(AP(current_hook) == AP_RESPONSE) { - if (php_request_startup_for_hook(TSRMLS_C) == FAILURE) - return FAILURE; - } - else { - if (php_request_startup_for_hook(TSRMLS_C) == FAILURE) - return FAILURE; - } - - req = php_apache_request_new(r); - php_register_variable_ex("request", req, PG(http_globals)[TRACK_VARS_SERVER] TSRMLS_CC); - - switch(handler->type) { - case AP_HANDLER_TYPE_FILE: - php_register_variable("PHP_SELF_HOOK", handler->name, PG(http_globals)[TRACK_VARS_SERVER] TSRMLS_CC); - memset(&file_handle, 0, sizeof(file_handle)); - file_handle.type = ZEND_HANDLE_FILENAME; - file_handle.filename = handler->name; - (void) php_execute_simple_script(&file_handle, ret TSRMLS_CC); - break; - case AP_HANDLER_TYPE_METHOD: - if( (tmp = strstr(handler->name, "::")) != NULL && *(tmp+2) != '\0' ) { - zval *class; - zval *method; - *tmp = '\0'; - ALLOC_ZVAL(class); - ZVAL_STRING(class, handler->name, 1); - ALLOC_ZVAL(method); - ZVAL_STRING(method, tmp +2, 1); - *tmp = ':'; - call_user_function_ex(EG(function_table), &class, method, ret, 0, NULL, 0, NULL TSRMLS_CC); - zval_dtor(class); - zval_dtor(method); - } - else { - php_error(E_ERROR, "Unable to call %s - not a Class::Method\n", handler->name); - /* not a class::method */ - } - break; - default: - /* not a valid type */ - assert(0); - break; - } - zval_dtor(req); - AP(in_request) = 0; - - return OK; -} - -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/sapi/caudium/CREDITS b/sapi/caudium/CREDITS deleted file mode 100644 index 45789dbdfe..0000000000 --- a/sapi/caudium/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -Caudium / Roxen -David Hedbor diff --git a/sapi/caudium/README b/sapi/caudium/README deleted file mode 100644 index 86ef65655d..0000000000 --- a/sapi/caudium/README +++ /dev/null @@ -1,16 +0,0 @@ -Embedded Caudium PHP support. It seems to work but isn't tested -much. Due to a design choice it requires _Pike_ threads and a -thread-safe PHP. It doesn't however require _Caudium_ to run in -threaded mode. Due to the design, utilization of multiple processors -should be pretty good. - -It requires a new Pike 7.0 and Caudium. It will not work with -Roxen. Also, with the help of the VIRTUAL_DIR code in PHP, PHP -execution should be very similar to that of mod_php or the cgi -script. - -If you have any questions, please contact me, David Hedbor -(neotron@php.net or neotron@caudium.net). For more information on -Caudium, see http://caudium.net/ and http://caudium.org/. - - diff --git a/sapi/caudium/TODO b/sapi/caudium/TODO deleted file mode 100644 index b8217c5934..0000000000 --- a/sapi/caudium/TODO +++ /dev/null @@ -1,30 +0,0 @@ -TODO: - -- per-virtual-server configuration -- configurable limit of number of concurrent PHP executions -- fix setting of auth info. - -FIXED: -+ => fixed -- => not fixed and no fix planned -? => Maybe fixed, maybe not. - -+ Allow multiple headers - This is now fixed. -+ fix backtraces - Uses th_farm, thus problem is fixed -+ exit in PHP exits Caudium - Name conflict with do_exit in Pike and PHP. Reported to both teams. -+ POST newline added? - Was a Caudium bug. -+ use th_farm - Yeppers. Works great. -- change cwd in single threaded mode - There will be no single threaded mode support. The Caudium module - will requite PHP ZTS and Pike threads to run. Single threaded PHP - is rather uninteresting anyway. -? Recursive mutex lock problem: - Dunno if this is fixed. Major rewrite so it would have to be - retested. - - diff --git a/sapi/caudium/caudium.c b/sapi/caudium/caudium.c deleted file mode 100644 index 1113f2c3c3..0000000000 --- a/sapi/caudium/caudium.c +++ /dev/null @@ -1,784 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 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: David Hedbor <neotron@php.net> | - | Based on aolserver SAPI by Sascha Schumann <sascha@schumann.cx> | - +----------------------------------------------------------------------+ - */ - -/* $Id$ */ - -#include "php.h" -#ifdef HAVE_CAUDIUM - -#include "php_ini.h" -#include "php_globals.h" -#include "SAPI.h" -#include "php_main.h" -#include "ext/standard/info.h" - -#include "php_version.h" - -/* Pike Include Files - * - * conflicts with pike avoided by only using long names. Requires a new - * Pike 0.7 since it was implemented for this interface only. - * - */ -#define NO_PIKE_SHORTHAND - -/* Ok, we are now using Pike level threads to handle PHP5 since - * the nice th_farm threads aren't working on Linux with glibc 2.2 - * (why this is I don't know). - */ -#define USE_PIKE_LEVEL_THREADS - -#include <fdlib.h> -#include <program.h> -#include <pike_types.h> -#include <interpret.h> -#include <module_support.h> -#include <array.h> -#include <backend.h> -#include <stralloc.h> -#include <mapping.h> -#include <object.h> -#include <threads.h> -#include <builtin_functions.h> -#include <operators.h> -#include <version.h> - -#if (PIKE_MAJOR_VERSION == 7 && PIKE_MINOR_VERSION == 1 && PIKE_BUILD_VERSION >= 12) || PIKE_MAJOR_VERSION > 7 || (PIKE_MAJOR_VERSION == 7 && PIKE_MINOR_VERSION > 1) -# include "pike_error.h" -#else -# include "error.h" -# ifndef Pike_error -# define Pike_error error -# endif -#endif - -/* Pike 7.x and newer */ -#define MY_MAPPING_LOOP(md, COUNT, KEY) \ - for(COUNT=0;COUNT < md->data->hashsize; COUNT++ ) \ - for(KEY=md->data->hash[COUNT];KEY;KEY=KEY->next) - -#ifndef ZTS -/* Need thread safety */ -#error You need to compile PHP with threads. -#endif - -#ifndef PIKE_THREADS -#error The PHP5 module requires that your Pike has thread support. -#endif - -#undef HIDE_GLOBAL_VARIABLES -#undef REVEAL_GLOBAL_VARIABLES -#define HIDE_GLOBAL_VARIABLES() -#define REVEAL_GLOBAL_VARIABLES() - -/* php_caudium_request is per-request object storage */ - -typedef struct -{ - struct mapping *request_data; - struct object *my_fd_obj; - struct svalue done_cb; - struct pike_string *filename; - int my_fd; - int written; - TSRMLS_D; -} php_caudium_request; - - -void pike_module_init(void); -void pike_module_exit(void); -static void free_struct(TSRMLS_D); -void f_php_caudium_request_handler(INT32 args); - -/* Defines to get to the data supplied when the script is started. */ - -/* Per thread storage area id... */ -static int caudium_globals_id; - -#define GET_THIS() php_caudium_request *_request = ts_resource(caudium_globals_id) -#define THIS _request -#define PTHIS ((php_caudium_request *)(Pike_fp->current_storage)) -/* File descriptor integer. Used to write directly to the FD without - * passing Pike - */ -#define MY_FD (THIS->my_fd) - -/* FD object. Really a PHPScript object from Pike which implements a couple - * of functions to handle headers, writing and buffering. - */ -#define MY_FD_OBJ ((struct object *)(THIS->my_fd_obj)) - -/* Mapping with data supplied from the calling Caudium module. Contains - * a mapping with headers, an FD object etc. - */ -#define REQUEST_DATA ((struct mapping *)(THIS->request_data)) - -extern int fd_from_object(struct object *o); -static unsigned char caudium_php_initialized; - -#ifndef mt_lock_interpreter -#define mt_lock_interpreter() mt_lock(&interpreter_lock); -#define mt_unlock_interpreter() mt_unlock(&interpreter_lock); -#endif - - -/* This allows calling of pike functions from the PHP callbacks, - * which requires the Pike interpreter to be locked. - */ -#define THREAD_SAFE_RUN(COMMAND, what) do {\ - struct thread_state *state;\ - if((state = thread_state_for_id(th_self()))!=NULL) {\ - if(!state->swapped) {\ - COMMAND;\ - } else {\ - mt_lock_interpreter();\ - SWAP_IN_THREAD(state);\ - COMMAND;\ - SWAP_OUT_THREAD(state);\ - mt_unlock_interpreter();\ - }\ - }\ -} while(0) - - - -/* Low level header lookup. Basically looks for the named header in the mapping - * headers in the supplied options mapping. - */ - -INLINE static struct svalue *lookup_header(char *headername) -{ - struct svalue *headers, *value; - struct pike_string *sind; - GET_THIS(); - sind = make_shared_string("env"); - headers = low_mapping_string_lookup(REQUEST_DATA, sind); - free_string(sind); - if(!headers || headers->type != PIKE_T_MAPPING) return NULL; - sind = make_shared_string(headername); - value = low_mapping_string_lookup(headers->u.mapping, sind); - free_string(sind); - if(!value) return NULL; - return value; -} - -/* Lookup a header in the mapping and return the value as a string, or - * return the default if it's missing - */ -INLINE static char *lookup_string_header(char *headername, char *default_value) -{ - struct svalue *head = NULL; - THREAD_SAFE_RUN(head = lookup_header(headername), "header lookup"); - if(!head || head->type != PIKE_T_STRING) - return default_value; - return head->u.string->str; -} - -/* Lookup a header in the mapping and return the value as if it's an integer - * and otherwise return the default. - */ -INLINE static int lookup_integer_header(char *headername, int default_value) -{ - struct svalue *head = NULL; - THREAD_SAFE_RUN(head = lookup_header(headername), "header lookup"); - if(!head || head->type != PIKE_T_INT) - return default_value; - return head->u.integer; -} - -/* - * php_caudium_low_ub_write() writes data to the client connection. Might be - * rewritten to do more direct IO to save CPU and the need to lock the - * interpreter for better threading. - */ - -INLINE static int -php_caudium_low_ub_write(const char *str, uint str_length TSRMLS_DC) { - int sent_bytes = 0; - struct pike_string *to_write = NULL; - GET_THIS(); - if(!MY_FD_OBJ->prog) { - PG(connection_status) = PHP_CONNECTION_ABORTED; - zend_bailout(); - return -1; - } - to_write = make_shared_binary_string(str, str_length); - push_string(to_write); - safe_apply(MY_FD_OBJ, "write", 1); - if(Pike_sp[-1].type == PIKE_T_INT) - sent_bytes = Pike_sp[-1].u.integer; - pop_stack(); - if(sent_bytes != str_length) { - /* This means the connection is closed. Dead. Gone. *sniff* */ - PG(connection_status) = PHP_CONNECTION_ABORTED; - zend_bailout(); - } - return sent_bytes; -} - -/* - * php_caudium_sapi_ub_write() calls php_caudium_low_ub_write in a Pike thread - * safe manner or writes directly to the output FD if RXML post-parsing is - * disabled. - */ - -static int -php_caudium_sapi_ub_write(const char *str, uint str_length TSRMLS_DC) -{ - GET_THIS(); - int sent_bytes = 0, fd = MY_FD; - if(fd) - { - for(sent_bytes=0;sent_bytes < str_length;) - { - int written; - written = fd_write(fd, str + sent_bytes, str_length - sent_bytes); - if(written < 0) - { - switch(errno) - { - default: - /* This means the connection is closed. Dead. Gone. *sniff* */ - PG(connection_status) = PHP_CONNECTION_ABORTED; - zend_bailout(); - THIS->written += sent_bytes; - return sent_bytes; - case EINTR: - case EWOULDBLOCK: - continue; - } - } else { - sent_bytes += written; - } - } - THIS->written += sent_bytes; - } else { - THREAD_SAFE_RUN(sent_bytes = php_caudium_low_ub_write(str, str_length TSRMLS_CC), - "write"); - } - return sent_bytes; -} - -/* php_caudium_set_header() sets a header in the header mapping. Called in a - * thread safe manner from php_caudium_sapi_header_handler. - */ -INLINE static void -php_caudium_set_header(char *header_name, char *value, char *p) -{ - struct svalue hsval; - struct pike_string *hval, *ind, *hind; - struct mapping *headermap; - struct svalue *s_headermap, *soldval; - int vallen; - GET_THIS(); - /* hval = make_shared_string(value); */ - ind = make_shared_string(" _headers"); - hind = make_shared_binary_string(header_name, - (int)(p - header_name)); - - s_headermap = low_mapping_string_lookup(REQUEST_DATA, ind); - if(!s_headermap || s_headermap->type != PIKE_T_MAPPING) - { - struct svalue mappie; - mappie.type = PIKE_T_MAPPING; - headermap = allocate_mapping(1); - mappie.u.mapping = headermap; - mapping_string_insert(REQUEST_DATA, ind, &mappie); - free_mapping(headermap); - hval = make_shared_string(value); - } else { - headermap = s_headermap->u.mapping; - soldval = low_mapping_string_lookup(headermap, hind); - vallen = strlen(value); - if(soldval != NULL && - soldval->type == PIKE_T_STRING && - soldval->u.string->size_shift == 0) { - /* Existing, valid header. Prepend.*/ - hval = begin_shared_string(soldval->u.string->len + 1 + vallen); - MEMCPY(hval->str, soldval->u.string->str, soldval->u.string->len); - STR0(hval)[soldval->u.string->len] = '\0'; - MEMCPY(hval->str+soldval->u.string->len+1, value, vallen); - hval = end_shared_string(hval); - } else { - hval = make_shared_string(value); - } - } - hsval.type = PIKE_T_STRING; - hsval.u.string = hval; - - mapping_string_insert(headermap, hind, &hsval); - - free_string(hval); - free_string(ind); - free_string(hind); -} - -/* - * php_caudium_sapi_header_handler() sets a HTTP reply header to be - * sent to the client. - */ -static int -php_caudium_sapi_header_handler(sapi_header_struct *sapi_header, - sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - char *header_name, *header_content, *p; - header_name = sapi_header->header; - header_content = p = strchr(header_name, ':'); - - if(p) { - do { - header_content++; - } while(*header_content == ' '); - THREAD_SAFE_RUN(php_caudium_set_header(header_name, header_content, p), "header handler"); - } - sapi_free_header(sapi_header); - return 0; -} - -/* - * php_caudium_sapi_send_headers() flushes the headers to the client. - * Called before real content is sent by PHP. - */ - -INLINE static int -php_caudium_low_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - struct pike_string *ind; - struct svalue *s_headermap; - GET_THIS(); - if(!MY_FD_OBJ->prog) { - PG(connection_status) = PHP_CONNECTION_ABORTED; - zend_bailout(); - return SAPI_HEADER_SEND_FAILED; - } - ind = make_shared_string(" _headers"); - s_headermap = low_mapping_string_lookup(REQUEST_DATA, ind); - free_string(ind); - - push_int(SG(sapi_headers).http_response_code); - if(s_headermap && s_headermap->type == PIKE_T_MAPPING) - ref_push_mapping(s_headermap->u.mapping); - else - push_int(0); - safe_apply(MY_FD_OBJ, "send_headers", 2); - pop_stack(); - - return SAPI_HEADER_SENT_SUCCESSFULLY; -} - -static int -php_caudium_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - int res = 0; - THREAD_SAFE_RUN(res = php_caudium_low_send_headers(sapi_headers TSRMLS_CC), "send headers"); - return res; -} - -/* - * php_caudium_sapi_read_post() reads a specified number of bytes from - * the client. Used for POST/PUT requests. - */ - -INLINE static int php_caudium_low_read_post(char *buf, uint count_bytes) -{ - uint total_read = 0; - GET_THIS(); - TSRMLS_FETCH(); - - if(!MY_FD_OBJ->prog) - { - PG(connection_status) = PHP_CONNECTION_ABORTED; - zend_bailout(); - return -1; - } - push_int(count_bytes); - safe_apply(MY_FD_OBJ, "read_post", 1); - if(Pike_sp[-1].type == PIKE_T_STRING) { - MEMCPY(buf, Pike_sp[-1].u.string->str, - (total_read = Pike_sp[-1].u.string->len)); - buf[total_read] = '\0'; - } else - total_read = 0; - pop_stack(); - return total_read; -} - -static int -php_caudium_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC) -{ - uint total_read = 0; - THREAD_SAFE_RUN(total_read = php_caudium_low_read_post(buf, count_bytes), "read post"); - return total_read; -} - -/* - * php_caudium_sapi_read_cookies() returns the Cookie header from - * the HTTP request header - */ - -static char * -php_caudium_sapi_read_cookies(TSRMLS_D) -{ - char *cookies; - cookies = lookup_string_header("HTTP_COOKIE", NULL); - return cookies; -} - -static void php_info_caudium(ZEND_MODULE_INFO_FUNC_ARGS) -{ - /* char buf[512]; */ - php_info_print_table_start(); - php_info_print_table_row(2, "SAPI module version", "$Id$"); - /* php_info_print_table_row(2, "Build date", Ns_InfoBuildDate()); - php_info_print_table_row(2, "Config file path", Ns_InfoConfigFile()); - php_info_print_table_row(2, "Error Log path", Ns_InfoErrorLog()); - php_info_print_table_row(2, "Installation path", Ns_InfoHomePath()); - php_info_print_table_row(2, "Hostname of server", Ns_InfoHostname()); - php_info_print_table_row(2, "Source code label", Ns_InfoLabel()); - php_info_print_table_row(2, "Server platform", Ns_InfoPlatform()); - snprintf(buf, 511, "%s/%s", Ns_InfoServerName(), Ns_InfoServerVersion()); - php_info_print_table_row(2, "Server version", buf); - snprintf(buf, 511, "%d day(s), %02d:%02d:%02d", - uptime / 86400, - (uptime / 3600) % 24, - (uptime / 60) % 60, - uptime % 60); - php_info_print_table_row(2, "Server uptime", buf); - */ - php_info_print_table_end(); -} - -static zend_module_entry php_caudium_module = { - STANDARD_MODULE_HEADER, - "Caudium", - NULL, - NULL, - NULL, - NULL, - NULL, - php_info_caudium, - NULL, - STANDARD_MODULE_PROPERTIES -}; - - -INLINE static void low_sapi_caudium_register_variables(zval *track_vars_array TSRMLS_DC) -{ - int i; - struct keypair *k; - struct svalue *headers; - struct pike_string *sind; - struct svalue *ind; - struct svalue *val; - GET_THIS(); - php_register_variable("PHP_SELF", SG(request_info).request_uri, - track_vars_array TSRMLS_CC); - php_register_variable("GATEWAY_INTERFACE", "CGI/1.1", - track_vars_array TSRMLS_CC); - php_register_variable("REQUEST_METHOD", - (char *) SG(request_info).request_method, - track_vars_array TSRMLS_CC); - php_register_variable("REQUEST_URI", SG(request_info).request_uri, - track_vars_array TSRMLS_CC); - php_register_variable("PATH_TRANSLATED", SG(request_info).path_translated, - track_vars_array TSRMLS_CC); - - sind = make_shared_string("env"); - headers = low_mapping_string_lookup(REQUEST_DATA, sind); - free_string(sind); - if(headers && headers->type == PIKE_T_MAPPING) { - MY_MAPPING_LOOP(headers->u.mapping, i, k) { - ind = &k->ind; - val = &k->val; - if(ind && ind->type == PIKE_T_STRING && - val && val->type == PIKE_T_STRING) { - php_register_variable(ind->u.string->str, val->u.string->str, - track_vars_array TSRMLS_CC ); - } - } - } -} - -static void sapi_caudium_register_variables(zval *track_vars_array TSRMLS_DC) -{ - THREAD_SAFE_RUN(low_sapi_caudium_register_variables(track_vars_array TSRMLS_CC), "register_variables"); -} - - -static int php_caudium_startup(sapi_module_struct *sapi_module) -{ - if (php_module_startup(sapi_module, &php_caudium_module, 1)==FAILURE) { - return FAILURE; - } - return SUCCESS; -} - - -/* this structure is static (as in "it does not change") */ -static sapi_module_struct caudium_sapi_module = { - "caudium", - "Caudium", - php_caudium_startup, /* startup */ - php_module_shutdown_wrapper, /* shutdown */ - NULL, /* activate */ - NULL, /* deactivate */ - php_caudium_sapi_ub_write, /* unbuffered write */ - NULL, /* flush */ - NULL, /* get uid */ - NULL, /* getenv */ - php_error, /* error handler */ - php_caudium_sapi_header_handler, /* header handler */ - php_caudium_sapi_send_headers, /* send headers handler */ - NULL, /* send header handler */ - php_caudium_sapi_read_post, /* read POST data */ - php_caudium_sapi_read_cookies, /* read cookies */ - sapi_caudium_register_variables, /* register server variables */ - NULL, /* Log message */ - NULL, /* Get request time */ - NULL, /* Child terminate */ - - STANDARD_SAPI_MODULE_PROPERTIES -}; - -/* - * php_caudium_module_main() is called by the per-request handler and - * "executes" the script - */ - -static void php_caudium_module_main(php_caudium_request *ureq) -{ - int res; - zend_file_handle file_handle; -#ifndef USE_PIKE_LEVEL_THREADS - struct thread_state *state; - extern struct program *thread_id_prog; -#endif - TSRMLS_FETCH(); - GET_THIS(); - THIS->filename = ureq->filename; - THIS->done_cb = ureq->done_cb; - THIS->my_fd_obj = ureq->my_fd_obj; - THIS->my_fd = ureq->my_fd; - THIS->request_data = ureq->request_data; - free(ureq); - -#ifndef USE_PIKE_LEVEL_THREADS - mt_lock_interpreter(); - init_interpreter(); -#if PIKE_MAJOR_VERSION == 7 && PIKE_MINOR_VERSION < 1 - thread_id = low_clone(thread_id_prog); - state = OBJ2THREAD(thread_id); - Pike_stack_top=((char *)&state)+ (thread_stack_size-16384) * STACK_DIRECTION; - recoveries = NULL; - call_c_initializers(thread_id); - OBJ2THREAD(thread_id)->id=th_self(); - num_threads++; - thread_table_insert(thread_id); - state->status=THREAD_RUNNING; -#else - Pike_interpreter.thread_id = low_clone(thread_id_prog); - state = OBJ2THREAD(Pike_interpreter.thread_id); - Pike_interpreter.stack_top=((char *)&state)+ (thread_stack_size-16384) * STACK_DIRECTION; - Pike_interpreter.recoveries = NULL; - call_c_initializers(Pike_interpreter.thread_id); - state->id=th_self(); - /* SWAP_OUT_THREAD(OBJ2THREAD(Pike_interpreter.thread_id)); */ - num_threads++; - thread_table_insert(Pike_interpreter.thread_id); - state->status=THREAD_RUNNING; -#endif - state->swapped = 0; -#endif - SG(request_info).query_string = lookup_string_header("QUERY_STRING", 0); - SG(server_context) = (void *)1; /* avoid server_context == NULL */ - - /* path_translated is apparently the absolute path to the file, not - the translated PATH_INFO - */ - SG(request_info).path_translated = - lookup_string_header("SCRIPT_FILENAME", NULL); - SG(request_info).request_uri = lookup_string_header("DOCUMENT_URI", NULL); - if(!SG(request_info).request_uri) - SG(request_info).request_uri = lookup_string_header("SCRIPT_NAME", NULL); - SG(request_info).request_method = lookup_string_header("REQUEST_METHOD", "GET"); - SG(request_info).content_length = lookup_integer_header("HTTP_CONTENT_LENGTH", 0); - SG(request_info).content_type = lookup_string_header("HTTP_CONTENT_TYPE", NULL); - SG(sapi_headers).http_response_code = 200; - if (!strcmp(SG(request_info).request_method, "HEAD")) { - SG(request_info).headers_only = 1; - } else { - SG(request_info).headers_only = 0; - } - - /* Let PHP5 handle the deconding of the AUTH */ - php_handle_auth_data(lookup_string_header("HTTP_AUTHORIZATION", NULL), TSRMLS_C); - /* Swap out this thread and release the interpreter lock to allow - * Pike threads to run. We wait since the above would otherwise require - * a lot of unlock/lock. - */ -#ifndef USE_PIKE_LEVEL_THREADS - SWAP_OUT_THREAD(state); - mt_unlock_interpreter(); -#else - THREADS_ALLOW(); -#endif - - file_handle.type = ZEND_HANDLE_FILENAME; - file_handle.filename = THIS->filename->str; - file_handle.opened_path = NULL; - file_handle.free_filename = 0; - - THIS->written = 0; - res = php_request_startup(TSRMLS_C); - - if(res == FAILURE) { - THREAD_SAFE_RUN({ - apply_svalue(&THIS->done_cb, 0); - pop_stack(); - free_struct(TSRMLS_C); - }, "Negative run response"); - } else { - php_execute_script(&file_handle TSRMLS_CC); - php_request_shutdown(NULL); - THREAD_SAFE_RUN({ - push_int(THIS->written); - apply_svalue(&THIS->done_cb, 1); - pop_stack(); - free_struct(TSRMLS_C); - }, "positive run response"); - } - -#ifndef USE_PIKE_LEVEL_THREADS - mt_lock_interpreter(); - SWAP_IN_THREAD(state); -#if PIKE_MAJOR_VERSION == 7 && PIKE_MINOR_VERSION < 1 - state->status=THREAD_EXITED; - co_signal(& state->status_change); - thread_table_delete(thread_id); - free_object(thread_id); - thread_id=NULL; -#else - state->status=THREAD_EXITED; - co_signal(& state->status_change); - thread_table_delete(Pike_interpreter.thread_id); - free_object(Pike_interpreter.thread_id); - Pike_interpreter.thread_id=NULL; -#endif - cleanup_interpret(); - num_threads--; - mt_unlock_interpreter(); -#else - THREADS_DISALLOW(); -#endif -} - -/* - * The php_caudium_request_handler() is called per request and handles - * everything for one request. - */ - -void f_php_caudium_request_handler(INT32 args) -{ - struct object *my_fd_obj; - struct mapping *request_data; - struct svalue *done_callback; - struct pike_string *script; - struct svalue *raw_fd; - struct pike_string *ind; - php_caudium_request *_request; - THIS = malloc(sizeof(php_caudium_request)); - if(THIS == NULL) - Pike_error("Out of memory."); - - get_all_args("PHP5.Interpreter->run", args, "%S%m%O%*", &script, - &request_data, &my_fd_obj, &done_callback); - if(done_callback->type != PIKE_T_FUNCTION) - Pike_error("PHP5.Interpreter->run: Bad argument 4, expected function.\n"); - add_ref(request_data); - add_ref(my_fd_obj); - add_ref(script); - - THIS->request_data = request_data; - THIS->my_fd_obj = my_fd_obj; - THIS->filename = script; - assign_svalue_no_free(&THIS->done_cb, done_callback); - - ind = make_shared_binary_string("my_fd", 5); - raw_fd = low_mapping_string_lookup(THIS->request_data, ind); - if(raw_fd && raw_fd->type == PIKE_T_OBJECT) - { - int fd = fd_from_object(raw_fd->u.object); - if(fd == -1) - THIS->my_fd = 0; /* Don't send directly to this FD... */ - else - THIS->my_fd = fd; - } else - THIS->my_fd = 0; -#ifdef USE_PIKE_LEVEL_THREADS - php_caudium_module_main(THIS); -#else - th_farm((void (*)(void *))php_caudium_module_main, THIS); -#endif - pop_n_elems(args); -} - -static void free_struct(TSRMLS_D) -{ - GET_THIS(); - if(THIS->request_data) free_mapping(THIS->request_data); - if(THIS->my_fd_obj) free_object(THIS->my_fd_obj); - free_svalue(&THIS->done_cb); - if(THIS->filename) free_string(THIS->filename); - MEMSET(THIS, 0, sizeof(php_caudium_request)); -} - - -/* - * pike_module_init() is called by Pike once at startup - * - * This functions allocates basic structures - */ - -void pike_module_init( void ) -{ - if (!caudium_php_initialized) { - caudium_php_initialized = 1; - tsrm_startup(1, 1, 0, NULL); - ts_allocate_id(&caudium_globals_id, sizeof(php_caudium_request), NULL, NULL); - sapi_startup(&caudium_sapi_module); - sapi_module.startup(&caudium_sapi_module); - } - start_new_program(); /* Text */ - pike_add_function("run", f_php_caudium_request_handler, - "function(string, mapping, object, function:void)", 0); - end_class("Interpreter", 0); -} - -/* - * pike_module_exit() performs the last steps before the - * server exists. Shutdowns basic services and frees memory - */ - -void pike_module_exit(void) -{ - caudium_php_initialized = 0; - sapi_module.shutdown(&caudium_sapi_module); - tsrm_shutdown(); -} -#endif diff --git a/sapi/caudium/config.m4 b/sapi/caudium/config.m4 deleted file mode 100644 index 5ce55f3f01..0000000000 --- a/sapi/caudium/config.m4 +++ /dev/null @@ -1,98 +0,0 @@ -dnl -dnl $Id$ -dnl - -RESULT=no -PHP_ARG_WITH(caudium,, -[ --with-caudium[=DIR] Build PHP as a Pike module for use with Caudium. - DIR is the Caudium server dir [/usr/local/caudium/server]], no, no) - -AC_MSG_CHECKING([for Caudium support]) - -if test "$PHP_CAUDIUM" != "no"; then - if test "$prefix" = "NONE"; then CPREF=/usr/local/; fi - if test ! -d $PHP_CAUDIUM ; then - if test "$prefix" = "NONE"; then - PHP_CAUDIUM=/usr/local/caudium/server/ - else - PHP_CAUDIUM=$prefix/caudium/server/ - fi - fi - if test -f $PHP_CAUDIUM/bin/caudium; then - PIKE=$PHP_CAUDIUM/bin/caudium - elif test -f $PHP_CAUDIUM/bin/pike; then - PIKE=$PHP_CAUDIUM/bin/pike - else - AC_MSG_ERROR([Could not find a pike in $PHP_CAUDIUM/bin/]) - fi - if $PIKE -e 'float v; int rel;sscanf(version(), "Pike v%f release %d", v, rel);v += rel/10000.0; if(v < 7.0268) exit(1); exit(0);'; then - PIKE_MODULE_DIR=`$PIKE --show-paths 2>&1| grep '^Module' | sed -e 's/.*: //'` - PIKE_INCLUDE_DIR=`echo $PIKE_MODULE_DIR | sed -e 's,lib/pike/modules,include/pike,' -e 's,lib/modules,include/pike,' ` - if test -z "$PIKE_INCLUDE_DIR" || test -z "$PIKE_MODULE_DIR"; then - AC_MSG_ERROR(Failed to figure out Pike module and include directories) - fi - AC_MSG_RESULT(yes) - PIKE=`echo $PIKE | pike -e 'int tries=100; - string orig,pike=Stdio.File("stdin")->read()-"\n"; - orig=pike; - if(search(orig, "/")) - orig = combine_path(getcwd(), orig); - while(!catch(pike=readlink(pike)) && tries--) - ; - write(combine_path(dirname(orig), pike)); '` - PHP_ADD_INCLUDE($PIKE_INCLUDE_DIR) - if test "$prefix" != "NONE"; then - PIKE_C_INCLUDE=$prefix/include/`basename $PIKE` - else - PIKE_C_INCLUDE=/usr/local/include/`basename $PIKE` - fi - AC_MSG_CHECKING([for C includes in $PIKE_C_INCLUDE]) - if test -f $PIKE_C_INCLUDE/version.h; then - PIKE_TEST_VER=`$PIKE -e 'string v; int rel;sscanf(version(), "Pike v%s release %d", v, rel); write(v+"."+rel);'` - ###### VERSION MATCH CHECK ####### - PMAJOR="^#define PIKE_MAJOR_VERSION" - PMINOR="^#define PIKE_MINOR_VERSION" - PBUILD="^#define PIKE_BUILD_VERSION" - - PIKE_CMAJOR_VERSION=0 - PIKE_CMINOR_VERSION=0 - PIKE_CBUILD_VERSION=0 - - PIKE_CMAJOR_VERSION=`grep "$PMAJOR" $PIKE_C_INCLUDE/version.h | sed -e 's/\(#define.*N \)\(.*\)/\2/'` - if test -z "$PIKE_CMAJOR_VERSION"; then - if test -n "`grep f_version $PIKE_C_INCLUDE/version.h`"; then - PIKE_CMAJOR_VERSION=6 - fi - else - PIKE_CMINOR_VERSION=`grep "$PMINOR" $PIKE_C_INCLUDE/version.h | sed -e 's/\(#define.*N \)\(.*\)/\2/'` - PIKE_CBUILD_VERSION=`grep "$PBUILD" $PIKE_C_INCLUDE/version.h | sed -e 's/\(#define.*N \)\(.*\)/\2/'` - fi - - if test "$PIKE_TEST_VER" = "${PIKE_CMAJOR_VERSION}.${PIKE_CMINOR_VERSION}.${PIKE_CBUILD_VERSION}"; then - PHP_ADD_INCLUDE($PIKE_C_INCLUDE) - PIKE_INCLUDE_DIR="$PIKE_INCLUDE_DIR, $PIKE_C_INCLUDE" - AC_MSG_RESULT(found) - else - AC_MSG_RESULT(version mismatch) - fi - else - AC_MSG_RESULT(not found) - fi - else - AC_MSG_ERROR([Caudium PHP5 requires Pike 7.0 or newer]) - fi - PIKE_VERSION=`$PIKE -e 'string v; int rel;sscanf(version(), "Pike v%s release %d", v, rel); write(v+"."+rel);'` - AC_DEFINE(HAVE_CAUDIUM,1,[Whether to compile with Caudium support]) - PHP_SELECT_SAPI(caudium, shared, caudium.c) - INSTALL_IT="\$(INSTALL) -m 0755 $SAPI_SHARED $PHP_CAUDIUM/lib/$PIKE_VERSION/PHP5.so" - RESULT=" *** Pike binary used: $PIKE - *** Pike include dir(s) used: $PIKE_INCLUDE_DIR - *** Pike version: $PIKE_VERSION" - dnl Always use threads since thread-free support really blows. - PHP_BUILD_THREAD_SAFE -fi -AC_MSG_RESULT($RESULT) - -dnl ## Local Variables: -dnl ## tab-width: 4 -dnl ## End: diff --git a/sapi/cgi/CHANGES b/sapi/cgi/CHANGES index de029474e5..b7cf41cf5e 100755 --- a/sapi/cgi/CHANGES +++ b/sapi/cgi/CHANGES @@ -31,4 +31,3 @@ In PHP5.3 all additional configure options (except --enable-cgi) are removed: Now it is disabled by default, but can be enabled with ini directive "cgi.discard_path=1". - diff --git a/sapi/cgi/Makefile.frag b/sapi/cgi/Makefile.frag index d3d7cb3553..75c72bf8b7 100644 --- a/sapi/cgi/Makefile.frag +++ b/sapi/cgi/Makefile.frag @@ -1,6 +1,6 @@ cgi: $(SAPI_CGI_PATH) -$(SAPI_CGI_PATH): $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_CGI_OBJS) +$(SAPI_CGI_PATH): $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_FASTCGI_OBJS) $(PHP_CGI_OBJS) $(BUILD_CGI) install-cgi: $(SAPI_CGI_PATH) diff --git a/sapi/cgi/README.FastCGI b/sapi/cgi/README.FastCGI index 3dda295d84..f0f11e102d 100644 --- a/sapi/cgi/README.FastCGI +++ b/sapi/cgi/README.FastCGI @@ -69,7 +69,7 @@ a line in your config like: Don't load mod_php, by the way. Make sure it is commented out! - #LoadModule php5_module /usr/lib/apache/2.0/libphp5.so + #LoadModule php7_module /usr/lib/apache/2.0/libphp7.so Now, we'll create a fcgi-bin directory, just like you would do with normal CGI scripts. You'll need to create a directory somewhere to store your diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c index bf2c3d2d29..8983b53dc2 100644 --- a/sapi/cgi/cgi_main.c +++ b/sapi/cgi/cgi_main.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -31,7 +31,6 @@ #include "SAPI.h" #include <stdio.h> -#include "php.h" #ifdef PHP_WIN32 # include "win32/time.h" @@ -69,6 +68,7 @@ #include "php_globals.h" #include "php_main.h" #include "fopen_wrappers.h" +#include "http_status_codes.h" #include "ext/standard/php_standard.h" #include "ext/standard/url.h" @@ -86,18 +86,21 @@ int __riscosify_control = __RISCOSIFY_STRICT_UNIX_SPECS; #include "zend_compile.h" #include "zend_execute.h" #include "zend_highlight.h" -#include "zend_indent.h" #include "php_getopt.h" #include "fastcgi.h" +#if defined(PHP_WIN32) && defined(HAVE_OPENSSL) +# include "openssl/applink.c" +#endif + #ifndef PHP_WIN32 /* XXX this will need to change later when threaded fastcgi is implemented. shane */ struct sigaction act, old_term, old_quit, old_int; #endif -static void (*php_php_import_environment_variables)(zval *array_ptr TSRMLS_DC); +static void (*php_php_import_environment_variables)(zval *array_ptr); #ifndef PHP_WIN32 /* these globals used for forking children on unix systems */ @@ -126,7 +129,6 @@ static pid_t pgroup; #define PHP_MODE_STANDARD 1 #define PHP_MODE_HIGHLIGHT 2 -#define PHP_MODE_INDENT 3 #define PHP_MODE_LINT 4 #define PHP_MODE_STRIP 5 @@ -159,6 +161,8 @@ static const opt_struct OPTIONS[] = { }; typedef struct _php_cgi_globals_struct { + HashTable user_config_cache; + char *redirect_status_env; zend_bool rfc2616_headers; zend_bool nph; zend_bool check_shebang_line; @@ -166,11 +170,9 @@ typedef struct _php_cgi_globals_struct { zend_bool force_redirect; zend_bool discard_path; zend_bool fcgi_logging; - char *redirect_status_env; #ifdef PHP_WIN32 zend_bool impersonate; #endif - HashTable user_config_cache; } php_cgi_globals_struct; /* {{{ user_config_cache @@ -187,16 +189,21 @@ typedef struct _user_config_cache_entry { HashTable *user_config; } user_config_cache_entry; -static void user_config_cache_entry_dtor(user_config_cache_entry *entry) +static void user_config_cache_entry_dtor(zval *el) { + user_config_cache_entry *entry = (user_config_cache_entry *)Z_PTR_P(el); zend_hash_destroy(entry->user_config); free(entry->user_config); + free(entry); } /* }}} */ #ifdef ZTS static int php_cgi_globals_id; -#define CGIG(v) TSRMG(php_cgi_globals_id, php_cgi_globals_struct *, v) +#define CGIG(v) ZEND_TSRMG(php_cgi_globals_id, php_cgi_globals_struct *, v) +#if defined(PHP_WIN32) +ZEND_TSRMLS_CACHE_DEFINE() +#endif #else static php_cgi_globals_struct php_cgi_globals; #define CGIG(v) (php_cgi_globals.v) @@ -215,53 +222,63 @@ static php_cgi_globals_struct php_cgi_globals; #define TRANSLATE_SLASHES(path) #endif -static int print_module_info(zend_module_entry *module, void *arg TSRMLS_DC) +#ifndef HAVE_ATTRIBUTE_WEAK +static void fcgi_log(int type, const char *format, ...) { + va_list ap; + + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); +} +#endif + +static int print_module_info(zval *element) { + zend_module_entry *module = Z_PTR_P(element); php_printf("%s\n", module->name); - return 0; + return ZEND_HASH_APPLY_KEEP; } -static int module_name_cmp(const void *a, const void *b TSRMLS_DC) +static int module_name_cmp(const void *a, const void *b) { - Bucket *f = *((Bucket **) a); - Bucket *s = *((Bucket **) b); + Bucket *f = (Bucket *) a; + Bucket *s = (Bucket *) b; - return strcasecmp( ((zend_module_entry *)f->pData)->name, - ((zend_module_entry *)s->pData)->name); + return strcasecmp( ((zend_module_entry *)Z_PTR(f->val))->name, + ((zend_module_entry *)Z_PTR(s->val))->name); } -static void print_modules(TSRMLS_D) +static void print_modules(void) { HashTable sorted_registry; - zend_module_entry tmp; - zend_hash_init(&sorted_registry, 50, NULL, NULL, 1); - zend_hash_copy(&sorted_registry, &module_registry, NULL, &tmp, sizeof(zend_module_entry)); - zend_hash_sort(&sorted_registry, zend_qsort, module_name_cmp, 0 TSRMLS_CC); - zend_hash_apply_with_argument(&sorted_registry, (apply_func_arg_t) print_module_info, NULL TSRMLS_CC); + zend_hash_init(&sorted_registry, 64, NULL, NULL, 1); + zend_hash_copy(&sorted_registry, &module_registry, NULL); + zend_hash_sort(&sorted_registry, module_name_cmp, 0); + zend_hash_apply(&sorted_registry, print_module_info); zend_hash_destroy(&sorted_registry); } -static int print_extension_info(zend_extension *ext, void *arg TSRMLS_DC) +static int print_extension_info(zend_extension *ext, void *arg) { php_printf("%s\n", ext->name); return 0; } -static int extension_name_cmp(const zend_llist_element **f, const zend_llist_element **s TSRMLS_DC) +static int extension_name_cmp(const zend_llist_element **f, const zend_llist_element **s) { return strcmp( ((zend_extension *)(*f)->data)->name, ((zend_extension *)(*s)->data)->name); } -static void print_extensions(TSRMLS_D) +static void print_extensions(void) { zend_llist sorted_exts; zend_llist_copy(&sorted_exts, &zend_extensions); sorted_exts.dtor = NULL; - zend_llist_sort(&sorted_exts, extension_name_cmp TSRMLS_CC); - zend_llist_apply_with_argument(&sorted_exts, (llist_apply_with_arg_func_t) print_extension_info, NULL TSRMLS_CC); + zend_llist_sort(&sorted_exts, extension_name_cmp); + zend_llist_apply_with_argument(&sorted_exts, (llist_apply_with_arg_func_t) print_extension_info, NULL); zend_llist_destroy(&sorted_exts); } @@ -269,10 +286,10 @@ static void print_extensions(TSRMLS_D) #define STDOUT_FILENO 1 #endif -static inline size_t sapi_cgi_single_write(const char *str, uint str_length TSRMLS_DC) +static inline size_t sapi_cgi_single_write(const char *str, size_t str_length) { #ifdef PHP_WRITE_STDOUT - long ret; + int ret; ret = write(STDOUT_FILENO, str, str_length); if (ret <= 0) return 0; @@ -285,14 +302,14 @@ static inline size_t sapi_cgi_single_write(const char *str, uint str_length TSRM #endif } -static int sapi_cgi_ub_write(const char *str, uint str_length TSRMLS_DC) +static size_t sapi_cgi_ub_write(const char *str, size_t str_length) { const char *ptr = str; - uint remaining = str_length; + size_t remaining = str_length; size_t ret; while (remaining > 0) { - ret = sapi_cgi_single_write(ptr, remaining TSRMLS_CC); + ret = sapi_cgi_single_write(ptr, remaining); if (!ret) { php_handle_aborted_connection(); return str_length - remaining; @@ -304,14 +321,15 @@ static int sapi_cgi_ub_write(const char *str, uint str_length TSRMLS_DC) return str_length; } -static int sapi_fcgi_ub_write(const char *str, uint str_length TSRMLS_DC) +static size_t sapi_fcgi_ub_write(const char *str, size_t str_length) { const char *ptr = str; - uint remaining = str_length; + size_t remaining = str_length; fcgi_request *request = (fcgi_request*) SG(server_context); while (remaining > 0) { - long ret = fcgi_write(request, FCGI_STDOUT, ptr, remaining); + int to_write = remaining > INT_MAX ? INT_MAX : (int)remaining; + int ret = fcgi_write(request, FCGI_STDOUT, ptr, to_write); if (ret <= 0) { php_handle_aborted_connection(); @@ -347,58 +365,7 @@ static void sapi_fcgi_flush(void *server_context) #define SAPI_CGI_MAX_HEADER_LENGTH 1024 -typedef struct _http_error { - int code; - const char* msg; -} http_error; - -static const http_error http_error_codes[] = { - {100, "Continue"}, - {101, "Switching Protocols"}, - {200, "OK"}, - {201, "Created"}, - {202, "Accepted"}, - {203, "Non-Authoritative Information"}, - {204, "No Content"}, - {205, "Reset Content"}, - {206, "Partial Content"}, - {300, "Multiple Choices"}, - {301, "Moved Permanently"}, - {302, "Moved Temporarily"}, - {303, "See Other"}, - {304, "Not Modified"}, - {305, "Use Proxy"}, - {400, "Bad Request"}, - {401, "Unauthorized"}, - {402, "Payment Required"}, - {403, "Forbidden"}, - {404, "Not Found"}, - {405, "Method Not Allowed"}, - {406, "Not Acceptable"}, - {407, "Proxy Authentication Required"}, - {408, "Request Time-out"}, - {409, "Conflict"}, - {410, "Gone"}, - {411, "Length Required"}, - {412, "Precondition Failed"}, - {413, "Request Entity Too Large"}, - {414, "Request-URI Too Large"}, - {415, "Unsupported Media Type"}, - {428, "Precondition Required"}, - {429, "Too Many Requests"}, - {431, "Request Header Fields Too Large"}, - {451, "Unavailable For Legal Reasons"}, - {500, "Internal Server Error"}, - {501, "Not Implemented"}, - {502, "Bad Gateway"}, - {503, "Service Unavailable"}, - {504, "Gateway Time-out"}, - {505, "HTTP Version not supported"}, - {511, "Network Authentication Required"}, - {0, NULL} -}; - -static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) +static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers) { char buf[SAPI_CGI_MAX_HEADER_LENGTH]; sapi_header_struct *h; @@ -448,7 +415,7 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos); } if (!has_status) { - http_error *err = (http_error*)http_error_codes; + http_response_status_code_pair *err = (http_response_status_code_pair*)http_status_map; while (err->code != 0) { if (err->code == SG(sapi_headers).http_response_code) { @@ -456,8 +423,8 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) } err++; } - if (err->msg) { - len = slprintf(buf, sizeof(buf), "Status: %d %s\r\n", SG(sapi_headers).http_response_code, err->msg); + if (err->str) { + len = slprintf(buf, sizeof(buf), "Status: %d %s\r\n", SG(sapi_headers).http_response_code, err->str); } else { len = slprintf(buf, sizeof(buf), "Status: %d\r\n", SG(sapi_headers).http_response_code); } @@ -475,7 +442,7 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) while (h) { /* prevent CRLFCRLF */ if (h->header_len) { - if (h->header_len > sizeof("Status:")-1 && + if (h->header_len > sizeof("Status:")-1 && strncasecmp(h->header, "Status:", sizeof("Status:")-1) == 0 ) { if (!ignore_status) { @@ -504,14 +471,26 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) # define STDIN_FILENO 0 #endif -static int sapi_cgi_read_post(char *buffer, uint count_bytes TSRMLS_DC) +static size_t sapi_cgi_read_post(char *buffer, size_t count_bytes) { - uint read_bytes = 0; + size_t read_bytes = 0; int tmp_read_bytes; + size_t remaining_bytes; - count_bytes = MIN(count_bytes, SG(request_info).content_length - SG(read_post_bytes)); + assert(SG(request_info).content_length >= SG(read_post_bytes)); + + remaining_bytes = (size_t)(SG(request_info).content_length - SG(read_post_bytes)); + + count_bytes = MIN(count_bytes, remaining_bytes); while (read_bytes < count_bytes) { +#ifdef PHP_WIN32 + size_t diff = count_bytes - read_bytes; + unsigned int to_read = (diff > UINT_MAX) ? UINT_MAX : (unsigned int)diff; + + tmp_read_bytes = read(STDIN_FILENO, buffer + read_bytes, to_read); +#else tmp_read_bytes = read(STDIN_FILENO, buffer + read_bytes, count_bytes - read_bytes); +#endif if (tmp_read_bytes <= 0) { break; } @@ -520,9 +499,9 @@ static int sapi_cgi_read_post(char *buffer, uint count_bytes TSRMLS_DC) return read_bytes; } -static int sapi_fcgi_read_post(char *buffer, uint count_bytes TSRMLS_DC) +static size_t sapi_fcgi_read_post(char *buffer, size_t count_bytes) { - uint read_bytes = 0; + size_t read_bytes = 0; int tmp_read_bytes; fcgi_request *request = (fcgi_request*) SG(server_context); size_t remaining = SG(request_info).content_length - SG(read_post_bytes); @@ -531,7 +510,10 @@ static int sapi_fcgi_read_post(char *buffer, uint count_bytes TSRMLS_DC) count_bytes = remaining; } while (read_bytes < count_bytes) { - tmp_read_bytes = fcgi_read(request, buffer + read_bytes, count_bytes - read_bytes); + size_t diff = count_bytes - read_bytes; + int to_read = (diff > INT_MAX) ? INT_MAX : (int)diff; + + tmp_read_bytes = fcgi_read(request, buffer + read_bytes, to_read); if (tmp_read_bytes <= 0) { break; } @@ -540,19 +522,19 @@ static int sapi_fcgi_read_post(char *buffer, uint count_bytes TSRMLS_DC) return read_bytes; } -static char *sapi_cgi_getenv(char *name, size_t name_len TSRMLS_DC) +static char *sapi_cgi_getenv(char *name, size_t name_len) { return getenv(name); } -static char *sapi_fcgi_getenv(char *name, size_t name_len TSRMLS_DC) +static char *sapi_fcgi_getenv(char *name, size_t name_len) { /* when php is started by mod_fastcgi, no regular environment * is provided to PHP. It is always sent to PHP at the start * of a request. So we have to do our own lookup to get env * vars. This could probably be faster somehow. */ fcgi_request *request = (fcgi_request*) SG(server_context); - char *ret = fcgi_getenv(request, name, name_len); + char *ret = fcgi_getenv(request, name, (int)name_len); if (ret) return ret; /* if cgi, or fastcgi and not found in fcgi env @@ -560,10 +542,10 @@ static char *sapi_fcgi_getenv(char *name, size_t name_len TSRMLS_DC) return getenv(name); } -static char *_sapi_cgi_putenv(char *name, int name_len, char *value) +static char *_sapi_cgi_putenv(char *name, size_t name_len, char *value) { #if !HAVE_SETENV || !HAVE_UNSETENV - int len; + size_t len; char *buf; #endif @@ -605,71 +587,65 @@ static char *_sapi_cgi_putenv(char *name, int name_len, char *value) return getenv(name); } -static char *sapi_cgi_read_cookies(TSRMLS_D) +static char *sapi_cgi_read_cookies(void) { return getenv("HTTP_COOKIE"); } -static char *sapi_fcgi_read_cookies(TSRMLS_D) +static char *sapi_fcgi_read_cookies(void) { fcgi_request *request = (fcgi_request*) SG(server_context); return FCGI_GETENV(request, "HTTP_COOKIE"); } -static void cgi_php_load_env_var(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg TSRMLS_DC) +static void cgi_php_load_env_var(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg) { - zval *array_ptr = (zval*)arg; - int filter_arg = (array_ptr == PG(http_globals)[TRACK_VARS_ENV])?PARSE_ENV:PARSE_SERVER; - unsigned int new_val_len; + zval *array_ptr = (zval*)arg; + int filter_arg = (Z_ARR_P(array_ptr) == Z_ARR(PG(http_globals)[TRACK_VARS_ENV]))?PARSE_ENV:PARSE_SERVER; + size_t new_val_len; - if (sapi_module.input_filter(filter_arg, var, &val, strlen(val), &new_val_len TSRMLS_CC)) { - php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC); + if (sapi_module.input_filter(filter_arg, var, &val, strlen(val), &new_val_len)) { + php_register_variable_safe(var, val, new_val_len, array_ptr); } } -static void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC) +static void cgi_php_import_environment_variables(zval *array_ptr) { - if (PG(http_globals)[TRACK_VARS_ENV] && - array_ptr != PG(http_globals)[TRACK_VARS_ENV] && - Z_TYPE_P(PG(http_globals)[TRACK_VARS_ENV]) == IS_ARRAY && - zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_ENV])) > 0 + if (Z_TYPE(PG(http_globals)[TRACK_VARS_ENV]) == IS_ARRAY && + Z_ARR_P(array_ptr) != Z_ARR(PG(http_globals)[TRACK_VARS_ENV]) && + zend_hash_num_elements(Z_ARRVAL(PG(http_globals)[TRACK_VARS_ENV])) > 0 ) { zval_dtor(array_ptr); - *array_ptr = *PG(http_globals)[TRACK_VARS_ENV]; - INIT_PZVAL(array_ptr); - zval_copy_ctor(array_ptr); + ZVAL_DUP(array_ptr, &PG(http_globals)[TRACK_VARS_ENV]); return; - } else if (PG(http_globals)[TRACK_VARS_SERVER] && - array_ptr != PG(http_globals)[TRACK_VARS_SERVER] && - Z_TYPE_P(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY && - zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER])) > 0 + } else if (Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY && + Z_ARR_P(array_ptr) != Z_ARR(PG(http_globals)[TRACK_VARS_SERVER]) && + zend_hash_num_elements(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER])) > 0 ) { zval_dtor(array_ptr); - *array_ptr = *PG(http_globals)[TRACK_VARS_SERVER]; - INIT_PZVAL(array_ptr); - zval_copy_ctor(array_ptr); + ZVAL_DUP(array_ptr, &PG(http_globals)[TRACK_VARS_SERVER]); return; } /* call php's original import as a catch-all */ - php_php_import_environment_variables(array_ptr TSRMLS_CC); + php_php_import_environment_variables(array_ptr); if (fcgi_is_fastcgi()) { fcgi_request *request = (fcgi_request*) SG(server_context); - fcgi_loadenv(request, cgi_php_load_env_var, array_ptr TSRMLS_CC); + fcgi_loadenv(request, cgi_php_load_env_var, array_ptr); } } -static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC) +static void sapi_cgi_register_variables(zval *track_vars_array) { - unsigned int php_self_len; + size_t php_self_len; char *php_self; /* In CGI mode, we consider the environment to be a part of the server * variables */ - php_import_environment_variables(track_vars_array TSRMLS_CC); + php_import_environment_variables(track_vars_array); if (CGIG(fix_pathinfo)) { char *script_name = SG(request_info).request_uri; @@ -686,10 +662,10 @@ static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC) } if (path_info) { - unsigned int path_info_len = strlen(path_info); + size_t path_info_len = strlen(path_info); if (script_name) { - unsigned int script_name_len = strlen(script_name); + size_t script_name_len = strlen(script_name); php_self_len = script_name_len + path_info_len; php_self = do_alloca(php_self_len + 1, use_heap); @@ -712,8 +688,8 @@ static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC) } /* Build the special-case PHP_SELF variable for the CGI version */ - if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len TSRMLS_CC)) { - php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array TSRMLS_CC); + if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len)) { + php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array); } if (free_php_self) { free_alloca(php_self, use_heap); @@ -721,25 +697,25 @@ static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC) } else { php_self = SG(request_info).request_uri ? SG(request_info).request_uri : ""; php_self_len = strlen(php_self); - if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len TSRMLS_CC)) { - php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array TSRMLS_CC); + if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len)) { + php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array); } } } -static void sapi_cgi_log_message(char *message TSRMLS_DC) +static void sapi_cgi_log_message(char *message) { if (fcgi_is_fastcgi() && CGIG(fcgi_logging)) { fcgi_request *request; request = (fcgi_request*) SG(server_context); if (request) { - int ret, len = strlen(message); + int ret, len = (int)strlen(message); char *buf = malloc(len+2); memcpy(buf, message, len); memcpy(buf + len, "\n", sizeof("\n")); - ret = fcgi_write(request, FCGI_STDERR, buf, len + 1); + ret = fcgi_write(request, FCGI_STDERR, buf, (int)(len + 1)); free(buf); if (ret < 0) { php_handle_aborted_connection(); @@ -755,34 +731,33 @@ static void sapi_cgi_log_message(char *message TSRMLS_DC) /* {{{ php_cgi_ini_activate_user_config */ -static void php_cgi_ini_activate_user_config(char *path, int path_len, const char *doc_root, int doc_root_len, int start TSRMLS_DC) +static void php_cgi_ini_activate_user_config(char *path, size_t path_len, const char *doc_root, size_t doc_root_len, int start) { char *ptr; user_config_cache_entry *new_entry, *entry; - time_t request_time = sapi_get_request_time(TSRMLS_C); + time_t request_time = (time_t)sapi_get_request_time(); /* Find cached config entry: If not found, create one */ - if (zend_hash_find(&CGIG(user_config_cache), path, path_len + 1, (void **) &entry) == FAILURE) { + if ((entry = zend_hash_str_find_ptr(&CGIG(user_config_cache), path, path_len)) == NULL) { new_entry = pemalloc(sizeof(user_config_cache_entry), 1); new_entry->expires = 0; new_entry->user_config = (HashTable *) pemalloc(sizeof(HashTable), 1); - zend_hash_init(new_entry->user_config, 0, NULL, (dtor_func_t) config_zval_dtor, 1); - zend_hash_update(&CGIG(user_config_cache), path, path_len + 1, new_entry, sizeof(user_config_cache_entry), (void **) &entry); - free(new_entry); + zend_hash_init(new_entry->user_config, 8, NULL, (dtor_func_t) config_zval_dtor, 1); + entry = zend_hash_str_update_ptr(&CGIG(user_config_cache), path, path_len, new_entry); } /* Check whether cache entry has expired and rescan if it is */ if (request_time > entry->expires) { char *real_path = NULL; - int real_path_len; + size_t real_path_len; char *s1, *s2; - int s_len; + size_t s_len; /* Clear the expired config */ zend_hash_clean(entry->user_config); if (!IS_ABSOLUTE_PATH(path, path_len)) { - real_path = tsrm_realpath(path, NULL TSRMLS_CC); + real_path = tsrm_realpath(path, NULL); if (real_path == NULL) { return; } @@ -802,23 +777,23 @@ static void php_cgi_ini_activate_user_config(char *path, int path_len, const cha } /* we have to test if path is part of DOCUMENT_ROOT. - if it is inside the docroot, we scan the tree up to the docroot + if it is inside the docroot, we scan the tree up to the docroot to find more user.ini, if not we only scan the current path. */ #ifdef PHP_WIN32 if (strnicmp(s1, s2, s_len) == 0) { -#else +#else if (strncmp(s1, s2, s_len) == 0) { #endif ptr = s2 + start; /* start is the point where doc_root ends! */ while ((ptr = strchr(ptr, DEFAULT_SLASH)) != NULL) { *ptr = 0; - php_parse_user_ini_file(path, PG(user_ini_filename), entry->user_config TSRMLS_CC); + php_parse_user_ini_file(path, PG(user_ini_filename), entry->user_config); *ptr = '/'; ptr++; } } else { - php_parse_user_ini_file(path, PG(user_ini_filename), entry->user_config TSRMLS_CC); + php_parse_user_ini_file(path, PG(user_ini_filename), entry->user_config); } if (real_path) { @@ -828,14 +803,14 @@ static void php_cgi_ini_activate_user_config(char *path, int path_len, const cha } /* Activate ini entries with values from the user config hash */ - php_ini_activate_config(entry->user_config, PHP_INI_PERDIR, PHP_INI_STAGE_HTACCESS TSRMLS_CC); + php_ini_activate_config(entry->user_config, PHP_INI_PERDIR, PHP_INI_STAGE_HTACCESS); } /* }}} */ -static int sapi_cgi_activate(TSRMLS_D) +static int sapi_cgi_activate(void) { char *path, *doc_root, *server_name; - uint path_len, doc_root_len, server_name_len; + size_t path_len, doc_root_len, server_name_len; /* PATH_TRANSLATED should be defined at this stage but better safe than sorry :) */ if (!SG(request_info).path_translated) { @@ -856,7 +831,7 @@ static int sapi_cgi_activate(TSRMLS_D) server_name_len = strlen(server_name); server_name = estrndup(server_name, server_name_len); zend_str_tolower(server_name, server_name_len); - php_ini_activate_per_host_config(server_name, server_name_len + 1 TSRMLS_CC); + php_ini_activate_per_host_config(server_name, server_name_len); efree(server_name); } } @@ -880,7 +855,7 @@ static int sapi_cgi_activate(TSRMLS_D) path[path_len] = 0; /* Activate per-dir-system-configuration defined in php.ini and stored into configuration_hash during startup */ - php_ini_activate_per_dir_config(path, path_len TSRMLS_CC); /* Note: for global settings sake we check from root to path */ + php_ini_activate_per_dir_config(path, path_len); /* Note: for global settings sake we check from root to path */ /* Load and activate user ini files in path starting from DOCUMENT_ROOT */ if (PG(user_ini_filename) && *PG(user_ini_filename)) { @@ -902,8 +877,8 @@ static int sapi_cgi_activate(TSRMLS_D) doc_root = estrndup(doc_root, doc_root_len); zend_str_tolower(doc_root, doc_root_len); #endif - php_cgi_ini_activate_user_config(path, path_len, doc_root, doc_root_len, doc_root_len - 1 TSRMLS_CC); - + php_cgi_ini_activate_user_config(path, path_len, doc_root, doc_root_len, (doc_root_len > 0 && (doc_root_len - 1))); + #ifdef PHP_WIN32 efree(doc_root); #endif @@ -916,7 +891,7 @@ static int sapi_cgi_activate(TSRMLS_D) return SUCCESS; } -static int sapi_cgi_deactivate(TSRMLS_D) +static int sapi_cgi_deactivate(void) { /* flush only when SAPI was started. The reasons are: 1. SAPI Deactivate is called from two places: module init and request shutdown @@ -1053,7 +1028,7 @@ static int is_valid_path(const char *path) p++; if (UNEXPECTED(!*p) || UNEXPECTED(IS_SLASH(*p))) { return 0; - } + } } } } @@ -1064,12 +1039,12 @@ static int is_valid_path(const char *path) /* }}} */ #define CGI_GETENV(name) \ - ((request) ? \ + ((has_env) ? \ FCGI_GETENV(request, name) : \ getenv(name)) #define CGI_PUTENV(name, value) \ - ((request) ? \ + ((has_env) ? \ FCGI_PUTENV(request, name, value) : \ _sapi_cgi_putenv(name, sizeof(name)-1, value)) @@ -1139,8 +1114,9 @@ static int is_valid_path(const char *path) Comments in the code below refer to using the above URL in a request */ -static void init_request_info(fcgi_request *request TSRMLS_DC) +static void init_request_info(fcgi_request *request) { + int has_env = fcgi_has_env(request); char *env_script_filename = CGI_GETENV("SCRIPT_FILENAME"); char *env_path_translated = CGI_GETENV("PATH_TRANSLATED"); char *script_path_translated = env_script_filename; @@ -1193,7 +1169,7 @@ static void init_request_info(fcgi_request *request TSRMLS_DC) #endif if (CGIG(fix_pathinfo)) { - struct stat st; + zend_stat_t st; char *real_path = NULL; char *env_redirect_url = CGI_GETENV("REDIRECT_URL"); char *env_document_root = CGI_GETENV("DOCUMENT_ROOT"); @@ -1201,7 +1177,7 @@ static void init_request_info(fcgi_request *request TSRMLS_DC) char *orig_path_info = env_path_info; char *orig_script_name = env_script_name; char *orig_script_filename = env_script_filename; - int script_path_translated_len; + size_t script_path_translated_len; if (!env_document_root && PG(doc_root)) { env_document_root = CGI_PUTENV("DOCUMENT_ROOT", PG(doc_root)); @@ -1239,15 +1215,15 @@ static void init_request_info(fcgi_request *request TSRMLS_DC) #ifdef PHP_WIN32 script_path_translated[script_path_translated_len-1] == '\\' || #endif - (real_path = tsrm_realpath(script_path_translated, NULL TSRMLS_CC)) == NULL) + (real_path = tsrm_realpath(script_path_translated, NULL)) == NULL) ) { char *pt = estrndup(script_path_translated, script_path_translated_len); - int len = script_path_translated_len; + size_t len = script_path_translated_len; char *ptr; while ((ptr = strrchr(pt, '/')) || (ptr = strrchr(pt, '\\'))) { *ptr = 0; - if (stat(pt, &st) == 0 && S_ISREG(st.st_mode)) { + if (zend_stat(pt, &st) == 0 && S_ISREG(st.st_mode)) { /* * okay, we found the base script! * work out how many chars we had to strip off; @@ -1263,8 +1239,8 @@ static void init_request_info(fcgi_request *request TSRMLS_DC) * we have to play the game of hide and seek to figure * out what SCRIPT_NAME should be */ - int slen = len - strlen(pt); - int pilen = env_path_info ? strlen(env_path_info) : 0; + size_t slen = len - strlen(pt); + size_t pilen = env_path_info ? strlen(env_path_info) : 0; char *path_info = env_path_info ? env_path_info + pilen - slen : NULL; if (orig_path_info != path_info) { @@ -1300,8 +1276,8 @@ static void init_request_info(fcgi_request *request TSRMLS_DC) * SCRIPT_FILENAME minus SCRIPT_NAME */ if (env_document_root) { - int l = strlen(env_document_root); - int path_translated_len = 0; + size_t l = strlen(env_document_root); + size_t path_translated_len = 0; char *path_translated = NULL; if (l && env_document_root[l - 1] == '/') { @@ -1330,8 +1306,8 @@ static void init_request_info(fcgi_request *request TSRMLS_DC) strstr(pt, env_script_name) ) { /* PATH_TRANSLATED = PATH_TRANSLATED - SCRIPT_NAME + PATH_INFO */ - int ptlen = strlen(pt) - strlen(env_script_name); - int path_translated_len = ptlen + (env_path_info ? strlen(env_path_info) : 0); + size_t ptlen = strlen(pt) - strlen(env_script_name); + size_t path_translated_len = ptlen + (env_path_info ? strlen(env_path_info) : 0); char *path_translated = NULL; path_translated = (char *) emalloc(path_translated_len + 1); @@ -1429,7 +1405,7 @@ static void init_request_info(fcgi_request *request TSRMLS_DC) /* The CGI RFC allows servers to pass on unvalidated Authorization data */ auth = CGI_GETENV("HTTP_AUTHORIZATION"); - php_handle_auth_data(auth TSRMLS_CC); + php_handle_auth_data(auth); } } /* }}} */ @@ -1473,8 +1449,11 @@ PHP_INI_END() /* {{{ php_cgi_globals_ctor */ -static void php_cgi_globals_ctor(php_cgi_globals_struct *php_cgi_globals TSRMLS_DC) +static void php_cgi_globals_ctor(php_cgi_globals_struct *php_cgi_globals) { +#ifdef ZTS + ZEND_TSRMLS_CACHE_UPDATE(); +#endif php_cgi_globals->rfc2616_headers = 0; php_cgi_globals->nph = 0; php_cgi_globals->check_shebang_line = 1; @@ -1486,7 +1465,7 @@ static void php_cgi_globals_ctor(php_cgi_globals_struct *php_cgi_globals TSRMLS_ #ifdef PHP_WIN32 php_cgi_globals->impersonate = 0; #endif - zend_hash_init(&php_cgi_globals->user_config_cache, 0, NULL, (dtor_func_t) user_config_cache_entry_dtor, 1); + zend_hash_init(&php_cgi_globals->user_config_cache, 8, NULL, user_config_cache_entry_dtor, 1); } /* }}} */ @@ -1520,8 +1499,8 @@ static PHP_MINFO_FUNCTION(cgi) PHP_FUNCTION(apache_child_terminate) /* {{{ */ { - if (ZEND_NUM_ARGS() > 0) { - WRONG_PARAM_COUNT; + if (zend_parse_parameters_none()) { + return; } if (fcgi_is_fastcgi()) { fcgi_terminate(); @@ -1529,7 +1508,7 @@ PHP_FUNCTION(apache_child_terminate) /* {{{ */ } /* }}} */ -static void add_request_header(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg TSRMLS_DC) /* {{{ */ +static void add_request_header(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg) /* {{{ */ { zval *return_value = (zval*)arg; char *str = NULL; @@ -1570,7 +1549,7 @@ static void add_request_header(char *var, unsigned int var_len, char *val, unsig } else { return; } - add_assoc_stringl_ex(return_value, var, var_len+1, val, val_len, 1); + add_assoc_stringl_ex(return_value, var, var_len, val, val_len); if (str) { free_alloca(var, use_heap); } @@ -1579,19 +1558,19 @@ static void add_request_header(char *var, unsigned int var_len, char *val, unsig PHP_FUNCTION(apache_request_headers) /* {{{ */ { - if (ZEND_NUM_ARGS() > 0) { - WRONG_PARAM_COUNT; + if (zend_parse_parameters_none()) { + return; } array_init(return_value); if (fcgi_is_fastcgi()) { fcgi_request *request = (fcgi_request*) SG(server_context); - fcgi_loadenv(request, add_request_header, return_value TSRMLS_CC); + fcgi_loadenv(request, add_request_header, return_value); } else { char buf[128]; char **env, *p, *q, *var, *val, *t = buf; size_t alloc_size = sizeof(buf); - unsigned long var_len; + zend_ulong var_len; for (env = environ; env != NULL && *env != NULL; env++) { val = strchr(*env, '='); @@ -1651,7 +1630,7 @@ PHP_FUNCTION(apache_request_headers) /* {{{ */ continue; } val++; - add_assoc_string_ex(return_value, var, var_len+1, val, 1); + add_assoc_string_ex(return_value, var, var_len, val); } if (t != buf && t != NULL) { efree(t); @@ -1660,10 +1639,10 @@ PHP_FUNCTION(apache_request_headers) /* {{{ */ } /* }}} */ -static void add_response_header(sapi_header_struct *h, zval *return_value TSRMLS_DC) /* {{{ */ +static void add_response_header(sapi_header_struct *h, zval *return_value) /* {{{ */ { char *s, *p; - int len = 0; + size_t len = 0; ALLOCA_FLAG(use_heap) if (h->header_len > 0) { @@ -1672,9 +1651,9 @@ static void add_response_header(sapi_header_struct *h, zval *return_value TSRMLS len = p - h->header; } if (len > 0) { - while (len > 0 && (h->header[len-1] == ' ' || h->header[len-1] == '\t')) { + do { len--; - } + } while (len != 0 && (h->header[len-1] == ' ' || h->header[len-1] == '\t')); if (len) { s = do_alloca(len + 1, use_heap); memcpy(s, h->header, len); @@ -1682,7 +1661,7 @@ static void add_response_header(sapi_header_struct *h, zval *return_value TSRMLS do { p++; } while (*p == ' ' || *p == '\t'); - add_assoc_stringl_ex(return_value, s, len+1, p, h->header_len - (p - h->header), 1); + add_assoc_stringl_ex(return_value, s, len, p, h->header_len - (p - h->header)); free_alloca(s, use_heap); } } @@ -1696,11 +1675,8 @@ PHP_FUNCTION(apache_response_headers) /* {{{ */ return; } - if (!&SG(sapi_headers).headers) { - RETURN_FALSE; - } array_init(return_value); - zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t)add_response_header, return_value TSRMLS_CC); + zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t)add_response_header, return_value); } /* }}} */ @@ -1734,7 +1710,8 @@ int main(int argc, char *argv[]) { int free_query_string = 0; int exit_status = SUCCESS; - int cgi = 0, c, i, len; + int cgi = 0, c, i; + size_t len; zend_file_handle file_handle; char *s; @@ -1744,19 +1721,16 @@ int main(int argc, char *argv[]) int orig_optind = php_optind; char *orig_optarg = php_optarg; char *script_file = NULL; - int ini_entries_len = 0; + size_t ini_entries_len = 0; /* end of temporary locals */ -#ifdef ZTS - void ***tsrm_ls; -#endif - int max_requests = 500; int requests = 0; int fastcgi; char *bindpath = NULL; int fcgi_fd = 0; fcgi_request *request = NULL; + int warmup_repeats = 0; int repeats = 1; int benchmark = 0; #if HAVE_GETTIMEOFDAY @@ -1794,13 +1768,18 @@ int main(int argc, char *argv[]) #ifdef ZTS tsrm_startup(1, 1, 0, NULL); - tsrm_ls = ts_resource(0); + (void)ts_resource(0); + ZEND_TSRMLS_CACHE_UPDATE(); +#endif + +#ifdef ZEND_SIGNALS + zend_signal_startup(); #endif #ifdef ZTS ts_allocate_id(&php_cgi_globals_id, sizeof(php_cgi_globals_struct), (ts_allocate_ctor) php_cgi_globals_ctor, NULL); #else - php_cgi_globals_ctor(&php_cgi_globals TSRMLS_CC); + php_cgi_globals_ctor(&php_cgi_globals); #endif sapi_startup(&cgi_sapi_module); @@ -1853,7 +1832,7 @@ int main(int argc, char *argv[]) break; case 'd': { /* define ini entries on command line */ - int len = strlen(php_optarg); + size_t len = strlen(php_optarg); char *val; if ((val = strchr(php_optarg, '='))) { @@ -1964,6 +1943,10 @@ consult the installation file that came with this distribution, or visit \n\ } } +#ifndef HAVE_ATTRIBUTE_WEAK + fcgi_set_logger(fcgi_log); +#endif + if (bindpath) { int backlog = 128; if (getenv("PHP_FCGI_BACKLOG")) { @@ -1994,109 +1977,109 @@ consult the installation file that came with this distribution, or visit \n\ php_import_environment_variables = cgi_php_import_environment_variables; /* library is already initialized, now init our request */ - request = fcgi_init_request(fcgi_fd); + request = fcgi_init_request(fcgi_fd, NULL, NULL, NULL); #ifndef PHP_WIN32 - /* Pre-fork, if required */ - if (getenv("PHP_FCGI_CHILDREN")) { - char * children_str = getenv("PHP_FCGI_CHILDREN"); - children = atoi(children_str); - if (children < 0) { - fprintf(stderr, "PHP_FCGI_CHILDREN is not valid\n"); - return FAILURE; + /* Pre-fork, if required */ + if (getenv("PHP_FCGI_CHILDREN")) { + char * children_str = getenv("PHP_FCGI_CHILDREN"); + children = atoi(children_str); + if (children < 0) { + fprintf(stderr, "PHP_FCGI_CHILDREN is not valid\n"); + return FAILURE; + } + fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, children_str, strlen(children_str)); + /* This is the number of concurrent requests, equals FCGI_MAX_CONNS */ + fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, children_str, strlen(children_str)); + } else { + fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, "1", sizeof("1")-1); + fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, "1", sizeof("1")-1); } - fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, children_str, strlen(children_str)); - /* This is the number of concurrent requests, equals FCGI_MAX_CONNS */ - fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, children_str, strlen(children_str)); - } else { - fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, "1", sizeof("1")-1); - fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, "1", sizeof("1")-1); - } - if (children) { - int running = 0; - pid_t pid; + if (children) { + int running = 0; + pid_t pid; - /* Create a process group for ourself & children */ - setsid(); - pgroup = getpgrp(); + /* Create a process group for ourself & children */ + setsid(); + pgroup = getpgrp(); #ifdef DEBUG_FASTCGI - fprintf(stderr, "Process group %d\n", pgroup); + fprintf(stderr, "Process group %d\n", pgroup); #endif - /* Set up handler to kill children upon exit */ - act.sa_flags = 0; - act.sa_handler = fastcgi_cleanup; - if (sigaction(SIGTERM, &act, &old_term) || - sigaction(SIGINT, &act, &old_int) || - sigaction(SIGQUIT, &act, &old_quit) - ) { - perror("Can't set signals"); - exit(1); - } + /* Set up handler to kill children upon exit */ + act.sa_flags = 0; + act.sa_handler = fastcgi_cleanup; + if (sigaction(SIGTERM, &act, &old_term) || + sigaction(SIGINT, &act, &old_int) || + sigaction(SIGQUIT, &act, &old_quit) + ) { + perror("Can't set signals"); + exit(1); + } - if (fcgi_in_shutdown()) { - goto parent_out; - } + if (fcgi_in_shutdown()) { + goto parent_out; + } - while (parent) { - do { + while (parent) { + do { #ifdef DEBUG_FASTCGI - fprintf(stderr, "Forking, %d running\n", running); -#endif - pid = fork(); - switch (pid) { - case 0: - /* One of the children. - * Make sure we don't go round the - * fork loop any more - */ - parent = 0; + fprintf(stderr, "Forking, %d running\n", running); +#endif + pid = fork(); + switch (pid) { + case 0: + /* One of the children. + * Make sure we don't go round the + * fork loop any more + */ + parent = 0; - /* don't catch our signals */ - sigaction(SIGTERM, &old_term, 0); - sigaction(SIGQUIT, &old_quit, 0); - sigaction(SIGINT, &old_int, 0); - break; - case -1: - perror("php (pre-forking)"); - exit(1); - break; - default: - /* Fine */ - running++; - break; - } - } while (parent && (running < children)); + /* don't catch our signals */ + sigaction(SIGTERM, &old_term, 0); + sigaction(SIGQUIT, &old_quit, 0); + sigaction(SIGINT, &old_int, 0); + break; + case -1: + perror("php (pre-forking)"); + exit(1); + break; + default: + /* Fine */ + running++; + break; + } + } while (parent && (running < children)); - if (parent) { + if (parent) { #ifdef DEBUG_FASTCGI - fprintf(stderr, "Wait for kids, pid %d\n", getpid()); + fprintf(stderr, "Wait for kids, pid %d\n", getpid()); #endif - parent_waiting = 1; - while (1) { - if (wait(&status) >= 0) { - running--; - break; - } else if (exit_signal) { - break; + parent_waiting = 1; + while (1) { + if (wait(&status) >= 0) { + running--; + break; + } else if (exit_signal) { + break; + } } - } - if (exit_signal) { + if (exit_signal) { #if 0 - while (running > 0) { - while (wait(&status) < 0) { + while (running > 0) { + while (wait(&status) < 0) { + } + running--; } - running--; - } #endif - goto parent_out; + goto parent_out; + } } } + } else { + parent = 0; } - } else { - parent = 0; - } #endif /* WIN32 */ } @@ -2106,7 +2089,15 @@ consult the installation file that came with this distribution, or visit \n\ switch (c) { case 'T': benchmark = 1; - repeats = atoi(php_optarg); + { + char *comma = strchr(php_optarg, ','); + if (comma) { + warmup_repeats = atoi(php_optarg); + repeats = atoi(comma + 1); + } else { + repeats = atoi(php_optarg); + } + } #ifdef HAVE_GETTIMEOFDAY gettimeofday(&start, NULL); #else @@ -2122,7 +2113,7 @@ consult the installation file that came with this distribution, or visit \n\ no_headers = 1; SG(headers_sent) = 1; php_cgi_usage(argv[0]); - php_output_end_all(TSRMLS_C); + php_output_end_all(); exit_status = 0; goto out; } @@ -2140,9 +2131,8 @@ consult the installation file that came with this distribution, or visit \n\ } #endif while (!fastcgi || fcgi_accept_request(request) >= 0) { - SG(server_context) = fastcgi ? (void *) request : (void *) 1; - init_request_info(request TSRMLS_CC); - CG(interactive) = 0; + SG(server_context) = fastcgi ? (void *)request : (void *) 1; + init_request_info(request); if (!cgi && !fastcgi) { while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) { @@ -2150,7 +2140,6 @@ consult the installation file that came with this distribution, or visit \n\ case 'a': /* interactive mode */ printf("Interactive mode enabled\n\n"); - CG(interactive) = 1; break; case 'C': /* don't chdir to the script directory */ @@ -2173,16 +2162,16 @@ consult the installation file that came with this distribution, or visit \n\ if (script_file) { efree(script_file); } - if (php_request_startup(TSRMLS_C) == FAILURE) { + if (php_request_startup() == FAILURE) { SG(server_context) = NULL; - php_module_shutdown(TSRMLS_C); + php_module_shutdown(); return FAILURE; } if (no_headers) { SG(headers_sent) = 1; SG(request_info).no_headers = 1; } - php_print_info(0xFFFFFFFF TSRMLS_CC); + php_print_info(0xFFFFFFFF); php_request_shutdown((void *) 0); fcgi_shutdown(); exit_status = 0; @@ -2199,21 +2188,15 @@ consult the installation file that came with this distribution, or visit \n\ } SG(headers_sent) = 1; php_printf("[PHP Modules]\n"); - print_modules(TSRMLS_C); + print_modules(); php_printf("\n[Zend Modules]\n"); - print_extensions(TSRMLS_C); + print_extensions(); php_printf("\n"); - php_output_end_all(TSRMLS_C); + php_output_end_all(); fcgi_shutdown(); exit_status = 0; goto out; -#if 0 /* not yet operational, see also below ... */ - case '': /* generate indented source mode*/ - behavior=PHP_MODE_INDENT; - break; -#endif - case 'q': /* do not generate HTTP headers */ no_headers = 1; break; @@ -2223,9 +2206,9 @@ consult the installation file that came with this distribution, or visit \n\ efree(script_file); } no_headers = 1; - if (php_request_startup(TSRMLS_C) == FAILURE) { + if (php_request_startup() == FAILURE) { SG(server_context) = NULL; - php_module_shutdown(TSRMLS_C); + php_module_shutdown(); return FAILURE; } if (no_headers) { @@ -2257,7 +2240,7 @@ consult the installation file that came with this distribution, or visit \n\ if (script_file) { /* override path_translated if -f on command line */ - STR_FREE(SG(request_info).path_translated); + if (SG(request_info).path_translated) efree(SG(request_info).path_translated); SG(request_info).path_translated = script_file; /* before registering argv to module exchange the *new* argv[0] */ /* we can achieve this without allocating more memory */ @@ -2266,7 +2249,7 @@ consult the installation file that came with this distribution, or visit \n\ SG(request_info).argv[0] = script_file; } else if (argc > php_optind) { /* file is on command line, but not in -f opt */ - STR_FREE(SG(request_info).path_translated); + if (SG(request_info).path_translated) efree(SG(request_info).path_translated); SG(request_info).path_translated = estrdup(argv[php_optind]); /* arguments after the file are considered script args */ SG(request_info).argc = argc - php_optind; @@ -2288,7 +2271,7 @@ consult the installation file that came with this distribution, or visit \n\ * test.php v1=test "v2=hello world!" */ if (!SG(request_info).query_string && argc > php_optind) { - int slen = strlen(PG(arg_separator).input); + size_t slen = strlen(PG(arg_separator).input); len = 0; for (i = php_optind; i < argc; i++) { if (i < (argc - 1)) { @@ -2332,12 +2315,12 @@ consult the installation file that came with this distribution, or visit \n\ /* request startup only after we've done all we can to * get path_translated */ - if (php_request_startup(TSRMLS_C) == FAILURE) { + if (php_request_startup() == FAILURE) { if (fastcgi) { fcgi_finish_request(request, 1); } SG(server_context) = NULL; - php_module_shutdown(TSRMLS_C); + php_module_shutdown(); return FAILURE; } if (no_headers) { @@ -2351,7 +2334,7 @@ consult the installation file that came with this distribution, or visit \n\ 2. we are running as cgi or fastcgi */ if (cgi || fastcgi || SG(request_info).path_translated) { - if (php_fopen_primary_script(&file_handle TSRMLS_CC) == FAILURE) { + if (php_fopen_primary_script(&file_handle) == FAILURE) { zend_try { if (errno == EACCES) { SG(sapi_headers).http_response_code = 403; @@ -2369,7 +2352,10 @@ consult the installation file that came with this distribution, or visit \n\ goto fastcgi_request_done; } - STR_FREE(SG(request_info).path_translated); + if (SG(request_info).path_translated) { + efree(SG(request_info).path_translated); + SG(request_info).path_translated = NULL; + } if (free_query_string && SG(request_info).query_string) { free(SG(request_info).query_string); @@ -2378,7 +2364,7 @@ consult the installation file that came with this distribution, or visit \n\ php_request_shutdown((void *) 0); SG(server_context) = NULL; - php_module_shutdown(TSRMLS_C); + php_module_shutdown(); sapi_shutdown(); #ifdef ZTS tsrm_shutdown(); @@ -2410,8 +2396,8 @@ consult the installation file that came with this distribution, or visit \n\ /* handle situations where line is terminated by \r\n */ if (c == '\r') { if (fgetc(file_handle.handle.fp) != '\n') { - long pos = ftell(file_handle.handle.fp); - fseek(file_handle.handle.fp, pos - 1, SEEK_SET); + zend_long pos = zend_ftell(file_handle.handle.fp); + zend_fseek(file_handle.handle.fp, pos - 1, SEEK_SET); } } CG(start_lineno) = 2; @@ -2428,7 +2414,7 @@ consult the installation file that came with this distribution, or visit \n\ /* handle situations where line is terminated by \r\n */ if (c == '\r') { if (php_stream_getc((php_stream*)file_handle.handle.stream.handle) != '\n') { - long pos = php_stream_tell((php_stream*)file_handle.handle.stream.handle); + zend_off_t pos = php_stream_tell((php_stream*)file_handle.handle.stream.handle); php_stream_seek((php_stream*)file_handle.handle.stream.handle, pos - 1, SEEK_SET); } } @@ -2439,7 +2425,7 @@ consult the installation file that came with this distribution, or visit \n\ break; case ZEND_HANDLE_MAPPED: if (file_handle.handle.stream.mmap.buf[0] == '#') { - int i = 1; + size_t i = 1; c = file_handle.handle.stream.mmap.buf[i++]; while (c != '\n' && c != '\r' && i < file_handle.handle.stream.mmap.len) { @@ -2464,11 +2450,11 @@ consult the installation file that came with this distribution, or visit \n\ switch (behavior) { case PHP_MODE_STANDARD: - php_execute_script(&file_handle TSRMLS_CC); + php_execute_script(&file_handle); break; case PHP_MODE_LINT: PG(during_request_startup) = 0; - exit_status = php_lint_script(&file_handle TSRMLS_CC); + exit_status = php_lint_script(&file_handle); if (exit_status == SUCCESS) { zend_printf("No syntax errors detected in %s\n", file_handle.filename); } else { @@ -2476,9 +2462,9 @@ consult the installation file that came with this distribution, or visit \n\ } break; case PHP_MODE_STRIP: - if (open_file_for_scanning(&file_handle TSRMLS_CC) == SUCCESS) { - zend_strip(TSRMLS_C); - zend_file_handle_dtor(&file_handle TSRMLS_CC); + if (open_file_for_scanning(&file_handle) == SUCCESS) { + zend_strip(); + zend_file_handle_dtor(&file_handle); php_output_teardown(); } return SUCCESS; @@ -2487,33 +2473,26 @@ consult the installation file that came with this distribution, or visit \n\ { zend_syntax_highlighter_ini syntax_highlighter_ini; - if (open_file_for_scanning(&file_handle TSRMLS_CC) == SUCCESS) { + if (open_file_for_scanning(&file_handle) == SUCCESS) { php_get_highlight_struct(&syntax_highlighter_ini); - zend_highlight(&syntax_highlighter_ini TSRMLS_CC); + zend_highlight(&syntax_highlighter_ini); if (fastcgi) { goto fastcgi_request_done; } - zend_file_handle_dtor(&file_handle TSRMLS_CC); + zend_file_handle_dtor(&file_handle); php_output_teardown(); } return SUCCESS; } break; -#if 0 - /* Zeev might want to do something with this one day */ - case PHP_MODE_INDENT: - open_file_for_scanning(&file_handle TSRMLS_CC); - zend_indent(); - zend_file_handle_dtor(&file_handle TSRMLS_CC); - php_output_teardown(); - return SUCCESS; - break; -#endif } fastcgi_request_done: { - STR_FREE(SG(request_info).path_translated); + if (SG(request_info).path_translated) { + efree(SG(request_info).path_translated); + SG(request_info).path_translated = NULL; + } php_request_shutdown((void *) 0); @@ -2529,12 +2508,24 @@ fastcgi_request_done: if (!fastcgi) { if (benchmark) { - repeats--; - if (repeats > 0) { - script_file = NULL; - php_optind = orig_optind; - php_optarg = orig_optarg; + if (warmup_repeats) { + warmup_repeats--; + if (!warmup_repeats) { +#ifdef HAVE_GETTIMEOFDAY + gettimeofday(&start, NULL); +#else + time(&start); +#endif + } continue; + } else { + repeats--; + if (repeats > 0) { + script_file = NULL; + php_optind = orig_optind; + php_optarg = orig_optarg; + continue; + } } } break; @@ -2555,6 +2546,7 @@ fastcgi_request_done: } /* end of fastcgi loop */ } + if (request) { fcgi_destroy_request(request); } @@ -2597,7 +2589,7 @@ parent_out: #endif SG(server_context) = NULL; - php_module_shutdown(TSRMLS_C); + php_module_shutdown(); sapi_shutdown(); #ifdef ZTS diff --git a/sapi/cgi/config.w32 b/sapi/cgi/config.w32 index 8d1d431da4..4e803fb1c4 100644 --- a/sapi/cgi/config.w32 +++ b/sapi/cgi/config.w32 @@ -4,7 +4,8 @@ ARG_ENABLE('cgi', 'Build CGI version of PHP', 'yes'); if (PHP_CGI == "yes") { - ADD_FLAG("LDFLAGS_CGI", "/stack:8388608"); - SAPI('cgi', 'cgi_main.c fastcgi.c', 'php-cgi.exe'); + ADD_FLAG("LDFLAGS_CGI", "/stack:67108864"); + SAPI('cgi', 'cgi_main.c', 'php-cgi.exe', '/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1'); + ADD_SOURCES('main', 'fastcgi.c', 'cgi'); ADD_FLAG('LIBS_CGI', 'ws2_32.lib kernel32.lib advapi32.lib'); } diff --git a/sapi/cgi/config9.m4 b/sapi/cgi/config9.m4 index 16ee22f39c..f544426202 100644 --- a/sapi/cgi/config9.m4 +++ b/sapi/cgi/config9.m4 @@ -50,21 +50,21 @@ if test "$PHP_CGI" != "no"; then esac dnl Select SAPI - PHP_SELECT_SAPI(cgi, program, cgi_main.c fastcgi.c,, '$(SAPI_CGI_PATH)') + PHP_SELECT_SAPI(cgi, program, cgi_main.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1, '$(SAPI_CGI_PATH)') case $host_alias in *aix*) if test "$php_sapi_module" = "shared"; then - BUILD_CGI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CGI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/.libs\/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)" + BUILD_CGI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CGI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/.libs\/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)" else - BUILD_CGI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CGI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)" + BUILD_CGI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CGI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)" fi ;; *darwin*) - BUILD_CGI="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_CGI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)" + BUILD_CGI="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_FASTCGI_OBJS:.lo=.o) \$(PHP_CGI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)" ;; *) - BUILD_CGI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)" + BUILD_CGI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)" ;; esac diff --git a/sapi/cgi/fastcgi.c b/sapi/cgi/fastcgi.c deleted file mode 100644 index 5502c99b01..0000000000 --- a/sapi/cgi/fastcgi.c +++ /dev/null @@ -1,1546 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Dmitry Stogov <dmitry@zend.com> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#include "php.h" -#include "fastcgi.h" - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <errno.h> - -#ifndef MAXFQDNLEN -#define MAXFQDNLEN 255 -#endif - -#ifdef _WIN32 - -#include <windows.h> - - typedef unsigned int in_addr_t; - - struct sockaddr_un { - short sun_family; - char sun_path[MAXPATHLEN]; - }; - - static HANDLE fcgi_accept_mutex = INVALID_HANDLE_VALUE; - static int is_impersonate = 0; - -#define FCGI_LOCK(fd) \ - if (fcgi_accept_mutex != INVALID_HANDLE_VALUE) { \ - DWORD ret; \ - while ((ret = WaitForSingleObject(fcgi_accept_mutex, 1000)) == WAIT_TIMEOUT) { \ - if (in_shutdown) return -1; \ - } \ - if (ret == WAIT_FAILED) { \ - fprintf(stderr, "WaitForSingleObject() failed\n"); \ - return -1; \ - } \ - } - -#define FCGI_UNLOCK(fd) \ - if (fcgi_accept_mutex != INVALID_HANDLE_VALUE) { \ - ReleaseMutex(fcgi_accept_mutex); \ - } - -#else - -# include <sys/types.h> -# include <sys/stat.h> -# include <unistd.h> -# include <fcntl.h> -# include <sys/socket.h> -# include <sys/un.h> -# include <netinet/in.h> -# include <netinet/tcp.h> -# include <arpa/inet.h> -# include <netdb.h> -# include <signal.h> - -# define closesocket(s) close(s) - -# if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL) -# include <sys/poll.h> -# endif -# if defined(HAVE_SYS_SELECT_H) -# include <sys/select.h> -# endif - -#ifndef INADDR_NONE -#define INADDR_NONE ((unsigned long) -1) -#endif - -# ifndef HAVE_SOCKLEN_T - typedef unsigned int socklen_t; -# endif - -# ifdef USE_LOCKING -# define FCGI_LOCK(fd) \ - do { \ - struct flock lock; \ - lock.l_type = F_WRLCK; \ - lock.l_start = 0; \ - lock.l_whence = SEEK_SET; \ - lock.l_len = 0; \ - if (fcntl(fd, F_SETLKW, &lock) != -1) { \ - break; \ - } else if (errno != EINTR || in_shutdown) { \ - return -1; \ - } \ - } while (1) - -# define FCGI_UNLOCK(fd) \ - do { \ - int orig_errno = errno; \ - while (1) { \ - struct flock lock; \ - lock.l_type = F_UNLCK; \ - lock.l_start = 0; \ - lock.l_whence = SEEK_SET; \ - lock.l_len = 0; \ - if (fcntl(fd, F_SETLK, &lock) != -1) { \ - break; \ - } else if (errno != EINTR) { \ - return -1; \ - } \ - } \ - errno = orig_errno; \ - } while (0) -# else -# define FCGI_LOCK(fd) -# define FCGI_UNLOCK(fd) -# endif - -#endif - -typedef union _sa_t { - struct sockaddr sa; - struct sockaddr_un sa_unix; - struct sockaddr_in sa_inet; -} sa_t; - -static HashTable fcgi_mgmt_vars; - -static int is_initialized = 0; -static int is_fastcgi = 0; -static int in_shutdown = 0; -static in_addr_t *allowed_clients = NULL; - -/* hash table */ - -#define FCGI_HASH_TABLE_SIZE 128 -#define FCGI_HASH_TABLE_MASK (FCGI_HASH_TABLE_SIZE - 1) -#define FCGI_HASH_SEG_SIZE 4096 - -typedef struct _fcgi_hash_bucket { - unsigned int hash_value; - unsigned int var_len; - char *var; - unsigned int val_len; - char *val; - struct _fcgi_hash_bucket *next; - struct _fcgi_hash_bucket *list_next; -} fcgi_hash_bucket; - -typedef struct _fcgi_hash_buckets { - unsigned int idx; - struct _fcgi_hash_buckets *next; - struct _fcgi_hash_bucket data[FCGI_HASH_TABLE_SIZE]; -} fcgi_hash_buckets; - -typedef struct _fcgi_data_seg { - char *pos; - char *end; - struct _fcgi_data_seg *next; - char data[1]; -} fcgi_data_seg; - -typedef struct _fcgi_hash { - fcgi_hash_bucket *hash_table[FCGI_HASH_TABLE_SIZE]; - fcgi_hash_bucket *list; - fcgi_hash_buckets *buckets; - fcgi_data_seg *data; -} fcgi_hash; - -static void fcgi_hash_init(fcgi_hash *h) -{ - memset(h->hash_table, 0, sizeof(h->hash_table)); - h->list = NULL; - h->buckets = (fcgi_hash_buckets*)malloc(sizeof(fcgi_hash_buckets)); - h->buckets->idx = 0; - h->buckets->next = NULL; - h->data = (fcgi_data_seg*)malloc(sizeof(fcgi_data_seg) - 1 + FCGI_HASH_SEG_SIZE); - h->data->pos = h->data->data; - h->data->end = h->data->pos + FCGI_HASH_SEG_SIZE; - h->data->next = NULL; -} - -static void fcgi_hash_destroy(fcgi_hash *h) -{ - fcgi_hash_buckets *b; - fcgi_data_seg *p; - - b = h->buckets; - while (b) { - fcgi_hash_buckets *q = b; - b = b->next; - free(q); - } - p = h->data; - while (p) { - fcgi_data_seg *q = p; - p = p->next; - free(q); - } -} - -static void fcgi_hash_clean(fcgi_hash *h) -{ - memset(h->hash_table, 0, sizeof(h->hash_table)); - h->list = NULL; - /* delete all bucket blocks except the first one */ - while (h->buckets->next) { - fcgi_hash_buckets *q = h->buckets; - - h->buckets = h->buckets->next; - free(q); - } - h->buckets->idx = 0; - /* delete all data segments except the first one */ - while (h->data->next) { - fcgi_data_seg *q = h->data; - - h->data = h->data->next; - free(q); - } - h->data->pos = h->data->data; -} - -static inline char* fcgi_hash_strndup(fcgi_hash *h, char *str, unsigned int str_len) -{ - char *ret; - - if (UNEXPECTED(h->data->pos + str_len + 1 >= h->data->end)) { - unsigned int seg_size = (str_len + 1 > FCGI_HASH_SEG_SIZE) ? str_len + 1 : FCGI_HASH_SEG_SIZE; - fcgi_data_seg *p = (fcgi_data_seg*)malloc(sizeof(fcgi_data_seg) - 1 + seg_size); - - p->pos = p->data; - p->end = p->pos + seg_size; - p->next = h->data; - h->data = p; - } - ret = h->data->pos; - memcpy(ret, str, str_len); - ret[str_len] = 0; - h->data->pos += str_len + 1; - return ret; -} - -static char* fcgi_hash_set(fcgi_hash *h, unsigned int hash_value, char *var, unsigned int var_len, char *val, unsigned int val_len) -{ - unsigned int idx = hash_value & FCGI_HASH_TABLE_MASK; - fcgi_hash_bucket *p = h->hash_table[idx]; - - while (UNEXPECTED(p != NULL)) { - if (UNEXPECTED(p->hash_value == hash_value) && - p->var_len == var_len && - memcmp(p->var, var, var_len) == 0) { - - p->val_len = val_len; - p->val = fcgi_hash_strndup(h, val, val_len); - return p->val; - } - p = p->next; - } - - if (UNEXPECTED(h->buckets->idx >= FCGI_HASH_TABLE_SIZE)) { - fcgi_hash_buckets *b = (fcgi_hash_buckets*)malloc(sizeof(fcgi_hash_buckets)); - b->idx = 0; - b->next = h->buckets; - h->buckets = b; - } - p = h->buckets->data + h->buckets->idx; - h->buckets->idx++; - p->next = h->hash_table[idx]; - h->hash_table[idx] = p; - p->list_next = h->list; - h->list = p; - p->hash_value = hash_value; - p->var_len = var_len; - p->var = fcgi_hash_strndup(h, var, var_len); - p->val_len = val_len; - p->val = fcgi_hash_strndup(h, val, val_len); - return p->val; -} - -static void fcgi_hash_del(fcgi_hash *h, unsigned int hash_value, char *var, unsigned int var_len) -{ - unsigned int idx = hash_value & FCGI_HASH_TABLE_MASK; - fcgi_hash_bucket **p = &h->hash_table[idx]; - - while (*p != NULL) { - if ((*p)->hash_value == hash_value && - (*p)->var_len == var_len && - memcmp((*p)->var, var, var_len) == 0) { - - (*p)->val = NULL; /* NULL value means deleted */ - (*p)->val_len = 0; - *p = (*p)->next; - return; - } - p = &(*p)->next; - } -} - -static char *fcgi_hash_get(fcgi_hash *h, unsigned int hash_value, char *var, unsigned int var_len, unsigned int *val_len) -{ - unsigned int idx = hash_value & FCGI_HASH_TABLE_MASK; - fcgi_hash_bucket *p = h->hash_table[idx]; - - while (p != NULL) { - if (p->hash_value == hash_value && - p->var_len == var_len && - memcmp(p->var, var, var_len) == 0) { - *val_len = p->val_len; - return p->val; - } - p = p->next; - } - return NULL; -} - -static void fcgi_hash_apply(fcgi_hash *h, fcgi_apply_func func, void *arg TSRMLS_DC) -{ - fcgi_hash_bucket *p = h->list; - - while (p) { - if (EXPECTED(p->val != NULL)) { - func(p->var, p->var_len, p->val, p->val_len, arg TSRMLS_CC); - } - p = p->list_next; - } -} - -struct _fcgi_request { - int listen_socket; - int tcp; - int fd; - int id; - int keep; -#ifdef TCP_NODELAY - int nodelay; -#endif - int closed; - - int in_len; - int in_pad; - - fcgi_header *out_hdr; - unsigned char *out_pos; - unsigned char out_buf[1024*8]; - unsigned char reserved[sizeof(fcgi_end_request_rec)]; - - int has_env; - fcgi_hash env; -}; - -#ifdef _WIN32 - -static DWORD WINAPI fcgi_shutdown_thread(LPVOID arg) -{ - HANDLE shutdown_event = (HANDLE) arg; - WaitForSingleObject(shutdown_event, INFINITE); - in_shutdown = 1; - return 0; -} - -#else - -static void fcgi_signal_handler(int signo) -{ - if (signo == SIGUSR1 || signo == SIGTERM) { - in_shutdown = 1; - } -} - -static void fcgi_setup_signals(void) -{ - struct sigaction new_sa, old_sa; - - sigemptyset(&new_sa.sa_mask); - new_sa.sa_flags = 0; - new_sa.sa_handler = fcgi_signal_handler; - sigaction(SIGUSR1, &new_sa, NULL); - sigaction(SIGTERM, &new_sa, NULL); - sigaction(SIGPIPE, NULL, &old_sa); - if (old_sa.sa_handler == SIG_DFL) { - sigaction(SIGPIPE, &new_sa, NULL); - } -} -#endif - -int fcgi_in_shutdown(void) -{ - return in_shutdown; -} - -void fcgi_terminate(void) -{ - in_shutdown = 1; -} - -int fcgi_init(void) -{ - if (!is_initialized) { -#ifndef _WIN32 - sa_t sa; - socklen_t len = sizeof(sa); -#endif - zend_hash_init(&fcgi_mgmt_vars, 0, NULL, fcgi_free_mgmt_var_cb, 1); - fcgi_set_mgmt_var("FCGI_MPXS_CONNS", sizeof("FCGI_MPXS_CONNS")-1, "0", sizeof("0")-1); - - is_initialized = 1; -#ifdef _WIN32 -# if 0 - /* TODO: Support for TCP sockets */ - WSADATA wsaData; - - if (WSAStartup(MAKEWORD(2,0), &wsaData)) { - fprintf(stderr, "Error starting Windows Sockets. Error: %d", WSAGetLastError()); - return 0; - } -# endif - if ((GetStdHandle(STD_OUTPUT_HANDLE) == INVALID_HANDLE_VALUE) && - (GetStdHandle(STD_ERROR_HANDLE) == INVALID_HANDLE_VALUE) && - (GetStdHandle(STD_INPUT_HANDLE) != INVALID_HANDLE_VALUE)) { - char *str; - DWORD pipe_mode = PIPE_READMODE_BYTE | PIPE_WAIT; - HANDLE pipe = GetStdHandle(STD_INPUT_HANDLE); - - SetNamedPipeHandleState(pipe, &pipe_mode, NULL, NULL); - - str = getenv("_FCGI_SHUTDOWN_EVENT_"); - if (str != NULL) { - HANDLE shutdown_event = (HANDLE) atoi(str); - if (!CreateThread(NULL, 0, fcgi_shutdown_thread, - shutdown_event, 0, NULL)) { - return -1; - } - } - str = getenv("_FCGI_MUTEX_"); - if (str != NULL) { - fcgi_accept_mutex = (HANDLE) atoi(str); - } - return is_fastcgi = 1; - } else { - return is_fastcgi = 0; - } -#else - errno = 0; - if (getpeername(0, (struct sockaddr *)&sa, &len) != 0 && errno == ENOTCONN) { - fcgi_setup_signals(); - return is_fastcgi = 1; - } else { - return is_fastcgi = 0; - } -#endif - } - return is_fastcgi; -} - - -int fcgi_is_fastcgi(void) -{ - if (!is_initialized) { - return fcgi_init(); - } else { - return is_fastcgi; - } -} - -void fcgi_shutdown(void) -{ - if (is_initialized) { - zend_hash_destroy(&fcgi_mgmt_vars); - } - is_fastcgi = 0; - if (allowed_clients) { - free(allowed_clients); - } -} - -#ifdef _WIN32 -/* Do some black magic with the NT security API. - * We prepare a DACL (Discretionary Access Control List) so that - * we, the creator, are allowed all access, while "Everyone Else" - * is only allowed to read and write to the pipe. - * This avoids security issues on shared hosts where a luser messes - * with the lower-level pipe settings and screws up the FastCGI service. - */ -static PACL prepare_named_pipe_acl(PSECURITY_DESCRIPTOR sd, LPSECURITY_ATTRIBUTES sa) -{ - DWORD req_acl_size; - char everyone_buf[32], owner_buf[32]; - PSID sid_everyone, sid_owner; - SID_IDENTIFIER_AUTHORITY - siaWorld = SECURITY_WORLD_SID_AUTHORITY, - siaCreator = SECURITY_CREATOR_SID_AUTHORITY; - PACL acl; - - sid_everyone = (PSID)&everyone_buf; - sid_owner = (PSID)&owner_buf; - - req_acl_size = sizeof(ACL) + - (2 * ((sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) + GetSidLengthRequired(1))); - - acl = malloc(req_acl_size); - - if (acl == NULL) { - return NULL; - } - - if (!InitializeSid(sid_everyone, &siaWorld, 1)) { - goto out_fail; - } - *GetSidSubAuthority(sid_everyone, 0) = SECURITY_WORLD_RID; - - if (!InitializeSid(sid_owner, &siaCreator, 1)) { - goto out_fail; - } - *GetSidSubAuthority(sid_owner, 0) = SECURITY_CREATOR_OWNER_RID; - - if (!InitializeAcl(acl, req_acl_size, ACL_REVISION)) { - goto out_fail; - } - - if (!AddAccessAllowedAce(acl, ACL_REVISION, FILE_GENERIC_READ | FILE_GENERIC_WRITE, sid_everyone)) { - goto out_fail; - } - - if (!AddAccessAllowedAce(acl, ACL_REVISION, FILE_ALL_ACCESS, sid_owner)) { - goto out_fail; - } - - if (!InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION)) { - goto out_fail; - } - - if (!SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE)) { - goto out_fail; - } - - sa->lpSecurityDescriptor = sd; - - return acl; - -out_fail: - free(acl); - return NULL; -} -#endif - -static int is_port_number(const char *bindpath) -{ - while (*bindpath) { - if (*bindpath < '0' || *bindpath > '9') { - return 0; - } - bindpath++; - } - return 1; -} - -int fcgi_listen(const char *path, int backlog) -{ - char *s; - int tcp = 0; - char host[MAXPATHLEN]; - short port = 0; - int listen_socket; - sa_t sa; - socklen_t sock_len; -#ifdef SO_REUSEADDR -# ifdef _WIN32 - BOOL reuse = 1; -# else - int reuse = 1; -# endif -#endif - - if ((s = strchr(path, ':'))) { - port = atoi(s+1); - if (port != 0 && (s-path) < MAXPATHLEN) { - strncpy(host, path, s-path); - host[s-path] = '\0'; - tcp = 1; - } - } else if (is_port_number(path)) { - port = atoi(path); - if (port != 0) { - host[0] = '\0'; - tcp = 1; - } - } - - /* Prepare socket address */ - if (tcp) { - memset(&sa.sa_inet, 0, sizeof(sa.sa_inet)); - sa.sa_inet.sin_family = AF_INET; - sa.sa_inet.sin_port = htons(port); - sock_len = sizeof(sa.sa_inet); - - if (!*host || !strncmp(host, "*", sizeof("*")-1)) { - sa.sa_inet.sin_addr.s_addr = htonl(INADDR_ANY); - } else { - sa.sa_inet.sin_addr.s_addr = inet_addr(host); - if (sa.sa_inet.sin_addr.s_addr == INADDR_NONE) { - struct hostent *hep; - - if(strlen(host) > MAXFQDNLEN) { - hep = NULL; - } else { - hep = gethostbyname(host); - } - if (!hep || hep->h_addrtype != AF_INET || !hep->h_addr_list[0]) { - fprintf(stderr, "Cannot resolve host name '%s'!\n", host); - return -1; - } else if (hep->h_addr_list[1]) { - fprintf(stderr, "Host '%s' has multiple addresses. You must choose one explicitly!\n", host); - return -1; - } - sa.sa_inet.sin_addr.s_addr = ((struct in_addr*)hep->h_addr_list[0])->s_addr; - } - } - } else { -#ifdef _WIN32 - SECURITY_DESCRIPTOR sd; - SECURITY_ATTRIBUTES saw; - PACL acl; - HANDLE namedPipe; - - memset(&sa, 0, sizeof(saw)); - saw.nLength = sizeof(saw); - saw.bInheritHandle = FALSE; - acl = prepare_named_pipe_acl(&sd, &saw); - - namedPipe = CreateNamedPipe(path, - PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, - PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_READMODE_BYTE, - PIPE_UNLIMITED_INSTANCES, - 8192, 8192, 0, &saw); - if (namedPipe == INVALID_HANDLE_VALUE) { - return -1; - } - listen_socket = _open_osfhandle((long)namedPipe, 0); - if (!is_initialized) { - fcgi_init(); - } - is_fastcgi = 1; - return listen_socket; - -#else - int path_len = strlen(path); - - if (path_len >= sizeof(sa.sa_unix.sun_path)) { - fprintf(stderr, "Listening socket's path name is too long.\n"); - return -1; - } - - memset(&sa.sa_unix, 0, sizeof(sa.sa_unix)); - sa.sa_unix.sun_family = AF_UNIX; - memcpy(sa.sa_unix.sun_path, path, path_len + 1); - sock_len = (size_t)(((struct sockaddr_un *)0)->sun_path) + path_len; -#ifdef HAVE_SOCKADDR_UN_SUN_LEN - sa.sa_unix.sun_len = sock_len; -#endif - unlink(path); -#endif - } - - /* Create, bind socket and start listen on it */ - if ((listen_socket = socket(sa.sa.sa_family, SOCK_STREAM, 0)) < 0 || -#ifdef SO_REUSEADDR - setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)) < 0 || -#endif - bind(listen_socket, (struct sockaddr *) &sa, sock_len) < 0 || - listen(listen_socket, backlog) < 0) { - - fprintf(stderr, "Cannot bind/listen socket - [%d] %s.\n",errno, strerror(errno)); - return -1; - } - - if (!tcp) { - chmod(path, 0777); - } else { - char *ip = getenv("FCGI_WEB_SERVER_ADDRS"); - char *cur, *end; - int n; - - if (ip) { - ip = strdup(ip); - cur = ip; - n = 0; - while (*cur) { - if (*cur == ',') n++; - cur++; - } - allowed_clients = malloc(sizeof(in_addr_t) * (n+2)); - n = 0; - cur = ip; - while (cur) { - end = strchr(cur, ','); - if (end) { - *end = 0; - end++; - } - allowed_clients[n] = inet_addr(cur); - if (allowed_clients[n] == INADDR_NONE) { - fprintf(stderr, "Wrong IP address '%s' in FCGI_WEB_SERVER_ADDRS\n", cur); - } - n++; - cur = end; - } - allowed_clients[n] = INADDR_NONE; - free(ip); - } - } - - if (!is_initialized) { - fcgi_init(); - } - is_fastcgi = 1; - -#ifdef _WIN32 - if (tcp) { - listen_socket = _open_osfhandle((long)listen_socket, 0); - } -#else - fcgi_setup_signals(); -#endif - return listen_socket; -} - -fcgi_request *fcgi_init_request(int listen_socket) -{ - fcgi_request *req = (fcgi_request*)calloc(1, sizeof(fcgi_request)); - req->listen_socket = listen_socket; - req->fd = -1; - req->id = -1; - - req->in_len = 0; - req->in_pad = 0; - - req->out_hdr = NULL; - req->out_pos = req->out_buf; - -#ifdef _WIN32 - req->tcp = !GetNamedPipeInfo((HANDLE)_get_osfhandle(req->listen_socket), NULL, NULL, NULL, NULL); -#endif - -#ifdef TCP_NODELAY - req->nodelay = 0; -#endif - - fcgi_hash_init(&req->env); - - return req; -} - -void fcgi_destroy_request(fcgi_request *req) -{ - fcgi_hash_destroy(&req->env); - free(req); -} - -static inline ssize_t safe_write(fcgi_request *req, const void *buf, size_t count) -{ - int ret; - size_t n = 0; - - do { - errno = 0; -#ifdef _WIN32 - if (!req->tcp) { - ret = write(req->fd, ((char*)buf)+n, count-n); - } else { - ret = send(req->fd, ((char*)buf)+n, count-n, 0); - if (ret <= 0) { - errno = WSAGetLastError(); - } - } -#else - ret = write(req->fd, ((char*)buf)+n, count-n); -#endif - if (ret > 0) { - n += ret; - } else if (ret <= 0 && errno != 0 && errno != EINTR) { - return ret; - } - } while (n != count); - return n; -} - -static inline ssize_t safe_read(fcgi_request *req, const void *buf, size_t count) -{ - int ret; - size_t n = 0; - - do { - errno = 0; -#ifdef _WIN32 - if (!req->tcp) { - ret = read(req->fd, ((char*)buf)+n, count-n); - } else { - ret = recv(req->fd, ((char*)buf)+n, count-n, 0); - if (ret <= 0) { - errno = WSAGetLastError(); - } - } -#else - ret = read(req->fd, ((char*)buf)+n, count-n); -#endif - if (ret > 0) { - n += ret; - } else if (ret == 0 && errno == 0) { - return n; - } else if (ret <= 0 && errno != 0 && errno != EINTR) { - return ret; - } - } while (n != count); - return n; -} - -static inline int fcgi_make_header(fcgi_header *hdr, fcgi_request_type type, int req_id, int len) -{ - int pad = ((len + 7) & ~7) - len; - - hdr->contentLengthB0 = (unsigned char)(len & 0xff); - hdr->contentLengthB1 = (unsigned char)((len >> 8) & 0xff); - hdr->paddingLength = (unsigned char)pad; - hdr->requestIdB0 = (unsigned char)(req_id & 0xff); - hdr->requestIdB1 = (unsigned char)((req_id >> 8) & 0xff); - hdr->reserved = 0; - hdr->type = type; - hdr->version = FCGI_VERSION_1; - if (pad) { - memset(((unsigned char*)hdr) + sizeof(fcgi_header) + len, 0, pad); - } - return pad; -} - -static int fcgi_get_params(fcgi_request *req, unsigned char *p, unsigned char *end) -{ - unsigned int name_len, val_len; - - while (p < end) { - name_len = *p++; - if (UNEXPECTED(name_len >= 128)) { - if (UNEXPECTED(p + 3 >= end)) return 0; - name_len = ((name_len & 0x7f) << 24); - name_len |= (*p++ << 16); - name_len |= (*p++ << 8); - name_len |= *p++; - } - if (UNEXPECTED(p >= end)) return 0; - val_len = *p++; - if (UNEXPECTED(val_len >= 128)) { - if (UNEXPECTED(p + 3 >= end)) return 0; - val_len = ((val_len & 0x7f) << 24); - val_len |= (*p++ << 16); - val_len |= (*p++ << 8); - val_len |= *p++; - } - if (UNEXPECTED(name_len + val_len > (unsigned int) (end - p))) { - /* Malformated request */ - return 0; - } - fcgi_hash_set(&req->env, FCGI_HASH_FUNC(p, name_len), (char*)p, name_len, (char*)p + name_len, val_len); - p += name_len + val_len; - } - return 1; -} - -static int fcgi_read_request(fcgi_request *req) -{ - fcgi_header hdr; - int len, padding; - unsigned char buf[FCGI_MAX_LENGTH+8]; - - req->keep = 0; - req->closed = 0; - req->in_len = 0; - req->out_hdr = NULL; - req->out_pos = req->out_buf; - req->has_env = 1; - - if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || - hdr.version < FCGI_VERSION_1) { - return 0; - } - - len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; - padding = hdr.paddingLength; - - while (hdr.type == FCGI_STDIN && len == 0) { - if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || - hdr.version < FCGI_VERSION_1) { - return 0; - } - - len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; - padding = hdr.paddingLength; - } - - if (len + padding > FCGI_MAX_LENGTH) { - return 0; - } - - req->id = (hdr.requestIdB1 << 8) + hdr.requestIdB0; - - if (hdr.type == FCGI_BEGIN_REQUEST && len == sizeof(fcgi_begin_request)) { - if (safe_read(req, buf, len+padding) != len+padding) { - return 0; - } - - req->keep = (((fcgi_begin_request*)buf)->flags & FCGI_KEEP_CONN); -#ifdef TCP_NODELAY - if (req->keep && req->tcp && !req->nodelay) { -# ifdef _WIN32 - BOOL on = 1; -# else - int on = 1; -# endif - - setsockopt(req->fd, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on)); - req->nodelay = 1; - } -#endif - switch ((((fcgi_begin_request*)buf)->roleB1 << 8) + ((fcgi_begin_request*)buf)->roleB0) { - case FCGI_RESPONDER: - fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "RESPONDER", sizeof("RESPONDER")-1); - break; - case FCGI_AUTHORIZER: - fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "AUTHORIZER", sizeof("AUTHORIZER")-1); - break; - case FCGI_FILTER: - fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "FILTER", sizeof("FILTER")-1); - break; - default: - return 0; - } - - if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || - hdr.version < FCGI_VERSION_1) { - return 0; - } - - len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; - padding = hdr.paddingLength; - - while (hdr.type == FCGI_PARAMS && len > 0) { - if (len + padding > FCGI_MAX_LENGTH) { - return 0; - } - - if (safe_read(req, buf, len+padding) != len+padding) { - req->keep = 0; - return 0; - } - - if (!fcgi_get_params(req, buf, buf+len)) { - req->keep = 0; - return 0; - } - - if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || - hdr.version < FCGI_VERSION_1) { - req->keep = 0; - return 0; - } - len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; - padding = hdr.paddingLength; - } - } else if (hdr.type == FCGI_GET_VALUES) { - unsigned char *p = buf + sizeof(fcgi_header); - zval ** value; - unsigned int zlen; - fcgi_hash_bucket *q; - - if (safe_read(req, buf, len+padding) != len+padding) { - req->keep = 0; - return 0; - } - - if (!fcgi_get_params(req, buf, buf+len)) { - req->keep = 0; - return 0; - } - - q = req->env.list; - while (q != NULL) { - if (zend_hash_find(&fcgi_mgmt_vars, q->var, q->var_len, (void**) &value) != SUCCESS) { - q = q->list_next; - continue; - } - zlen = Z_STRLEN_PP(value); - if ((p + 4 + 4 + q->var_len + zlen) >= (buf + sizeof(buf))) { - break; - } - if (q->var_len < 0x80) { - *p++ = q->var_len; - } else { - *p++ = ((q->var_len >> 24) & 0xff) | 0x80; - *p++ = (q->var_len >> 16) & 0xff; - *p++ = (q->var_len >> 8) & 0xff; - *p++ = q->var_len & 0xff; - } - if (zlen < 0x80) { - *p++ = zlen; - } else { - *p++ = ((zlen >> 24) & 0xff) | 0x80; - *p++ = (zlen >> 16) & 0xff; - *p++ = (zlen >> 8) & 0xff; - *p++ = zlen & 0xff; - } - memcpy(p, q->var, q->var_len); - p += q->var_len; - memcpy(p, Z_STRVAL_PP(value), zlen); - p += zlen; - q = q->list_next; - } - len = p - buf - sizeof(fcgi_header); - len += fcgi_make_header((fcgi_header*)buf, FCGI_GET_VALUES_RESULT, 0, len); - if (safe_write(req, buf, sizeof(fcgi_header)+len) != (int)sizeof(fcgi_header)+len) { - req->keep = 0; - return 0; - } - return 0; - } else { - return 0; - } - - return 1; -} - -int fcgi_read(fcgi_request *req, char *str, int len) -{ - int ret, n, rest; - fcgi_header hdr; - unsigned char buf[255]; - - n = 0; - rest = len; - while (rest > 0) { - if (req->in_len == 0) { - if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || - hdr.version < FCGI_VERSION_1 || - hdr.type != FCGI_STDIN) { - req->keep = 0; - return 0; - } - req->in_len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; - req->in_pad = hdr.paddingLength; - if (req->in_len == 0) { - return n; - } - } - - if (req->in_len >= rest) { - ret = safe_read(req, str, rest); - } else { - ret = safe_read(req, str, req->in_len); - } - if (ret < 0) { - req->keep = 0; - return ret; - } else if (ret > 0) { - req->in_len -= ret; - rest -= ret; - n += ret; - str += ret; - if (req->in_len == 0) { - if (req->in_pad) { - if (safe_read(req, buf, req->in_pad) != req->in_pad) { - req->keep = 0; - return ret; - } - } - } else { - return n; - } - } else { - return n; - } - } - return n; -} - -static inline void fcgi_close(fcgi_request *req, int force, int destroy) -{ - if (destroy && req->has_env) { - fcgi_hash_clean(&req->env); - req->has_env = 0; - } - -#ifdef _WIN32 - if (is_impersonate && !req->tcp) { - RevertToSelf(); - } -#endif - - if ((force || !req->keep) && req->fd >= 0) { -#ifdef _WIN32 - if (!req->tcp) { - HANDLE pipe = (HANDLE)_get_osfhandle(req->fd); - - if (!force) { - FlushFileBuffers(pipe); - } - DisconnectNamedPipe(pipe); - } else { - if (!force) { - fcgi_header buf; - - shutdown(req->fd, 1); - /* read the last FCGI_STDIN header (it may be omitted) */ - recv(req->fd, (char *)(&buf), sizeof(buf), 0); - } - closesocket(req->fd); - } -#else - if (!force) { - fcgi_header buf; - - shutdown(req->fd, 1); - /* read the last FCGI_STDIN header (it may be omitted) */ - recv(req->fd, (char *)(&buf), sizeof(buf), 0); - } - close(req->fd); -#endif -#ifdef TCP_NODELAY - req->nodelay = 0; -#endif - req->fd = -1; - } -} - -int fcgi_accept_request(fcgi_request *req) -{ -#ifdef _WIN32 - HANDLE pipe; - OVERLAPPED ov; -#endif - - while (1) { - if (req->fd < 0) { - while (1) { - if (in_shutdown) { - return -1; - } -#ifdef _WIN32 - if (!req->tcp) { - pipe = (HANDLE)_get_osfhandle(req->listen_socket); - FCGI_LOCK(req->listen_socket); - ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if (!ConnectNamedPipe(pipe, &ov)) { - errno = GetLastError(); - if (errno == ERROR_IO_PENDING) { - while (WaitForSingleObject(ov.hEvent, 1000) == WAIT_TIMEOUT) { - if (in_shutdown) { - CloseHandle(ov.hEvent); - FCGI_UNLOCK(req->listen_socket); - return -1; - } - } - } else if (errno != ERROR_PIPE_CONNECTED) { - } - } - CloseHandle(ov.hEvent); - req->fd = req->listen_socket; - FCGI_UNLOCK(req->listen_socket); - } else { - SOCKET listen_socket = (SOCKET)_get_osfhandle(req->listen_socket); -#else - { - int listen_socket = req->listen_socket; -#endif - sa_t sa; - socklen_t len = sizeof(sa); - - FCGI_LOCK(req->listen_socket); - req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len); - FCGI_UNLOCK(req->listen_socket); - if (req->fd >= 0) { - if (((struct sockaddr *)&sa)->sa_family == AF_INET) { -#ifndef _WIN32 - req->tcp = 1; -#endif - if (allowed_clients) { - int n = 0; - int allowed = 0; - - while (allowed_clients[n] != INADDR_NONE) { - if (allowed_clients[n] == sa.sa_inet.sin_addr.s_addr) { - allowed = 1; - break; - } - n++; - } - if (!allowed) { - fprintf(stderr, "Connection from disallowed IP address '%s' is dropped.\n", inet_ntoa(sa.sa_inet.sin_addr)); - closesocket(req->fd); - req->fd = -1; - continue; - } - } -#ifndef _WIN32 - } else { - req->tcp = 0; -#endif - } - } - } - -#ifdef _WIN32 - if (req->fd < 0 && (in_shutdown || errno != EINTR)) { -#else - if (req->fd < 0 && (in_shutdown || (errno != EINTR && errno != ECONNABORTED))) { -#endif - return -1; - } - -#ifdef _WIN32 - break; -#else - if (req->fd >= 0) { -#if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL) - struct pollfd fds; - int ret; - - fds.fd = req->fd; - fds.events = POLLIN; - fds.revents = 0; - do { - errno = 0; - ret = poll(&fds, 1, 5000); - } while (ret < 0 && errno == EINTR); - if (ret > 0 && (fds.revents & POLLIN)) { - break; - } - fcgi_close(req, 1, 0); -#else - if (req->fd < FD_SETSIZE) { - struct timeval tv = {5,0}; - fd_set set; - int ret; - - FD_ZERO(&set); - FD_SET(req->fd, &set); - do { - errno = 0; - ret = select(req->fd + 1, &set, NULL, NULL, &tv) >= 0; - } while (ret < 0 && errno == EINTR); - if (ret > 0 && FD_ISSET(req->fd, &set)) { - break; - } - fcgi_close(req, 1, 0); - } else { - fprintf(stderr, "Too many open file descriptors. FD_SETSIZE limit exceeded."); - fcgi_close(req, 1, 0); - } -#endif - } -#endif - } - } else if (in_shutdown) { - return -1; - } - if (fcgi_read_request(req)) { -#ifdef _WIN32 - if (is_impersonate && !req->tcp) { - pipe = (HANDLE)_get_osfhandle(req->fd); - if (!ImpersonateNamedPipeClient(pipe)) { - fcgi_close(req, 1, 1); - continue; - } - } -#endif - return req->fd; - } else { - fcgi_close(req, 1, 1); - } - } -} - -static inline fcgi_header* open_packet(fcgi_request *req, fcgi_request_type type) -{ - req->out_hdr = (fcgi_header*) req->out_pos; - req->out_hdr->type = type; - req->out_pos += sizeof(fcgi_header); - return req->out_hdr; -} - -static inline void close_packet(fcgi_request *req) -{ - if (req->out_hdr) { - int len = req->out_pos - ((unsigned char*)req->out_hdr + sizeof(fcgi_header)); - - req->out_pos += fcgi_make_header(req->out_hdr, (fcgi_request_type)req->out_hdr->type, req->id, len); - req->out_hdr = NULL; - } -} - -int fcgi_flush(fcgi_request *req, int close) -{ - int len; - - close_packet(req); - - len = req->out_pos - req->out_buf; - - if (close) { - fcgi_end_request_rec *rec = (fcgi_end_request_rec*)(req->out_pos); - - fcgi_make_header(&rec->hdr, FCGI_END_REQUEST, req->id, sizeof(fcgi_end_request)); - rec->body.appStatusB3 = 0; - rec->body.appStatusB2 = 0; - rec->body.appStatusB1 = 0; - rec->body.appStatusB0 = 0; - rec->body.protocolStatus = FCGI_REQUEST_COMPLETE; - len += sizeof(fcgi_end_request_rec); - } - - if (safe_write(req, req->out_buf, len) != len) { - req->keep = 0; - req->out_pos = req->out_buf; - return 0; - } - - req->out_pos = req->out_buf; - return 1; -} - -int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len) -{ - int limit, rest; - - if (len <= 0) { - return 0; - } - - if (req->out_hdr && req->out_hdr->type != type) { - close_packet(req); - } -#if 0 - /* Unoptimized, but clear version */ - rest = len; - while (rest > 0) { - limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf); - - if (!req->out_hdr) { - if (limit < sizeof(fcgi_header)) { - if (!fcgi_flush(req, 0)) { - return -1; - } - } - open_packet(req, type); - } - limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf); - if (rest < limit) { - memcpy(req->out_pos, str, rest); - req->out_pos += rest; - return len; - } else { - memcpy(req->out_pos, str, limit); - req->out_pos += limit; - rest -= limit; - str += limit; - if (!fcgi_flush(req, 0)) { - return -1; - } - } - } -#else - /* Optimized version */ - limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf); - if (!req->out_hdr) { - limit -= sizeof(fcgi_header); - if (limit < 0) limit = 0; - } - - if (len < limit) { - if (!req->out_hdr) { - open_packet(req, type); - } - memcpy(req->out_pos, str, len); - req->out_pos += len; - } else if (len - limit < sizeof(req->out_buf) - sizeof(fcgi_header)) { - if (!req->out_hdr) { - open_packet(req, type); - } - if (limit > 0) { - memcpy(req->out_pos, str, limit); - req->out_pos += limit; - } - if (!fcgi_flush(req, 0)) { - return -1; - } - if (len > limit) { - open_packet(req, type); - memcpy(req->out_pos, str + limit, len - limit); - req->out_pos += len - limit; - } - } else { - int pos = 0; - int pad; - - close_packet(req); - while ((len - pos) > 0xffff) { - open_packet(req, type); - fcgi_make_header(req->out_hdr, type, req->id, 0xfff8); - req->out_hdr = NULL; - if (!fcgi_flush(req, 0)) { - return -1; - } - if (safe_write(req, str + pos, 0xfff8) != 0xfff8) { - req->keep = 0; - return -1; - } - pos += 0xfff8; - } - - pad = (((len - pos) + 7) & ~7) - (len - pos); - rest = pad ? 8 - pad : 0; - - open_packet(req, type); - fcgi_make_header(req->out_hdr, type, req->id, (len - pos) - rest); - req->out_hdr = NULL; - if (!fcgi_flush(req, 0)) { - return -1; - } - if (safe_write(req, str + pos, (len - pos) - rest) != (len - pos) - rest) { - req->keep = 0; - return -1; - } - if (pad) { - open_packet(req, type); - memcpy(req->out_pos, str + len - rest, rest); - req->out_pos += rest; - } - } -#endif - return len; -} - -int fcgi_finish_request(fcgi_request *req, int force_close) -{ - int ret = 1; - - if (req->fd >= 0) { - if (!req->closed) { - ret = fcgi_flush(req, 1); - req->closed = 1; - } - fcgi_close(req, force_close, 1); - } - return ret; -} - -char* fcgi_getenv(fcgi_request *req, const char* var, int var_len) -{ - unsigned int val_len; - - if (!req) return NULL; - - return fcgi_hash_get(&req->env, FCGI_HASH_FUNC(var, var_len), (char*)var, var_len, &val_len); -} - -char* fcgi_quick_getenv(fcgi_request *req, const char* var, int var_len, unsigned int hash_value) -{ - unsigned int val_len; - - return fcgi_hash_get(&req->env, hash_value, (char*)var, var_len, &val_len); -} - -char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val) -{ - if (!req) return NULL; - if (val == NULL) { - fcgi_hash_del(&req->env, FCGI_HASH_FUNC(var, var_len), var, var_len); - return NULL; - } else { - return fcgi_hash_set(&req->env, FCGI_HASH_FUNC(var, var_len), var, var_len, val, strlen(val)); - } -} - -char* fcgi_quick_putenv(fcgi_request *req, char* var, int var_len, unsigned int hash_value, char* val) -{ - if (val == NULL) { - fcgi_hash_del(&req->env, hash_value, var, var_len); - return NULL; - } else { - return fcgi_hash_set(&req->env, hash_value, var, var_len, val, strlen(val)); - } -} - -void fcgi_loadenv(fcgi_request *req, fcgi_apply_func func, zval *array TSRMLS_DC) -{ - fcgi_hash_apply(&req->env, func, array TSRMLS_CC); -} - -#ifdef _WIN32 -void fcgi_impersonate(void) -{ - char *os_name; - - os_name = getenv("OS"); - if (os_name && stricmp(os_name, "Windows_NT") == 0) { - is_impersonate = 1; - } -} -#endif - -void fcgi_set_mgmt_var(const char * name, size_t name_len, const char * value, size_t value_len) -{ - zval * zvalue; - zvalue = pemalloc(sizeof(*zvalue), 1); - Z_TYPE_P(zvalue) = IS_STRING; - Z_STRVAL_P(zvalue) = pestrndup(value, value_len, 1); - Z_STRLEN_P(zvalue) = value_len; - zend_hash_add(&fcgi_mgmt_vars, name, name_len, &zvalue, sizeof(zvalue), NULL); -} - -void fcgi_free_mgmt_var_cb(void * ptr) -{ - zval ** var = (zval **)ptr; - pefree(Z_STRVAL_PP(var), 1); - pefree(*var, 1); -} - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/sapi/cgi/fastcgi.h b/sapi/cgi/fastcgi.h deleted file mode 100644 index 7a80b1ae24..0000000000 --- a/sapi/cgi/fastcgi.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Dmitry Stogov <dmitry@zend.com> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -/* FastCGI protocol */ - -#define FCGI_VERSION_1 1 - -#define FCGI_MAX_LENGTH 0xffff - -#define FCGI_KEEP_CONN 1 - -/* this is near the perfect hash function for most useful FastCGI variables - * which combines efficiency and minimal hash collisions - */ - -#define FCGI_HASH_FUNC(var, var_len) \ - (UNEXPECTED(var_len < 3) ? var_len : \ - (((unsigned int)var[3]) << 2) + \ - (((unsigned int)var[var_len-2]) << 4) + \ - (((unsigned int)var[var_len-1]) << 2) + \ - var_len) - -#define FCGI_GETENV(request, name) \ - fcgi_quick_getenv(request, name, sizeof(name)-1, FCGI_HASH_FUNC(name, sizeof(name)-1)) - -#define FCGI_PUTENV(request, name, value) \ - fcgi_quick_putenv(request, name, sizeof(name)-1, FCGI_HASH_FUNC(name, sizeof(name)-1), value) - -typedef enum _fcgi_role { - FCGI_RESPONDER = 1, - FCGI_AUTHORIZER = 2, - FCGI_FILTER = 3 -} fcgi_role; - -typedef enum _fcgi_request_type { - FCGI_BEGIN_REQUEST = 1, /* [in] */ - FCGI_ABORT_REQUEST = 2, /* [in] (not supported) */ - FCGI_END_REQUEST = 3, /* [out] */ - FCGI_PARAMS = 4, /* [in] environment variables */ - FCGI_STDIN = 5, /* [in] post data */ - FCGI_STDOUT = 6, /* [out] response */ - FCGI_STDERR = 7, /* [out] errors */ - FCGI_DATA = 8, /* [in] filter data (not supported) */ - FCGI_GET_VALUES = 9, /* [in] */ - FCGI_GET_VALUES_RESULT = 10 /* [out] */ -} fcgi_request_type; - -typedef enum _fcgi_protocol_status { - FCGI_REQUEST_COMPLETE = 0, - FCGI_CANT_MPX_CONN = 1, - FCGI_OVERLOADED = 2, - FCGI_UNKNOWN_ROLE = 3 -} dcgi_protocol_status; - -typedef struct _fcgi_header { - unsigned char version; - unsigned char type; - unsigned char requestIdB1; - unsigned char requestIdB0; - unsigned char contentLengthB1; - unsigned char contentLengthB0; - unsigned char paddingLength; - unsigned char reserved; -} fcgi_header; - -typedef struct _fcgi_begin_request { - unsigned char roleB1; - unsigned char roleB0; - unsigned char flags; - unsigned char reserved[5]; -} fcgi_begin_request; - -typedef struct _fcgi_begin_request_rec { - fcgi_header hdr; - fcgi_begin_request body; -} fcgi_begin_request_rec; - -typedef struct _fcgi_end_request { - unsigned char appStatusB3; - unsigned char appStatusB2; - unsigned char appStatusB1; - unsigned char appStatusB0; - unsigned char protocolStatus; - unsigned char reserved[3]; -} fcgi_end_request; - -typedef struct _fcgi_end_request_rec { - fcgi_header hdr; - fcgi_end_request body; -} fcgi_end_request_rec; - -/* FastCGI client API */ - -typedef void (*fcgi_apply_func)(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg TSRMLS_DC); - -typedef struct _fcgi_request fcgi_request; - -int fcgi_init(void); -void fcgi_shutdown(void); -int fcgi_is_fastcgi(void); -int fcgi_in_shutdown(void); -void fcgi_terminate(void); -int fcgi_listen(const char *path, int backlog); -fcgi_request* fcgi_init_request(int listen_socket); -void fcgi_destroy_request(fcgi_request *req); -int fcgi_accept_request(fcgi_request *req); -int fcgi_finish_request(fcgi_request *req, int force_close); - -char* fcgi_getenv(fcgi_request *req, const char* var, int var_len); -char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val); -char* fcgi_quick_getenv(fcgi_request *req, const char* var, int var_len, unsigned int hash_value); -char* fcgi_quick_putenv(fcgi_request *req, char* var, int var_len, unsigned int hash_value, char* val); -void fcgi_loadenv(fcgi_request *req, fcgi_apply_func load_func, zval *array TSRMLS_DC); - -int fcgi_read(fcgi_request *req, char *str, int len); - -int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len); -int fcgi_flush(fcgi_request *req, int close); - -#ifdef PHP_WIN32 -void fcgi_impersonate(void); -#endif - -void fcgi_set_mgmt_var(const char * name, size_t name_len, const char * value, size_t value_len); -void fcgi_free_mgmt_var_cb(void * ptr); - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/sapi/cgi/tests/003.phpt b/sapi/cgi/tests/003.phpt index 533743323f..1ba94f27ef 100644 --- a/sapi/cgi/tests/003.phpt +++ b/sapi/cgi/tests/003.phpt @@ -2,6 +2,11 @@ strip comments and whitespace with -w --SKIPIF-- <?php + +if (substr(PHP_OS, 0, 3) == 'WIN') { + die ("skip not for Windows"); +} + include "skipif.inc"; ?> --FILE-- diff --git a/sapi/cgi/tests/004.phpt b/sapi/cgi/tests/004.phpt index c841b68e04..0e7117080d 100644 --- a/sapi/cgi/tests/004.phpt +++ b/sapi/cgi/tests/004.phpt @@ -26,7 +26,11 @@ var_dump(test::$pri); file_put_contents($filename, $code); -var_dump(`$php -n -f "$filename" 2>/dev/null`); +if (defined("PHP_WINDOWS_VERSION_MAJOR")) { + var_dump(`$php -n -f "$filename"`); +} else { + var_dump(`$php -n -f "$filename" 2>/dev/null`); +} var_dump(`$php -n -f "wrong"`); @unlink($filename); @@ -36,7 +40,10 @@ echo "Done\n"; --EXPECTF-- string(%d) " <br /> -<b>Fatal error</b>: Cannot access private property test::$pri in <b>%s004.test.php</b> on line <b>8</b><br /> +<b>Fatal error</b>: Uncaught Error: Cannot access private property test::$pri in %s004.test.php:8 +Stack trace: +#0 {main} + thrown in <b>%s004.test.php</b> on line <b>8</b><br /> " string(25) "No input file specified. " diff --git a/sapi/cgi/tests/005-win32.phpt b/sapi/cgi/tests/005-win32.phpt new file mode 100644 index 0000000000..b7efb9b500 --- /dev/null +++ b/sapi/cgi/tests/005-win32.phpt @@ -0,0 +1,34 @@ +--TEST-- +using invalid combinations of cmdline options +--SKIPIF-- +<?php + +if (substr(PHP_OS, 0, 3) != 'WIN') { + die ("skip Windows only"); +} + +include "skipif.inc"; +?> +--FILE-- +<?php + +include "include.inc"; + +$php = get_cgi_path(); +reset_env_vars(); + +var_dump(`$php -n -a -f "wrong"`); +var_dump(`$php -n -f "wrong" -a`); + +echo "Done\n"; +?> +--EXPECTF-- +string(51) "Interactive mode enabled + +No input file specified. +" +string(51) "Interactive mode enabled + +No input file specified. +" +Done diff --git a/sapi/cgi/tests/005.phpt b/sapi/cgi/tests/005.phpt index 34a28f9c5e..259005f3d9 100644 --- a/sapi/cgi/tests/005.phpt +++ b/sapi/cgi/tests/005.phpt @@ -1,7 +1,14 @@ --TEST-- using invalid combinations of cmdline options --SKIPIF-- -<?php include "skipif.inc"; ?> +<?php + +if (substr(PHP_OS, 0, 3) == 'WIN') { + die ("skip not for Windows"); +} + +include "skipif.inc"; +?> --FILE-- <?php diff --git a/sapi/cgi/tests/006.phpt b/sapi/cgi/tests/006.phpt index a2b2b2903a..08bfbf5d6c 100644 --- a/sapi/cgi/tests/006.phpt +++ b/sapi/cgi/tests/006.phpt @@ -44,7 +44,11 @@ class test file_put_contents($filename, $code); -var_dump(`"$php" -n -l "$filename" 2>/dev/null`); +if (defined("PHP_WINDOWS_VERSION_MAJOR")) { + var_dump(`"$php" -n -l "$filename"`); +} else { + var_dump(`"$php" -n -l "$filename" 2>/dev/null`); +} @unlink($filename); diff --git a/sapi/cgi/tests/include.inc b/sapi/cgi/tests/include.inc index 2d8ed8a2e3..dc98dc0f23 100644 --- a/sapi/cgi/tests/include.inc +++ b/sapi/cgi/tests/include.inc @@ -21,18 +21,27 @@ function get_cgi_path() /* {{{ */ if ($cli) { /* trying to guess ... */ $php_path = $php; - for ($i = 0; $i < 2; $i++) { - $slash_pos = strrpos($php_path, "/"); - if ($slash_pos) { - $php_path = substr($php_path, 0, $slash_pos); - } else { - return FALSE; + if (defined("PHP_WINDOWS_VERSION_MAJOR")) { + /* On Windows it should be in the same dir as php.exe in most of the cases. */ + $php_path = dirname($php); + + if (is_dir($php_path) && file_exists("$php_path/php-cgi.exe") && is_executable("$php_path/php-cgi.exe")) { + return "$php_path/php-cgi.exe"; + } + } else { + for ($i = 0; $i < 2; $i++) { + $slash_pos = strrpos($php_path, "/"); + if ($slash_pos) { + $php_path = substr($php_path, 0, $slash_pos); + } else { + return FALSE; + } } - } - if ($php_path && is_dir($php_path) && file_exists($php_path."/cgi/php-cgi") && is_executable($php_path."/cgi/php-cgi")) { - /* gotcha */ - return $php_path."/cgi/php-cgi"; + if ($php_path && is_dir($php_path) && file_exists($php_path."/cgi/php-cgi") && is_executable($php_path."/cgi/php-cgi")) { + /* gotcha */ + return $php_path."/cgi/php-cgi"; + } } return false; } diff --git a/sapi/cgi/tests/skipif.inc b/sapi/cgi/tests/skipif.inc index 9da8b7934d..d2cef23589 100644 --- a/sapi/cgi/tests/skipif.inc +++ b/sapi/cgi/tests/skipif.inc @@ -4,10 +4,6 @@ if (substr(php_sapi_name(), 0, 3) == "cgi") { exit; } -if (substr(PHP_OS, 0, 3) == 'WIN') { - die ("skip not for Windows"); -} - include dirname(__FILE__)."/include.inc"; if (!get_cgi_path()) { diff --git a/sapi/cli/cli.h b/sapi/cli/cli.h index eac121bcfa..ea373c2595 100644 --- a/sapi/cli/cli.h +++ b/sapi/cli/cli.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -30,12 +30,12 @@ #endif -extern PHP_CLI_API size_t sapi_cli_single_write(const char *str, uint str_length TSRMLS_DC); +extern PHP_CLI_API size_t sapi_cli_single_write(const char *str, size_t str_length); typedef struct { - size_t (*cli_shell_write)(const char *str, uint str_length TSRMLS_DC); - int (*cli_shell_ub_write)(const char *str, uint str_length TSRMLS_DC); - int (*cli_shell_run)(TSRMLS_D); + size_t (*cli_shell_write)(const char *str, size_t str_length); + size_t (*cli_shell_ub_write)(const char *str, size_t str_length); + int (*cli_shell_run)(void); } cli_shell_callbacks_t; extern PHP_CLI_API cli_shell_callbacks_t *php_cli_get_shell_callbacks(); diff --git a/sapi/cli/config.m4 b/sapi/cli/config.m4 index 1a585c327a..04db2fecee 100644 --- a/sapi/cli/config.m4 +++ b/sapi/cli/config.m4 @@ -31,7 +31,7 @@ if test "$PHP_CLI" != "no"; then SAPI_CLI_PATH=sapi/cli/php dnl Select SAPI - PHP_SELECT_SAPI(cli, program, php_cli.c php_http_parser.c php_cli_server.c ps_title.c php_cli_process_title.c,, '$(SAPI_CLI_PATH)') + PHP_SELECT_SAPI(cli, program, php_cli.c php_http_parser.c php_cli_server.c ps_title.c php_cli_process_title.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1, '$(SAPI_CLI_PATH)') case $host_alias in *aix*) @@ -45,7 +45,7 @@ if test "$PHP_CLI" != "no"; then BUILD_CLI="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_CLI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CLI_PATH)" ;; *netware*) - BUILD_CLI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_BINARY_OBJS) \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -Lnetware -lphp5lib -o \$(SAPI_CLI_PATH)" + BUILD_CLI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_BINARY_OBJS) \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -Lnetware -lphp7lib -o \$(SAPI_CLI_PATH)" ;; *) BUILD_CLI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CLI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CLI_PATH)" diff --git a/sapi/cli/config.w32 b/sapi/cli/config.w32 index adcbb2b496..664394c8a6 100644 --- a/sapi/cli/config.w32 +++ b/sapi/cli/config.w32 @@ -6,16 +6,16 @@ ARG_ENABLE('crt-debug', 'Enable CRT memory dumps for debugging sent to STDERR', ARG_ENABLE('cli-win32', 'Build console-less CLI version of PHP', 'no'); if (PHP_CLI == "yes") { - SAPI('cli', 'php_cli.c php_http_parser.c php_cli_server.c php_cli_process_title.c ps_title.c', 'php.exe'); + SAPI('cli', 'php_cli.c php_http_parser.c php_cli_server.c php_cli_process_title.c ps_title.c', 'php.exe', '/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1'); ADD_FLAG("LIBS_CLI", "ws2_32.lib"); if (PHP_CRT_DEBUG == "yes") { ADD_FLAG("CFLAGS_CLI", "/D PHP_WIN32_DEBUG_HEAP"); } - ADD_FLAG("LDFLAGS_CLI", "/stack:8388608"); + ADD_FLAG("LDFLAGS_CLI", "/stack:67108864"); } if (PHP_CLI_WIN32 == "yes") { - SAPI('cli_win32', 'cli_win32.c php_cli_process_title.c ps_title.c', 'php-win.exe'); - ADD_FLAG("LDFLAGS_CLI_WIN32", "/stack:8388608"); + SAPI('cli_win32', 'cli_win32.c php_cli_process_title.c ps_title.c', 'php-win.exe', '/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1'); + ADD_FLAG("LDFLAGS_CLI_WIN32", "/stack:67108864"); } diff --git a/sapi/cli/generate_mime_type_map.php b/sapi/cli/generate_mime_type_map.php new file mode 100644 index 0000000000..402be0070c --- /dev/null +++ b/sapi/cli/generate_mime_type_map.php @@ -0,0 +1,88 @@ +#!/usr/bin/env php +<?php + +// Check if we are being given a mime.types file or if we should use the +// default URL. +$source = count($_SERVER['argv']) > 1 ? $_SERVER['argv'][1] : 'https://raw.githubusercontent.com/apache/httpd/trunk/docs/conf/mime.types'; + +// See if we can actually load it. +$types = @file($source); +if ($types === false) { + fprintf(STDERR, "Error: unable to read $source\n"); + exit(1); +} + +// Remove comments and flip into an extensions array. +$extensions = []; +array_walk($types, function ($line) use (&$extensions) { + $line = trim($line); + if ($line && $line[0] != '#') { + $fields = preg_split('/\s+/', $line); + if (count($fields) > 1) { + $mime = array_shift($fields); + foreach ($fields as $extension) { + $extensions[$extension] = $mime; + } + } + } +}); + +$additional_mime_maps = [ + "map" => "application/json", // from commit: a0d62f08ae8cbebc88e5c92e08fca8d0cdc7309d +]; + +foreach($additional_mime_maps as $ext => $mime) { + if (!isset($extensions[$ext])) { + $extensions[$ext] = $mime; + } else { + printf(STDERR, "Ignored exist mime type: $ext => $mime\n"); + } +} + +?> +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2016 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: Moriyoshi Koizumi <moriyoshi@php.net> | + +----------------------------------------------------------------------+ +*/ + +/* This is a generated file. Rather than modifying it, please run + * "php generate_mime_type_map.php > mime_type_map.h" to regenerate the file. */ + +#ifndef PHP_CLI_SERVER_MIME_TYPE_MAP_H +#define PHP_CLI_SERVER_MIME_TYPE_MAP_H + +typedef struct php_cli_server_ext_mime_type_pair { + const char *ext; + const char *mime_type; +} php_cli_server_ext_mime_type_pair; + +static php_cli_server_ext_mime_type_pair mime_type_map[] = { +<?php foreach ($extensions as $extension => $mime): ?> + { "<?= addcslashes($extension, "\0..\37!@\@\177..\377") ?>", "<?= addcslashes($mime, "\0..\37!@\@\177..\377") ?>" }, +<?php endforeach ?> + { NULL, NULL } +}; + +#endif /* PHP_CLI_SERVER_MIME_TYPE_MAP_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/sapi/cli/mime_type_map.h b/sapi/cli/mime_type_map.h new file mode 100644 index 0000000000..0afa501429 --- /dev/null +++ b/sapi/cli/mime_type_map.h @@ -0,0 +1,1025 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2016 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: Moriyoshi Koizumi <moriyoshi@php.net> | + +----------------------------------------------------------------------+ +*/ + +/* This is a generated file. Rather than modifying it, please run + * "php generate_mime_type_map.php > mime_type_map.h" to regenerate the file. */ + +#ifndef PHP_CLI_SERVER_MIME_TYPE_MAP_H +#define PHP_CLI_SERVER_MIME_TYPE_MAP_H + +typedef struct php_cli_server_ext_mime_type_pair { + const char *ext; + const char *mime_type; +} php_cli_server_ext_mime_type_pair; + +static php_cli_server_ext_mime_type_pair mime_type_map[] = { + { "ez", "application/andrew-inset" }, + { "aw", "application/applixware" }, + { "atom", "application/atom+xml" }, + { "atomcat", "application/atomcat+xml" }, + { "atomsvc", "application/atomsvc+xml" }, + { "ccxml", "application/ccxml+xml" }, + { "cdmia", "application/cdmi-capability" }, + { "cdmic", "application/cdmi-container" }, + { "cdmid", "application/cdmi-domain" }, + { "cdmio", "application/cdmi-object" }, + { "cdmiq", "application/cdmi-queue" }, + { "cu", "application/cu-seeme" }, + { "davmount", "application/davmount+xml" }, + { "dbk", "application/docbook+xml" }, + { "dssc", "application/dssc+der" }, + { "xdssc", "application/dssc+xml" }, + { "ecma", "application/ecmascript" }, + { "emma", "application/emma+xml" }, + { "epub", "application/epub+zip" }, + { "exi", "application/exi" }, + { "pfr", "application/font-tdpfr" }, + { "gml", "application/gml+xml" }, + { "gpx", "application/gpx+xml" }, + { "gxf", "application/gxf" }, + { "stk", "application/hyperstudio" }, + { "ink", "application/inkml+xml" }, + { "inkml", "application/inkml+xml" }, + { "ipfix", "application/ipfix" }, + { "jar", "application/java-archive" }, + { "ser", "application/java-serialized-object" }, + { "class", "application/java-vm" }, + { "js", "application/javascript" }, + { "json", "application/json" }, + { "jsonml", "application/jsonml+json" }, + { "lostxml", "application/lost+xml" }, + { "hqx", "application/mac-binhex40" }, + { "cpt", "application/mac-compactpro" }, + { "mads", "application/mads+xml" }, + { "mrc", "application/marc" }, + { "mrcx", "application/marcxml+xml" }, + { "ma", "application/mathematica" }, + { "nb", "application/mathematica" }, + { "mb", "application/mathematica" }, + { "mathml", "application/mathml+xml" }, + { "mbox", "application/mbox" }, + { "mscml", "application/mediaservercontrol+xml" }, + { "metalink", "application/metalink+xml" }, + { "meta4", "application/metalink4+xml" }, + { "mets", "application/mets+xml" }, + { "mods", "application/mods+xml" }, + { "m21", "application/mp21" }, + { "mp21", "application/mp21" }, + { "mp4s", "application/mp4" }, + { "doc", "application/msword" }, + { "dot", "application/msword" }, + { "mxf", "application/mxf" }, + { "bin", "application/octet-stream" }, + { "dms", "application/octet-stream" }, + { "lrf", "application/octet-stream" }, + { "mar", "application/octet-stream" }, + { "so", "application/octet-stream" }, + { "dist", "application/octet-stream" }, + { "distz", "application/octet-stream" }, + { "pkg", "application/octet-stream" }, + { "bpk", "application/octet-stream" }, + { "dump", "application/octet-stream" }, + { "elc", "application/octet-stream" }, + { "deploy", "application/octet-stream" }, + { "oda", "application/oda" }, + { "opf", "application/oebps-package+xml" }, + { "ogx", "application/ogg" }, + { "omdoc", "application/omdoc+xml" }, + { "onetoc", "application/onenote" }, + { "onetoc2", "application/onenote" }, + { "onetmp", "application/onenote" }, + { "onepkg", "application/onenote" }, + { "oxps", "application/oxps" }, + { "xer", "application/patch-ops-error+xml" }, + { "pdf", "application/pdf" }, + { "pgp", "application/pgp-encrypted" }, + { "asc", "application/pgp-signature" }, + { "sig", "application/pgp-signature" }, + { "prf", "application/pics-rules" }, + { "p10", "application/pkcs10" }, + { "p7m", "application/pkcs7-mime" }, + { "p7c", "application/pkcs7-mime" }, + { "p7s", "application/pkcs7-signature" }, + { "p8", "application/pkcs8" }, + { "ac", "application/pkix-attr-cert" }, + { "cer", "application/pkix-cert" }, + { "crl", "application/pkix-crl" }, + { "pkipath", "application/pkix-pkipath" }, + { "pki", "application/pkixcmp" }, + { "pls", "application/pls+xml" }, + { "ai", "application/postscript" }, + { "eps", "application/postscript" }, + { "ps", "application/postscript" }, + { "cww", "application/prs.cww" }, + { "pskcxml", "application/pskc+xml" }, + { "rdf", "application/rdf+xml" }, + { "rif", "application/reginfo+xml" }, + { "rnc", "application/relax-ng-compact-syntax" }, + { "rl", "application/resource-lists+xml" }, + { "rld", "application/resource-lists-diff+xml" }, + { "rs", "application/rls-services+xml" }, + { "gbr", "application/rpki-ghostbusters" }, + { "mft", "application/rpki-manifest" }, + { "roa", "application/rpki-roa" }, + { "rsd", "application/rsd+xml" }, + { "rss", "application/rss+xml" }, + { "rtf", "application/rtf" }, + { "sbml", "application/sbml+xml" }, + { "scq", "application/scvp-cv-request" }, + { "scs", "application/scvp-cv-response" }, + { "spq", "application/scvp-vp-request" }, + { "spp", "application/scvp-vp-response" }, + { "sdp", "application/sdp" }, + { "setpay", "application/set-payment-initiation" }, + { "setreg", "application/set-registration-initiation" }, + { "shf", "application/shf+xml" }, + { "smi", "application/smil+xml" }, + { "smil", "application/smil+xml" }, + { "rq", "application/sparql-query" }, + { "srx", "application/sparql-results+xml" }, + { "gram", "application/srgs" }, + { "grxml", "application/srgs+xml" }, + { "sru", "application/sru+xml" }, + { "ssdl", "application/ssdl+xml" }, + { "ssml", "application/ssml+xml" }, + { "tei", "application/tei+xml" }, + { "teicorpus", "application/tei+xml" }, + { "tfi", "application/thraud+xml" }, + { "tsd", "application/timestamped-data" }, + { "plb", "application/vnd.3gpp.pic-bw-large" }, + { "psb", "application/vnd.3gpp.pic-bw-small" }, + { "pvb", "application/vnd.3gpp.pic-bw-var" }, + { "tcap", "application/vnd.3gpp2.tcap" }, + { "pwn", "application/vnd.3m.post-it-notes" }, + { "aso", "application/vnd.accpac.simply.aso" }, + { "imp", "application/vnd.accpac.simply.imp" }, + { "acu", "application/vnd.acucobol" }, + { "atc", "application/vnd.acucorp" }, + { "acutc", "application/vnd.acucorp" }, + { "air", "application/vnd.adobe.air-application-installer-package+zip" }, + { "fcdt", "application/vnd.adobe.formscentral.fcdt" }, + { "fxp", "application/vnd.adobe.fxp" }, + { "fxpl", "application/vnd.adobe.fxp" }, + { "xdp", "application/vnd.adobe.xdp+xml" }, + { "xfdf", "application/vnd.adobe.xfdf" }, + { "ahead", "application/vnd.ahead.space" }, + { "azf", "application/vnd.airzip.filesecure.azf" }, + { "azs", "application/vnd.airzip.filesecure.azs" }, + { "azw", "application/vnd.amazon.ebook" }, + { "acc", "application/vnd.americandynamics.acc" }, + { "ami", "application/vnd.amiga.ami" }, + { "apk", "application/vnd.android.package-archive" }, + { "cii", "application/vnd.anser-web-certificate-issue-initiation" }, + { "fti", "application/vnd.anser-web-funds-transfer-initiation" }, + { "atx", "application/vnd.antix.game-component" }, + { "mpkg", "application/vnd.apple.installer+xml" }, + { "m3u8", "application/vnd.apple.mpegurl" }, + { "swi", "application/vnd.aristanetworks.swi" }, + { "iota", "application/vnd.astraea-software.iota" }, + { "aep", "application/vnd.audiograph" }, + { "mpm", "application/vnd.blueice.multipass" }, + { "bmi", "application/vnd.bmi" }, + { "rep", "application/vnd.businessobjects" }, + { "cdxml", "application/vnd.chemdraw+xml" }, + { "mmd", "application/vnd.chipnuts.karaoke-mmd" }, + { "cdy", "application/vnd.cinderella" }, + { "cla", "application/vnd.claymore" }, + { "rp9", "application/vnd.cloanto.rp9" }, + { "c4g", "application/vnd.clonk.c4group" }, + { "c4d", "application/vnd.clonk.c4group" }, + { "c4f", "application/vnd.clonk.c4group" }, + { "c4p", "application/vnd.clonk.c4group" }, + { "c4u", "application/vnd.clonk.c4group" }, + { "c11amc", "application/vnd.cluetrust.cartomobile-config" }, + { "c11amz", "application/vnd.cluetrust.cartomobile-config-pkg" }, + { "csp", "application/vnd.commonspace" }, + { "cdbcmsg", "application/vnd.contact.cmsg" }, + { "cmc", "application/vnd.cosmocaller" }, + { "clkx", "application/vnd.crick.clicker" }, + { "clkk", "application/vnd.crick.clicker.keyboard" }, + { "clkp", "application/vnd.crick.clicker.palette" }, + { "clkt", "application/vnd.crick.clicker.template" }, + { "clkw", "application/vnd.crick.clicker.wordbank" }, + { "wbs", "application/vnd.criticaltools.wbs+xml" }, + { "pml", "application/vnd.ctc-posml" }, + { "ppd", "application/vnd.cups-ppd" }, + { "car", "application/vnd.curl.car" }, + { "pcurl", "application/vnd.curl.pcurl" }, + { "dart", "application/vnd.dart" }, + { "rdz", "application/vnd.data-vision.rdz" }, + { "uvf", "application/vnd.dece.data" }, + { "uvvf", "application/vnd.dece.data" }, + { "uvd", "application/vnd.dece.data" }, + { "uvvd", "application/vnd.dece.data" }, + { "uvt", "application/vnd.dece.ttml+xml" }, + { "uvvt", "application/vnd.dece.ttml+xml" }, + { "uvx", "application/vnd.dece.unspecified" }, + { "uvvx", "application/vnd.dece.unspecified" }, + { "uvz", "application/vnd.dece.zip" }, + { "uvvz", "application/vnd.dece.zip" }, + { "fe_launch", "application/vnd.denovo.fcselayout-link" }, + { "dna", "application/vnd.dna" }, + { "mlp", "application/vnd.dolby.mlp" }, + { "dpg", "application/vnd.dpgraph" }, + { "dfac", "application/vnd.dreamfactory" }, + { "kpxx", "application/vnd.ds-keypoint" }, + { "ait", "application/vnd.dvb.ait" }, + { "svc", "application/vnd.dvb.service" }, + { "geo", "application/vnd.dynageo" }, + { "mag", "application/vnd.ecowin.chart" }, + { "nml", "application/vnd.enliven" }, + { "esf", "application/vnd.epson.esf" }, + { "msf", "application/vnd.epson.msf" }, + { "qam", "application/vnd.epson.quickanime" }, + { "slt", "application/vnd.epson.salt" }, + { "ssf", "application/vnd.epson.ssf" }, + { "es3", "application/vnd.eszigno3+xml" }, + { "et3", "application/vnd.eszigno3+xml" }, + { "ez2", "application/vnd.ezpix-album" }, + { "ez3", "application/vnd.ezpix-package" }, + { "fdf", "application/vnd.fdf" }, + { "mseed", "application/vnd.fdsn.mseed" }, + { "seed", "application/vnd.fdsn.seed" }, + { "dataless", "application/vnd.fdsn.seed" }, + { "gph", "application/vnd.flographit" }, + { "ftc", "application/vnd.fluxtime.clip" }, + { "fm", "application/vnd.framemaker" }, + { "frame", "application/vnd.framemaker" }, + { "maker", "application/vnd.framemaker" }, + { "book", "application/vnd.framemaker" }, + { "fnc", "application/vnd.frogans.fnc" }, + { "ltf", "application/vnd.frogans.ltf" }, + { "fsc", "application/vnd.fsc.weblaunch" }, + { "oas", "application/vnd.fujitsu.oasys" }, + { "oa2", "application/vnd.fujitsu.oasys2" }, + { "oa3", "application/vnd.fujitsu.oasys3" }, + { "fg5", "application/vnd.fujitsu.oasysgp" }, + { "bh2", "application/vnd.fujitsu.oasysprs" }, + { "ddd", "application/vnd.fujixerox.ddd" }, + { "xdw", "application/vnd.fujixerox.docuworks" }, + { "xbd", "application/vnd.fujixerox.docuworks.binder" }, + { "fzs", "application/vnd.fuzzysheet" }, + { "txd", "application/vnd.genomatix.tuxedo" }, + { "ggb", "application/vnd.geogebra.file" }, + { "ggt", "application/vnd.geogebra.tool" }, + { "gex", "application/vnd.geometry-explorer" }, + { "gre", "application/vnd.geometry-explorer" }, + { "gxt", "application/vnd.geonext" }, + { "g2w", "application/vnd.geoplan" }, + { "g3w", "application/vnd.geospace" }, + { "gmx", "application/vnd.gmx" }, + { "kml", "application/vnd.google-earth.kml+xml" }, + { "kmz", "application/vnd.google-earth.kmz" }, + { "gqf", "application/vnd.grafeq" }, + { "gqs", "application/vnd.grafeq" }, + { "gac", "application/vnd.groove-account" }, + { "ghf", "application/vnd.groove-help" }, + { "gim", "application/vnd.groove-identity-message" }, + { "grv", "application/vnd.groove-injector" }, + { "gtm", "application/vnd.groove-tool-message" }, + { "tpl", "application/vnd.groove-tool-template" }, + { "vcg", "application/vnd.groove-vcard" }, + { "hal", "application/vnd.hal+xml" }, + { "zmm", "application/vnd.handheld-entertainment+xml" }, + { "hbci", "application/vnd.hbci" }, + { "les", "application/vnd.hhe.lesson-player" }, + { "hpgl", "application/vnd.hp-hpgl" }, + { "hpid", "application/vnd.hp-hpid" }, + { "hps", "application/vnd.hp-hps" }, + { "jlt", "application/vnd.hp-jlyt" }, + { "pcl", "application/vnd.hp-pcl" }, + { "pclxl", "application/vnd.hp-pclxl" }, + { "sfd-hdstx", "application/vnd.hydrostatix.sof-data" }, + { "mpy", "application/vnd.ibm.minipay" }, + { "afp", "application/vnd.ibm.modcap" }, + { "listafp", "application/vnd.ibm.modcap" }, + { "list3820", "application/vnd.ibm.modcap" }, + { "irm", "application/vnd.ibm.rights-management" }, + { "sc", "application/vnd.ibm.secure-container" }, + { "icc", "application/vnd.iccprofile" }, + { "icm", "application/vnd.iccprofile" }, + { "igl", "application/vnd.igloader" }, + { "ivp", "application/vnd.immervision-ivp" }, + { "ivu", "application/vnd.immervision-ivu" }, + { "igm", "application/vnd.insors.igm" }, + { "xpw", "application/vnd.intercon.formnet" }, + { "xpx", "application/vnd.intercon.formnet" }, + { "i2g", "application/vnd.intergeo" }, + { "qbo", "application/vnd.intu.qbo" }, + { "qfx", "application/vnd.intu.qfx" }, + { "rcprofile", "application/vnd.ipunplugged.rcprofile" }, + { "irp", "application/vnd.irepository.package+xml" }, + { "xpr", "application/vnd.is-xpr" }, + { "fcs", "application/vnd.isac.fcs" }, + { "jam", "application/vnd.jam" }, + { "rms", "application/vnd.jcp.javame.midlet-rms" }, + { "jisp", "application/vnd.jisp" }, + { "joda", "application/vnd.joost.joda-archive" }, + { "ktz", "application/vnd.kahootz" }, + { "ktr", "application/vnd.kahootz" }, + { "karbon", "application/vnd.kde.karbon" }, + { "chrt", "application/vnd.kde.kchart" }, + { "kfo", "application/vnd.kde.kformula" }, + { "flw", "application/vnd.kde.kivio" }, + { "kon", "application/vnd.kde.kontour" }, + { "kpr", "application/vnd.kde.kpresenter" }, + { "kpt", "application/vnd.kde.kpresenter" }, + { "ksp", "application/vnd.kde.kspread" }, + { "kwd", "application/vnd.kde.kword" }, + { "kwt", "application/vnd.kde.kword" }, + { "htke", "application/vnd.kenameaapp" }, + { "kia", "application/vnd.kidspiration" }, + { "kne", "application/vnd.kinar" }, + { "knp", "application/vnd.kinar" }, + { "skp", "application/vnd.koan" }, + { "skd", "application/vnd.koan" }, + { "skt", "application/vnd.koan" }, + { "skm", "application/vnd.koan" }, + { "sse", "application/vnd.kodak-descriptor" }, + { "lasxml", "application/vnd.las.las+xml" }, + { "lbd", "application/vnd.llamagraphics.life-balance.desktop" }, + { "lbe", "application/vnd.llamagraphics.life-balance.exchange+xml" }, + { "123", "application/vnd.lotus-1-2-3" }, + { "apr", "application/vnd.lotus-approach" }, + { "pre", "application/vnd.lotus-freelance" }, + { "nsf", "application/vnd.lotus-notes" }, + { "org", "application/vnd.lotus-organizer" }, + { "scm", "application/vnd.lotus-screencam" }, + { "lwp", "application/vnd.lotus-wordpro" }, + { "portpkg", "application/vnd.macports.portpkg" }, + { "mcd", "application/vnd.mcd" }, + { "mc1", "application/vnd.medcalcdata" }, + { "cdkey", "application/vnd.mediastation.cdkey" }, + { "mwf", "application/vnd.mfer" }, + { "mfm", "application/vnd.mfmp" }, + { "flo", "application/vnd.micrografx.flo" }, + { "igx", "application/vnd.micrografx.igx" }, + { "mif", "application/vnd.mif" }, + { "daf", "application/vnd.mobius.daf" }, + { "dis", "application/vnd.mobius.dis" }, + { "mbk", "application/vnd.mobius.mbk" }, + { "mqy", "application/vnd.mobius.mqy" }, + { "msl", "application/vnd.mobius.msl" }, + { "plc", "application/vnd.mobius.plc" }, + { "txf", "application/vnd.mobius.txf" }, + { "mpn", "application/vnd.mophun.application" }, + { "mpc", "application/vnd.mophun.certificate" }, + { "xul", "application/vnd.mozilla.xul+xml" }, + { "cil", "application/vnd.ms-artgalry" }, + { "cab", "application/vnd.ms-cab-compressed" }, + { "xls", "application/vnd.ms-excel" }, + { "xlm", "application/vnd.ms-excel" }, + { "xla", "application/vnd.ms-excel" }, + { "xlc", "application/vnd.ms-excel" }, + { "xlt", "application/vnd.ms-excel" }, + { "xlw", "application/vnd.ms-excel" }, + { "xlam", "application/vnd.ms-excel.addin.macroenabled.12" }, + { "xlsb", "application/vnd.ms-excel.sheet.binary.macroenabled.12" }, + { "xlsm", "application/vnd.ms-excel.sheet.macroenabled.12" }, + { "xltm", "application/vnd.ms-excel.template.macroenabled.12" }, + { "eot", "application/vnd.ms-fontobject" }, + { "chm", "application/vnd.ms-htmlhelp" }, + { "ims", "application/vnd.ms-ims" }, + { "lrm", "application/vnd.ms-lrm" }, + { "thmx", "application/vnd.ms-officetheme" }, + { "cat", "application/vnd.ms-pki.seccat" }, + { "stl", "application/vnd.ms-pki.stl" }, + { "ppt", "application/vnd.ms-powerpoint" }, + { "pps", "application/vnd.ms-powerpoint" }, + { "pot", "application/vnd.ms-powerpoint" }, + { "ppam", "application/vnd.ms-powerpoint.addin.macroenabled.12" }, + { "pptm", "application/vnd.ms-powerpoint.presentation.macroenabled.12" }, + { "sldm", "application/vnd.ms-powerpoint.slide.macroenabled.12" }, + { "ppsm", "application/vnd.ms-powerpoint.slideshow.macroenabled.12" }, + { "potm", "application/vnd.ms-powerpoint.template.macroenabled.12" }, + { "mpp", "application/vnd.ms-project" }, + { "mpt", "application/vnd.ms-project" }, + { "docm", "application/vnd.ms-word.document.macroenabled.12" }, + { "dotm", "application/vnd.ms-word.template.macroenabled.12" }, + { "wps", "application/vnd.ms-works" }, + { "wks", "application/vnd.ms-works" }, + { "wcm", "application/vnd.ms-works" }, + { "wdb", "application/vnd.ms-works" }, + { "wpl", "application/vnd.ms-wpl" }, + { "xps", "application/vnd.ms-xpsdocument" }, + { "mseq", "application/vnd.mseq" }, + { "mus", "application/vnd.musician" }, + { "msty", "application/vnd.muvee.style" }, + { "taglet", "application/vnd.mynfc" }, + { "nlu", "application/vnd.neurolanguage.nlu" }, + { "ntf", "application/vnd.nitf" }, + { "nitf", "application/vnd.nitf" }, + { "nnd", "application/vnd.noblenet-directory" }, + { "nns", "application/vnd.noblenet-sealer" }, + { "nnw", "application/vnd.noblenet-web" }, + { "ngdat", "application/vnd.nokia.n-gage.data" }, + { "n-gage", "application/vnd.nokia.n-gage.symbian.install" }, + { "rpst", "application/vnd.nokia.radio-preset" }, + { "rpss", "application/vnd.nokia.radio-presets" }, + { "edm", "application/vnd.novadigm.edm" }, + { "edx", "application/vnd.novadigm.edx" }, + { "ext", "application/vnd.novadigm.ext" }, + { "odc", "application/vnd.oasis.opendocument.chart" }, + { "otc", "application/vnd.oasis.opendocument.chart-template" }, + { "odb", "application/vnd.oasis.opendocument.database" }, + { "odf", "application/vnd.oasis.opendocument.formula" }, + { "odft", "application/vnd.oasis.opendocument.formula-template" }, + { "odg", "application/vnd.oasis.opendocument.graphics" }, + { "otg", "application/vnd.oasis.opendocument.graphics-template" }, + { "odi", "application/vnd.oasis.opendocument.image" }, + { "oti", "application/vnd.oasis.opendocument.image-template" }, + { "odp", "application/vnd.oasis.opendocument.presentation" }, + { "otp", "application/vnd.oasis.opendocument.presentation-template" }, + { "ods", "application/vnd.oasis.opendocument.spreadsheet" }, + { "ots", "application/vnd.oasis.opendocument.spreadsheet-template" }, + { "odt", "application/vnd.oasis.opendocument.text" }, + { "odm", "application/vnd.oasis.opendocument.text-master" }, + { "ott", "application/vnd.oasis.opendocument.text-template" }, + { "oth", "application/vnd.oasis.opendocument.text-web" }, + { "xo", "application/vnd.olpc-sugar" }, + { "dd2", "application/vnd.oma.dd2+xml" }, + { "oxt", "application/vnd.openofficeorg.extension" }, + { "pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation" }, + { "sldx", "application/vnd.openxmlformats-officedocument.presentationml.slide" }, + { "ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow" }, + { "potx", "application/vnd.openxmlformats-officedocument.presentationml.template" }, + { "xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }, + { "xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template" }, + { "docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document" }, + { "dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template" }, + { "mgp", "application/vnd.osgeo.mapguide.package" }, + { "dp", "application/vnd.osgi.dp" }, + { "esa", "application/vnd.osgi.subsystem" }, + { "pdb", "application/vnd.palm" }, + { "pqa", "application/vnd.palm" }, + { "oprc", "application/vnd.palm" }, + { "paw", "application/vnd.pawaafile" }, + { "str", "application/vnd.pg.format" }, + { "ei6", "application/vnd.pg.osasli" }, + { "efif", "application/vnd.picsel" }, + { "wg", "application/vnd.pmi.widget" }, + { "plf", "application/vnd.pocketlearn" }, + { "pbd", "application/vnd.powerbuilder6" }, + { "box", "application/vnd.previewsystems.box" }, + { "mgz", "application/vnd.proteus.magazine" }, + { "qps", "application/vnd.publishare-delta-tree" }, + { "ptid", "application/vnd.pvi.ptid1" }, + { "qxd", "application/vnd.quark.quarkxpress" }, + { "qxt", "application/vnd.quark.quarkxpress" }, + { "qwd", "application/vnd.quark.quarkxpress" }, + { "qwt", "application/vnd.quark.quarkxpress" }, + { "qxl", "application/vnd.quark.quarkxpress" }, + { "qxb", "application/vnd.quark.quarkxpress" }, + { "bed", "application/vnd.realvnc.bed" }, + { "mxl", "application/vnd.recordare.musicxml" }, + { "musicxml", "application/vnd.recordare.musicxml+xml" }, + { "cryptonote", "application/vnd.rig.cryptonote" }, + { "cod", "application/vnd.rim.cod" }, + { "rm", "application/vnd.rn-realmedia" }, + { "rmvb", "application/vnd.rn-realmedia-vbr" }, + { "link66", "application/vnd.route66.link66+xml" }, + { "st", "application/vnd.sailingtracker.track" }, + { "see", "application/vnd.seemail" }, + { "sema", "application/vnd.sema" }, + { "semd", "application/vnd.semd" }, + { "semf", "application/vnd.semf" }, + { "ifm", "application/vnd.shana.informed.formdata" }, + { "itp", "application/vnd.shana.informed.formtemplate" }, + { "iif", "application/vnd.shana.informed.interchange" }, + { "ipk", "application/vnd.shana.informed.package" }, + { "twd", "application/vnd.simtech-mindmapper" }, + { "twds", "application/vnd.simtech-mindmapper" }, + { "mmf", "application/vnd.smaf" }, + { "teacher", "application/vnd.smart.teacher" }, + { "sdkm", "application/vnd.solent.sdkm+xml" }, + { "sdkd", "application/vnd.solent.sdkm+xml" }, + { "dxp", "application/vnd.spotfire.dxp" }, + { "sfs", "application/vnd.spotfire.sfs" }, + { "sdc", "application/vnd.stardivision.calc" }, + { "sda", "application/vnd.stardivision.draw" }, + { "sdd", "application/vnd.stardivision.impress" }, + { "smf", "application/vnd.stardivision.math" }, + { "sdw", "application/vnd.stardivision.writer" }, + { "vor", "application/vnd.stardivision.writer" }, + { "sgl", "application/vnd.stardivision.writer-global" }, + { "smzip", "application/vnd.stepmania.package" }, + { "sm", "application/vnd.stepmania.stepchart" }, + { "sxc", "application/vnd.sun.xml.calc" }, + { "stc", "application/vnd.sun.xml.calc.template" }, + { "sxd", "application/vnd.sun.xml.draw" }, + { "std", "application/vnd.sun.xml.draw.template" }, + { "sxi", "application/vnd.sun.xml.impress" }, + { "sti", "application/vnd.sun.xml.impress.template" }, + { "sxm", "application/vnd.sun.xml.math" }, + { "sxw", "application/vnd.sun.xml.writer" }, + { "sxg", "application/vnd.sun.xml.writer.global" }, + { "stw", "application/vnd.sun.xml.writer.template" }, + { "sus", "application/vnd.sus-calendar" }, + { "susp", "application/vnd.sus-calendar" }, + { "svd", "application/vnd.svd" }, + { "sis", "application/vnd.symbian.install" }, + { "sisx", "application/vnd.symbian.install" }, + { "xsm", "application/vnd.syncml+xml" }, + { "bdm", "application/vnd.syncml.dm+wbxml" }, + { "xdm", "application/vnd.syncml.dm+xml" }, + { "tao", "application/vnd.tao.intent-module-archive" }, + { "pcap", "application/vnd.tcpdump.pcap" }, + { "cap", "application/vnd.tcpdump.pcap" }, + { "dmp", "application/vnd.tcpdump.pcap" }, + { "tmo", "application/vnd.tmobile-livetv" }, + { "tpt", "application/vnd.trid.tpt" }, + { "mxs", "application/vnd.triscape.mxs" }, + { "tra", "application/vnd.trueapp" }, + { "ufd", "application/vnd.ufdl" }, + { "ufdl", "application/vnd.ufdl" }, + { "utz", "application/vnd.uiq.theme" }, + { "umj", "application/vnd.umajin" }, + { "unityweb", "application/vnd.unity" }, + { "uoml", "application/vnd.uoml+xml" }, + { "vcx", "application/vnd.vcx" }, + { "vsd", "application/vnd.visio" }, + { "vst", "application/vnd.visio" }, + { "vss", "application/vnd.visio" }, + { "vsw", "application/vnd.visio" }, + { "vis", "application/vnd.visionary" }, + { "vsf", "application/vnd.vsf" }, + { "wbxml", "application/vnd.wap.wbxml" }, + { "wmlc", "application/vnd.wap.wmlc" }, + { "wmlsc", "application/vnd.wap.wmlscriptc" }, + { "wtb", "application/vnd.webturbo" }, + { "nbp", "application/vnd.wolfram.player" }, + { "wpd", "application/vnd.wordperfect" }, + { "wqd", "application/vnd.wqd" }, + { "stf", "application/vnd.wt.stf" }, + { "xar", "application/vnd.xara" }, + { "xfdl", "application/vnd.xfdl" }, + { "hvd", "application/vnd.yamaha.hv-dic" }, + { "hvs", "application/vnd.yamaha.hv-script" }, + { "hvp", "application/vnd.yamaha.hv-voice" }, + { "osf", "application/vnd.yamaha.openscoreformat" }, + { "osfpvg", "application/vnd.yamaha.openscoreformat.osfpvg+xml" }, + { "saf", "application/vnd.yamaha.smaf-audio" }, + { "spf", "application/vnd.yamaha.smaf-phrase" }, + { "cmp", "application/vnd.yellowriver-custom-menu" }, + { "zir", "application/vnd.zul" }, + { "zirz", "application/vnd.zul" }, + { "zaz", "application/vnd.zzazz.deck+xml" }, + { "vxml", "application/voicexml+xml" }, + { "wgt", "application/widget" }, + { "hlp", "application/winhlp" }, + { "wsdl", "application/wsdl+xml" }, + { "wspolicy", "application/wspolicy+xml" }, + { "7z", "application/x-7z-compressed" }, + { "abw", "application/x-abiword" }, + { "ace", "application/x-ace-compressed" }, + { "dmg", "application/x-apple-diskimage" }, + { "aab", "application/x-authorware-bin" }, + { "x32", "application/x-authorware-bin" }, + { "u32", "application/x-authorware-bin" }, + { "vox", "application/x-authorware-bin" }, + { "aam", "application/x-authorware-map" }, + { "aas", "application/x-authorware-seg" }, + { "bcpio", "application/x-bcpio" }, + { "torrent", "application/x-bittorrent" }, + { "blb", "application/x-blorb" }, + { "blorb", "application/x-blorb" }, + { "bz", "application/x-bzip" }, + { "bz2", "application/x-bzip2" }, + { "boz", "application/x-bzip2" }, + { "cbr", "application/x-cbr" }, + { "cba", "application/x-cbr" }, + { "cbt", "application/x-cbr" }, + { "cbz", "application/x-cbr" }, + { "cb7", "application/x-cbr" }, + { "vcd", "application/x-cdlink" }, + { "cfs", "application/x-cfs-compressed" }, + { "chat", "application/x-chat" }, + { "pgn", "application/x-chess-pgn" }, + { "nsc", "application/x-conference" }, + { "cpio", "application/x-cpio" }, + { "csh", "application/x-csh" }, + { "deb", "application/x-debian-package" }, + { "udeb", "application/x-debian-package" }, + { "dgc", "application/x-dgc-compressed" }, + { "dir", "application/x-director" }, + { "dcr", "application/x-director" }, + { "dxr", "application/x-director" }, + { "cst", "application/x-director" }, + { "cct", "application/x-director" }, + { "cxt", "application/x-director" }, + { "w3d", "application/x-director" }, + { "fgd", "application/x-director" }, + { "swa", "application/x-director" }, + { "wad", "application/x-doom" }, + { "ncx", "application/x-dtbncx+xml" }, + { "dtb", "application/x-dtbook+xml" }, + { "res", "application/x-dtbresource+xml" }, + { "dvi", "application/x-dvi" }, + { "evy", "application/x-envoy" }, + { "eva", "application/x-eva" }, + { "bdf", "application/x-font-bdf" }, + { "gsf", "application/x-font-ghostscript" }, + { "psf", "application/x-font-linux-psf" }, + { "otf", "application/x-font-otf" }, + { "pcf", "application/x-font-pcf" }, + { "snf", "application/x-font-snf" }, + { "ttf", "application/x-font-ttf" }, + { "ttc", "application/x-font-ttf" }, + { "pfa", "application/x-font-type1" }, + { "pfb", "application/x-font-type1" }, + { "pfm", "application/x-font-type1" }, + { "afm", "application/x-font-type1" }, + { "woff", "application/font-woff" }, + { "arc", "application/x-freearc" }, + { "spl", "application/x-futuresplash" }, + { "gca", "application/x-gca-compressed" }, + { "ulx", "application/x-glulx" }, + { "gnumeric", "application/x-gnumeric" }, + { "gramps", "application/x-gramps-xml" }, + { "gtar", "application/x-gtar" }, + { "hdf", "application/x-hdf" }, + { "install", "application/x-install-instructions" }, + { "iso", "application/x-iso9660-image" }, + { "jnlp", "application/x-java-jnlp-file" }, + { "latex", "application/x-latex" }, + { "lzh", "application/x-lzh-compressed" }, + { "lha", "application/x-lzh-compressed" }, + { "mie", "application/x-mie" }, + { "prc", "application/x-mobipocket-ebook" }, + { "mobi", "application/x-mobipocket-ebook" }, + { "application", "application/x-ms-application" }, + { "lnk", "application/x-ms-shortcut" }, + { "wmd", "application/x-ms-wmd" }, + { "wmz", "application/x-msmetafile" }, + { "xbap", "application/x-ms-xbap" }, + { "mdb", "application/x-msaccess" }, + { "obd", "application/x-msbinder" }, + { "crd", "application/x-mscardfile" }, + { "clp", "application/x-msclip" }, + { "exe", "application/x-msdownload" }, + { "dll", "application/x-msdownload" }, + { "com", "application/x-msdownload" }, + { "bat", "application/x-msdownload" }, + { "msi", "application/x-msdownload" }, + { "mvb", "application/x-msmediaview" }, + { "m13", "application/x-msmediaview" }, + { "m14", "application/x-msmediaview" }, + { "wmf", "application/x-msmetafile" }, + { "emf", "application/x-msmetafile" }, + { "emz", "application/x-msmetafile" }, + { "mny", "application/x-msmoney" }, + { "pub", "application/x-mspublisher" }, + { "scd", "application/x-msschedule" }, + { "trm", "application/x-msterminal" }, + { "wri", "application/x-mswrite" }, + { "nc", "application/x-netcdf" }, + { "cdf", "application/x-netcdf" }, + { "nzb", "application/x-nzb" }, + { "p12", "application/x-pkcs12" }, + { "pfx", "application/x-pkcs12" }, + { "p7b", "application/x-pkcs7-certificates" }, + { "spc", "application/x-pkcs7-certificates" }, + { "p7r", "application/x-pkcs7-certreqresp" }, + { "rar", "application/x-rar-compressed" }, + { "ris", "application/x-research-info-systems" }, + { "sh", "application/x-sh" }, + { "shar", "application/x-shar" }, + { "swf", "application/x-shockwave-flash" }, + { "xap", "application/x-silverlight-app" }, + { "sql", "application/x-sql" }, + { "sit", "application/x-stuffit" }, + { "sitx", "application/x-stuffitx" }, + { "srt", "application/x-subrip" }, + { "sv4cpio", "application/x-sv4cpio" }, + { "sv4crc", "application/x-sv4crc" }, + { "t3", "application/x-t3vm-image" }, + { "gam", "application/x-tads" }, + { "tar", "application/x-tar" }, + { "tcl", "application/x-tcl" }, + { "tex", "application/x-tex" }, + { "tfm", "application/x-tex-tfm" }, + { "texinfo", "application/x-texinfo" }, + { "texi", "application/x-texinfo" }, + { "obj", "application/x-tgif" }, + { "ustar", "application/x-ustar" }, + { "src", "application/x-wais-source" }, + { "der", "application/x-x509-ca-cert" }, + { "crt", "application/x-x509-ca-cert" }, + { "fig", "application/x-xfig" }, + { "xlf", "application/x-xliff+xml" }, + { "xpi", "application/x-xpinstall" }, + { "xz", "application/x-xz" }, + { "z1", "application/x-zmachine" }, + { "z2", "application/x-zmachine" }, + { "z3", "application/x-zmachine" }, + { "z4", "application/x-zmachine" }, + { "z5", "application/x-zmachine" }, + { "z6", "application/x-zmachine" }, + { "z7", "application/x-zmachine" }, + { "z8", "application/x-zmachine" }, + { "xaml", "application/xaml+xml" }, + { "xdf", "application/xcap-diff+xml" }, + { "xenc", "application/xenc+xml" }, + { "xhtml", "application/xhtml+xml" }, + { "xht", "application/xhtml+xml" }, + { "xml", "application/xml" }, + { "xsl", "application/xml" }, + { "dtd", "application/xml-dtd" }, + { "xop", "application/xop+xml" }, + { "xpl", "application/xproc+xml" }, + { "xslt", "application/xslt+xml" }, + { "xspf", "application/xspf+xml" }, + { "mxml", "application/xv+xml" }, + { "xhvml", "application/xv+xml" }, + { "xvml", "application/xv+xml" }, + { "xvm", "application/xv+xml" }, + { "yang", "application/yang" }, + { "yin", "application/yin+xml" }, + { "zip", "application/zip" }, + { "adp", "audio/adpcm" }, + { "au", "audio/basic" }, + { "snd", "audio/basic" }, + { "mid", "audio/midi" }, + { "midi", "audio/midi" }, + { "kar", "audio/midi" }, + { "rmi", "audio/midi" }, + { "mp4a", "audio/mp4" }, + { "mpga", "audio/mpeg" }, + { "mp2", "audio/mpeg" }, + { "mp2a", "audio/mpeg" }, + { "mp3", "audio/mpeg" }, + { "m2a", "audio/mpeg" }, + { "m3a", "audio/mpeg" }, + { "oga", "audio/ogg" }, + { "ogg", "audio/ogg" }, + { "spx", "audio/ogg" }, + { "s3m", "audio/s3m" }, + { "sil", "audio/silk" }, + { "uva", "audio/vnd.dece.audio" }, + { "uvva", "audio/vnd.dece.audio" }, + { "eol", "audio/vnd.digital-winds" }, + { "dra", "audio/vnd.dra" }, + { "dts", "audio/vnd.dts" }, + { "dtshd", "audio/vnd.dts.hd" }, + { "lvp", "audio/vnd.lucent.voice" }, + { "pya", "audio/vnd.ms-playready.media.pya" }, + { "ecelp4800", "audio/vnd.nuera.ecelp4800" }, + { "ecelp7470", "audio/vnd.nuera.ecelp7470" }, + { "ecelp9600", "audio/vnd.nuera.ecelp9600" }, + { "rip", "audio/vnd.rip" }, + { "weba", "audio/webm" }, + { "aac", "audio/x-aac" }, + { "aif", "audio/x-aiff" }, + { "aiff", "audio/x-aiff" }, + { "aifc", "audio/x-aiff" }, + { "caf", "audio/x-caf" }, + { "flac", "audio/x-flac" }, + { "mka", "audio/x-matroska" }, + { "m3u", "audio/x-mpegurl" }, + { "wax", "audio/x-ms-wax" }, + { "wma", "audio/x-ms-wma" }, + { "ram", "audio/x-pn-realaudio" }, + { "ra", "audio/x-pn-realaudio" }, + { "rmp", "audio/x-pn-realaudio-plugin" }, + { "wav", "audio/x-wav" }, + { "xm", "audio/xm" }, + { "cdx", "chemical/x-cdx" }, + { "cif", "chemical/x-cif" }, + { "cmdf", "chemical/x-cmdf" }, + { "cml", "chemical/x-cml" }, + { "csml", "chemical/x-csml" }, + { "xyz", "chemical/x-xyz" }, + { "bmp", "image/bmp" }, + { "cgm", "image/cgm" }, + { "g3", "image/g3fax" }, + { "gif", "image/gif" }, + { "ief", "image/ief" }, + { "jpeg", "image/jpeg" }, + { "jpg", "image/jpeg" }, + { "jpe", "image/jpeg" }, + { "ktx", "image/ktx" }, + { "png", "image/png" }, + { "btif", "image/prs.btif" }, + { "sgi", "image/sgi" }, + { "svg", "image/svg+xml" }, + { "svgz", "image/svg+xml" }, + { "tiff", "image/tiff" }, + { "tif", "image/tiff" }, + { "psd", "image/vnd.adobe.photoshop" }, + { "uvi", "image/vnd.dece.graphic" }, + { "uvvi", "image/vnd.dece.graphic" }, + { "uvg", "image/vnd.dece.graphic" }, + { "uvvg", "image/vnd.dece.graphic" }, + { "sub", "text/vnd.dvb.subtitle" }, + { "djvu", "image/vnd.djvu" }, + { "djv", "image/vnd.djvu" }, + { "dwg", "image/vnd.dwg" }, + { "dxf", "image/vnd.dxf" }, + { "fbs", "image/vnd.fastbidsheet" }, + { "fpx", "image/vnd.fpx" }, + { "fst", "image/vnd.fst" }, + { "mmr", "image/vnd.fujixerox.edmics-mmr" }, + { "rlc", "image/vnd.fujixerox.edmics-rlc" }, + { "mdi", "image/vnd.ms-modi" }, + { "wdp", "image/vnd.ms-photo" }, + { "npx", "image/vnd.net-fpx" }, + { "wbmp", "image/vnd.wap.wbmp" }, + { "xif", "image/vnd.xiff" }, + { "webp", "image/webp" }, + { "3ds", "image/x-3ds" }, + { "ras", "image/x-cmu-raster" }, + { "cmx", "image/x-cmx" }, + { "fh", "image/x-freehand" }, + { "fhc", "image/x-freehand" }, + { "fh4", "image/x-freehand" }, + { "fh5", "image/x-freehand" }, + { "fh7", "image/x-freehand" }, + { "ico", "image/x-icon" }, + { "sid", "image/x-mrsid-image" }, + { "pcx", "image/x-pcx" }, + { "pic", "image/x-pict" }, + { "pct", "image/x-pict" }, + { "pnm", "image/x-portable-anymap" }, + { "pbm", "image/x-portable-bitmap" }, + { "pgm", "image/x-portable-graymap" }, + { "ppm", "image/x-portable-pixmap" }, + { "rgb", "image/x-rgb" }, + { "tga", "image/x-tga" }, + { "xbm", "image/x-xbitmap" }, + { "xpm", "image/x-xpixmap" }, + { "xwd", "image/x-xwindowdump" }, + { "eml", "message/rfc822" }, + { "mime", "message/rfc822" }, + { "igs", "model/iges" }, + { "iges", "model/iges" }, + { "msh", "model/mesh" }, + { "mesh", "model/mesh" }, + { "silo", "model/mesh" }, + { "dae", "model/vnd.collada+xml" }, + { "dwf", "model/vnd.dwf" }, + { "gdl", "model/vnd.gdl" }, + { "gtw", "model/vnd.gtw" }, + { "mts", "model/vnd.mts" }, + { "vtu", "model/vnd.vtu" }, + { "wrl", "model/vrml" }, + { "vrml", "model/vrml" }, + { "x3db", "model/x3d+binary" }, + { "x3dbz", "model/x3d+binary" }, + { "x3dv", "model/x3d+vrml" }, + { "x3dvz", "model/x3d+vrml" }, + { "x3d", "model/x3d+xml" }, + { "x3dz", "model/x3d+xml" }, + { "appcache", "text/cache-manifest" }, + { "ics", "text/calendar" }, + { "ifb", "text/calendar" }, + { "css", "text/css" }, + { "csv", "text/csv" }, + { "html", "text/html" }, + { "htm", "text/html" }, + { "n3", "text/n3" }, + { "txt", "text/plain" }, + { "text", "text/plain" }, + { "conf", "text/plain" }, + { "def", "text/plain" }, + { "list", "text/plain" }, + { "log", "text/plain" }, + { "in", "text/plain" }, + { "dsc", "text/prs.lines.tag" }, + { "rtx", "text/richtext" }, + { "sgml", "text/sgml" }, + { "sgm", "text/sgml" }, + { "tsv", "text/tab-separated-values" }, + { "t", "text/troff" }, + { "tr", "text/troff" }, + { "roff", "text/troff" }, + { "man", "text/troff" }, + { "me", "text/troff" }, + { "ms", "text/troff" }, + { "ttl", "text/turtle" }, + { "uri", "text/uri-list" }, + { "uris", "text/uri-list" }, + { "urls", "text/uri-list" }, + { "vcard", "text/vcard" }, + { "curl", "text/vnd.curl" }, + { "dcurl", "text/vnd.curl.dcurl" }, + { "scurl", "text/vnd.curl.scurl" }, + { "mcurl", "text/vnd.curl.mcurl" }, + { "fly", "text/vnd.fly" }, + { "flx", "text/vnd.fmi.flexstor" }, + { "gv", "text/vnd.graphviz" }, + { "3dml", "text/vnd.in3d.3dml" }, + { "spot", "text/vnd.in3d.spot" }, + { "jad", "text/vnd.sun.j2me.app-descriptor" }, + { "wml", "text/vnd.wap.wml" }, + { "wmls", "text/vnd.wap.wmlscript" }, + { "s", "text/x-asm" }, + { "asm", "text/x-asm" }, + { "c", "text/x-c" }, + { "cc", "text/x-c" }, + { "cxx", "text/x-c" }, + { "cpp", "text/x-c" }, + { "h", "text/x-c" }, + { "hh", "text/x-c" }, + { "dic", "text/x-c" }, + { "f", "text/x-fortran" }, + { "for", "text/x-fortran" }, + { "f77", "text/x-fortran" }, + { "f90", "text/x-fortran" }, + { "java", "text/x-java-source" }, + { "opml", "text/x-opml" }, + { "p", "text/x-pascal" }, + { "pas", "text/x-pascal" }, + { "nfo", "text/x-nfo" }, + { "etx", "text/x-setext" }, + { "sfv", "text/x-sfv" }, + { "uu", "text/x-uuencode" }, + { "vcs", "text/x-vcalendar" }, + { "vcf", "text/x-vcard" }, + { "3gp", "video/3gpp" }, + { "3g2", "video/3gpp2" }, + { "h261", "video/h261" }, + { "h263", "video/h263" }, + { "h264", "video/h264" }, + { "jpgv", "video/jpeg" }, + { "jpm", "video/jpm" }, + { "jpgm", "video/jpm" }, + { "mj2", "video/mj2" }, + { "mjp2", "video/mj2" }, + { "mp4", "video/mp4" }, + { "mp4v", "video/mp4" }, + { "mpg4", "video/mp4" }, + { "mpeg", "video/mpeg" }, + { "mpg", "video/mpeg" }, + { "mpe", "video/mpeg" }, + { "m1v", "video/mpeg" }, + { "m2v", "video/mpeg" }, + { "ogv", "video/ogg" }, + { "qt", "video/quicktime" }, + { "mov", "video/quicktime" }, + { "uvh", "video/vnd.dece.hd" }, + { "uvvh", "video/vnd.dece.hd" }, + { "uvm", "video/vnd.dece.mobile" }, + { "uvvm", "video/vnd.dece.mobile" }, + { "uvp", "video/vnd.dece.pd" }, + { "uvvp", "video/vnd.dece.pd" }, + { "uvs", "video/vnd.dece.sd" }, + { "uvvs", "video/vnd.dece.sd" }, + { "uvv", "video/vnd.dece.video" }, + { "uvvv", "video/vnd.dece.video" }, + { "dvb", "video/vnd.dvb.file" }, + { "fvt", "video/vnd.fvt" }, + { "mxu", "video/vnd.mpegurl" }, + { "m4u", "video/vnd.mpegurl" }, + { "pyv", "video/vnd.ms-playready.media.pyv" }, + { "uvu", "video/vnd.uvvu.mp4" }, + { "uvvu", "video/vnd.uvvu.mp4" }, + { "viv", "video/vnd.vivo" }, + { "webm", "video/webm" }, + { "f4v", "video/x-f4v" }, + { "fli", "video/x-fli" }, + { "flv", "video/x-flv" }, + { "m4v", "video/x-m4v" }, + { "mkv", "video/x-matroska" }, + { "mk3d", "video/x-matroska" }, + { "mks", "video/x-matroska" }, + { "mng", "video/x-mng" }, + { "asf", "video/x-ms-asf" }, + { "asx", "video/x-ms-asf" }, + { "vob", "video/x-ms-vob" }, + { "wm", "video/x-ms-wm" }, + { "wmv", "video/x-ms-wmv" }, + { "wmx", "video/x-ms-wmx" }, + { "wvx", "video/x-ms-wvx" }, + { "avi", "video/x-msvideo" }, + { "movie", "video/x-sgi-movie" }, + { "smv", "video/x-smv" }, + { "ice", "x-conference/x-cooltalk" }, + { "map", "application/json" }, + { NULL, NULL } +}; + +#endif /* PHP_CLI_SERVER_MIME_TYPE_MAP_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index 40a41e544d..978c8b332e 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -77,7 +77,6 @@ #include "zend_compile.h" #include "zend_execute.h" #include "zend_highlight.h" -#include "zend_indent.h" #include "zend_exceptions.h" #include "php_getopt.h" @@ -95,17 +94,24 @@ # include "win32/select.h" #endif +#if defined(PHP_WIN32) && defined(HAVE_OPENSSL) +# include "openssl/applink.c" +#endif + PHPAPI extern char *php_ini_opened_path; PHPAPI extern char *php_ini_scanned_path; PHPAPI extern char *php_ini_scanned_files; +#if defined(PHP_WIN32) && defined(ZTS) +ZEND_TSRMLS_CACHE_DEFINE() +#endif + #ifndef O_BINARY #define O_BINARY 0 #endif #define PHP_MODE_STANDARD 1 #define PHP_MODE_HIGHLIGHT 2 -#define PHP_MODE_INDENT 3 #define PHP_MODE_LINT 4 #define PHP_MODE_STRIP 5 #define PHP_MODE_CLI_DIRECT 6 @@ -173,58 +179,58 @@ const opt_struct OPTIONS[] = { {'-', 0, NULL} /* end of args */ }; -static int print_module_info(zend_module_entry *module TSRMLS_DC) /* {{{ */ +static int print_module_info(zval *element) /* {{{ */ { + zend_module_entry *module = (zend_module_entry*)Z_PTR_P(element); php_printf("%s\n", module->name); return ZEND_HASH_APPLY_KEEP; } /* }}} */ -static int module_name_cmp(const void *a, const void *b TSRMLS_DC) /* {{{ */ +static int module_name_cmp(const void *a, const void *b) /* {{{ */ { - Bucket *f = *((Bucket **) a); - Bucket *s = *((Bucket **) b); + Bucket *f = (Bucket *) a; + Bucket *s = (Bucket *) b; - return strcasecmp(((zend_module_entry *)f->pData)->name, - ((zend_module_entry *)s->pData)->name); + return strcasecmp(((zend_module_entry *)Z_PTR(f->val))->name, + ((zend_module_entry *)Z_PTR(s->val))->name); } /* }}} */ -static void print_modules(TSRMLS_D) /* {{{ */ +static void print_modules(void) /* {{{ */ { HashTable sorted_registry; - zend_module_entry tmp; - zend_hash_init(&sorted_registry, 50, NULL, NULL, 1); - zend_hash_copy(&sorted_registry, &module_registry, NULL, &tmp, sizeof(zend_module_entry)); - zend_hash_sort(&sorted_registry, zend_qsort, module_name_cmp, 0 TSRMLS_CC); - zend_hash_apply(&sorted_registry, (apply_func_t) print_module_info TSRMLS_CC); + zend_hash_init(&sorted_registry, 50, NULL, NULL, 0); + zend_hash_copy(&sorted_registry, &module_registry, NULL); + zend_hash_sort(&sorted_registry, module_name_cmp, 0); + zend_hash_apply(&sorted_registry, print_module_info); zend_hash_destroy(&sorted_registry); } /* }}} */ -static int print_extension_info(zend_extension *ext, void *arg TSRMLS_DC) /* {{{ */ +static int print_extension_info(zend_extension *ext, void *arg) /* {{{ */ { php_printf("%s\n", ext->name); return ZEND_HASH_APPLY_KEEP; } /* }}} */ -static int extension_name_cmp(const zend_llist_element **f, const zend_llist_element **s TSRMLS_DC) /* {{{ */ +static int extension_name_cmp(const zend_llist_element **f, const zend_llist_element **s) /* {{{ */ { return strcmp(((zend_extension *)(*f)->data)->name, ((zend_extension *)(*s)->data)->name); } /* }}} */ -static void print_extensions(TSRMLS_D) /* {{{ */ +static void print_extensions(void) /* {{{ */ { zend_llist sorted_exts; zend_llist_copy(&sorted_exts, &zend_extensions); sorted_exts.dtor = NULL; - zend_llist_sort(&sorted_exts, extension_name_cmp TSRMLS_CC); - zend_llist_apply(&sorted_exts, (llist_apply_func_t) print_extension_info TSRMLS_CC); + zend_llist_sort(&sorted_exts, extension_name_cmp); + zend_llist_apply(&sorted_exts, (llist_apply_func_t) print_extension_info); zend_llist_destroy(&sorted_exts); } /* }}} */ @@ -233,7 +239,7 @@ static void print_extensions(TSRMLS_D) /* {{{ */ #define STDOUT_FILENO 1 #endif -static inline int sapi_cli_select(int fd TSRMLS_DC) +static inline int sapi_cli_select(int fd) { fd_set wfd, dfd; struct timeval tv; @@ -244,7 +250,7 @@ static inline int sapi_cli_select(int fd TSRMLS_DC) PHP_SAFE_FD_SET(fd, &wfd); - tv.tv_sec = FG(default_socket_timeout); + tv.tv_sec = (long)FG(default_socket_timeout); tv.tv_usec = 0; ret = php_select(fd+1, &dfd, &wfd, &dfd, &tv); @@ -252,17 +258,17 @@ static inline int sapi_cli_select(int fd TSRMLS_DC) return ret != -1; } -PHP_CLI_API size_t sapi_cli_single_write(const char *str, uint str_length TSRMLS_DC) /* {{{ */ +PHP_CLI_API size_t sapi_cli_single_write(const char *str, size_t str_length) /* {{{ */ { #ifdef PHP_WRITE_STDOUT - long ret; + zend_long ret; #else size_t ret; #endif if (cli_shell_callbacks.cli_shell_write) { size_t shell_wrote; - shell_wrote = cli_shell_callbacks.cli_shell_write(str, str_length TSRMLS_CC); + shell_wrote = cli_shell_callbacks.cli_shell_write(str, str_length); if (shell_wrote > -1) { return shell_wrote; } @@ -271,7 +277,7 @@ PHP_CLI_API size_t sapi_cli_single_write(const char *str, uint str_length TSRMLS #ifdef PHP_WRITE_STDOUT do { ret = write(STDOUT_FILENO, str, str_length); - } while (ret <= 0 && errno == EAGAIN && sapi_cli_select(STDOUT_FILENO TSRMLS_CC)); + } while (ret <= 0 && errno == EAGAIN && sapi_cli_select(STDOUT_FILENO)); if (ret <= 0) { return 0; @@ -285,10 +291,10 @@ PHP_CLI_API size_t sapi_cli_single_write(const char *str, uint str_length TSRMLS } /* }}} */ -static int sapi_cli_ub_write(const char *str, uint str_length TSRMLS_DC) /* {{{ */ +static size_t sapi_cli_ub_write(const char *str, size_t str_length) /* {{{ */ { const char *ptr = str; - uint remaining = str_length; + size_t remaining = str_length; size_t ret; if (!str_length) { @@ -296,16 +302,16 @@ static int sapi_cli_ub_write(const char *str, uint str_length TSRMLS_DC) /* {{{ } if (cli_shell_callbacks.cli_shell_ub_write) { - int ub_wrote; - ub_wrote = cli_shell_callbacks.cli_shell_ub_write(str, str_length TSRMLS_CC); - if (ub_wrote > -1) { + size_t ub_wrote; + ub_wrote = cli_shell_callbacks.cli_shell_ub_write(str, str_length); + if (ub_wrote != (size_t) -1) { return ub_wrote; } } while (remaining > 0) { - ret = sapi_cli_single_write(ptr, remaining TSRMLS_CC); + ret = sapi_cli_single_write(ptr, remaining); if (!ret) { #ifndef PHP_CLI_WIN32_NO_CONSOLE php_handle_aborted_connection(); @@ -336,47 +342,47 @@ static void sapi_cli_flush(void *server_context) /* {{{ */ static char *php_self = ""; static char *script_filename = ""; -static void sapi_cli_register_variables(zval *track_vars_array TSRMLS_DC) /* {{{ */ +static void sapi_cli_register_variables(zval *track_vars_array) /* {{{ */ { - unsigned int len; + size_t len; char *docroot = ""; /* In CGI mode, we consider the environment to be a part of the server * variables */ - php_import_environment_variables(track_vars_array TSRMLS_CC); + php_import_environment_variables(track_vars_array); /* Build the special-case PHP_SELF variable for the CLI version */ len = strlen(php_self); - if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, len, &len TSRMLS_CC)) { - php_register_variable("PHP_SELF", php_self, track_vars_array TSRMLS_CC); + if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, len, &len)) { + php_register_variable("PHP_SELF", php_self, track_vars_array); } - if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_NAME", &php_self, len, &len TSRMLS_CC)) { - php_register_variable("SCRIPT_NAME", php_self, track_vars_array TSRMLS_CC); + if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_NAME", &php_self, len, &len)) { + php_register_variable("SCRIPT_NAME", php_self, track_vars_array); } /* filenames are empty for stdin */ len = strlen(script_filename); - if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_FILENAME", &script_filename, len, &len TSRMLS_CC)) { - php_register_variable("SCRIPT_FILENAME", script_filename, track_vars_array TSRMLS_CC); + if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_FILENAME", &script_filename, len, &len)) { + php_register_variable("SCRIPT_FILENAME", script_filename, track_vars_array); } - if (sapi_module.input_filter(PARSE_SERVER, "PATH_TRANSLATED", &script_filename, len, &len TSRMLS_CC)) { - php_register_variable("PATH_TRANSLATED", script_filename, track_vars_array TSRMLS_CC); + if (sapi_module.input_filter(PARSE_SERVER, "PATH_TRANSLATED", &script_filename, len, &len)) { + php_register_variable("PATH_TRANSLATED", script_filename, track_vars_array); } /* just make it available */ len = 0U; - if (sapi_module.input_filter(PARSE_SERVER, "DOCUMENT_ROOT", &docroot, len, &len TSRMLS_CC)) { - php_register_variable("DOCUMENT_ROOT", docroot, track_vars_array TSRMLS_CC); + if (sapi_module.input_filter(PARSE_SERVER, "DOCUMENT_ROOT", &docroot, len, &len)) { + php_register_variable("DOCUMENT_ROOT", docroot, track_vars_array); } } /* }}} */ -static void sapi_cli_log_message(char *message TSRMLS_DC) /* {{{ */ +static void sapi_cli_log_message(char *message) /* {{{ */ { fprintf(stderr, "%s\n", message); } /* }}} */ -static int sapi_cli_deactivate(TSRMLS_D) /* {{{ */ +static int sapi_cli_deactivate(void) /* {{{ */ { fflush(stdout); if(SG(request_info).argv0) { @@ -387,19 +393,19 @@ static int sapi_cli_deactivate(TSRMLS_D) /* {{{ */ } /* }}} */ -static char* sapi_cli_read_cookies(TSRMLS_D) /* {{{ */ +static char* sapi_cli_read_cookies(void) /* {{{ */ { return NULL; } /* }}} */ -static int sapi_cli_header_handler(sapi_header_struct *h, sapi_header_op_enum op, sapi_headers_struct *s TSRMLS_DC) /* {{{ */ +static int sapi_cli_header_handler(sapi_header_struct *h, sapi_header_op_enum op, sapi_headers_struct *s) /* {{{ */ { return 0; } /* }}} */ -static int sapi_cli_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) /* {{{ */ +static int sapi_cli_send_headers(sapi_headers_struct *sapi_headers) /* {{{ */ { /* We do nothing here, this function is needed to prevent that the fallback * header handling is called. */ @@ -407,7 +413,7 @@ static int sapi_cli_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) /* } /* }}} */ -static void sapi_cli_send_header(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC) /* {{{ */ +static void sapi_cli_send_header(sapi_header_struct *sapi_header, void *server_context) /* {{{ */ { } /* }}} */ @@ -425,10 +431,8 @@ static int php_cli_startup(sapi_module_struct *sapi_module) /* {{{ */ /* overwriteable ini defaults must be set in sapi_cli_ini_defaults() */ #define INI_DEFAULT(name,value)\ - Z_SET_REFCOUNT(tmp, 0);\ - Z_UNSET_ISREF(tmp); \ - ZVAL_STRINGL(&tmp, zend_strndup(value, sizeof(value)-1), sizeof(value)-1, 0);\ - zend_hash_update(configuration_hash, name, sizeof(name), &tmp, sizeof(zval), NULL);\ + ZVAL_NEW_STR(&tmp, zend_string_init(value, sizeof(value)-1, 1));\ + zend_hash_str_update(configuration_hash, name, sizeof(name)-1, &tmp);\ static void sapi_cli_ini_defaults(HashTable *configuration_hash) { @@ -468,7 +472,7 @@ static sapi_module_struct cli_sapi_module = { sapi_cli_log_message, /* Log message */ NULL, /* Get request time */ NULL, /* Child terminate */ - + STANDARD_SAPI_MODULE_PROPERTIES }; /* }}} */ @@ -498,7 +502,7 @@ static void php_cli_usage(char *argv0) } else { prog = "php"; } - + printf( "Usage: %s [options] [-f] <file> [--] [args...]\n" " %s [options] -r <code> [--] [args...]\n" " %s [options] [-B <begin_code>] -R <code> [-E <end_code>] [--] [args...]\n" @@ -513,7 +517,7 @@ static void php_cli_usage(char *argv0) " -a Run interactively\n" #endif " -c <path>|<file> Look for php.ini file in this directory\n" - " -n No php.ini file will be used\n" + " -n No configuration (ini) files will be used\n" " -d foo[=bar] Define INI entry foo with value 'bar'\n" " -e Generate extended information for debugger/profiler\n" " -f <file> Parse and execute <file>.\n" @@ -551,31 +555,24 @@ static void php_cli_usage(char *argv0) static php_stream *s_in_process = NULL; -static void cli_register_file_handles(TSRMLS_D) /* {{{ */ +static void cli_register_file_handles(void) /* {{{ */ { - zval *zin, *zout, *zerr; + zval zin, zout, zerr; php_stream *s_in, *s_out, *s_err; php_stream_context *sc_in=NULL, *sc_out=NULL, *sc_err=NULL; zend_constant ic, oc, ec; - - MAKE_STD_ZVAL(zin); - MAKE_STD_ZVAL(zout); - MAKE_STD_ZVAL(zerr); s_in = php_stream_open_wrapper_ex("php://stdin", "rb", 0, NULL, sc_in); s_out = php_stream_open_wrapper_ex("php://stdout", "wb", 0, NULL, sc_out); s_err = php_stream_open_wrapper_ex("php://stderr", "wb", 0, NULL, sc_err); if (s_in==NULL || s_out==NULL || s_err==NULL) { - FREE_ZVAL(zin); - FREE_ZVAL(zout); - FREE_ZVAL(zerr); if (s_in) php_stream_close(s_in); if (s_out) php_stream_close(s_out); if (s_err) php_stream_close(s_err); return; } - + #if PHP_DEBUG /* do not close stdout and stderr */ s_out->flags |= PHP_STREAM_FLAG_NO_CLOSE; @@ -584,34 +581,27 @@ static void cli_register_file_handles(TSRMLS_D) /* {{{ */ s_in_process = s_in; - php_stream_to_zval(s_in, zin); - php_stream_to_zval(s_out, zout); - php_stream_to_zval(s_err, zerr); - - ic.value = *zin; + php_stream_to_zval(s_in, &zin); + php_stream_to_zval(s_out, &zout); + php_stream_to_zval(s_err, &zerr); + + ZVAL_COPY_VALUE(&ic.value, &zin); ic.flags = CONST_CS; - ic.name = zend_strndup(ZEND_STRL("STDIN")); - ic.name_len = sizeof("STDIN"); + ic.name = zend_string_init("STDIN", sizeof("STDIN")-1, 1); ic.module_number = 0; - zend_register_constant(&ic TSRMLS_CC); + zend_register_constant(&ic); - oc.value = *zout; + ZVAL_COPY_VALUE(&oc.value, &zout); oc.flags = CONST_CS; - oc.name = zend_strndup(ZEND_STRL("STDOUT")); - oc.name_len = sizeof("STDOUT"); + oc.name = zend_string_init("STDOUT", sizeof("STDOUT")-1, 1); oc.module_number = 0; - zend_register_constant(&oc TSRMLS_CC); + zend_register_constant(&oc); - ec.value = *zerr; + ZVAL_COPY_VALUE(&ec.value, &zerr); ec.flags = CONST_CS; - ec.name = zend_strndup(ZEND_STRL("STDERR")); - ec.name_len = sizeof("STDERR"); + ec.name = zend_string_init("STDERR", sizeof("STDERR")-1, 1); ec.module_number = 0; - zend_register_constant(&ec TSRMLS_CC); - - FREE_ZVAL(zin); - FREE_ZVAL(zout); - FREE_ZVAL(zerr); + zend_register_constant(&ec); } /* }}} */ @@ -619,7 +609,7 @@ static const char *param_mode_conflict = "Either execute direct code, process st /* {{{ cli_seek_file_begin */ -static int cli_seek_file_begin(zend_file_handle *file_handle, char *script_file, int *lineno TSRMLS_DC) +static int cli_seek_file_begin(zend_file_handle *file_handle, char *script_file, int *lineno) { int c; @@ -643,8 +633,8 @@ static int cli_seek_file_begin(zend_file_handle *file_handle, char *script_file, /* handle situations where line is terminated by \r\n */ if (c == '\r') { if (fgetc(file_handle->handle.fp) != '\n') { - long pos = ftell(file_handle->handle.fp); - fseek(file_handle->handle.fp, pos - 1, SEEK_SET); + zend_long pos = zend_ftell(file_handle->handle.fp); + zend_fseek(file_handle->handle.fp, pos - 1, SEEK_SET); } } *lineno = 2; @@ -656,7 +646,7 @@ static int cli_seek_file_begin(zend_file_handle *file_handle, char *script_file, } /* }}} */ -static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */ +static int do_cli(int argc, char **argv) /* {{{ */ { int c; zend_file_handle file_handle; @@ -675,51 +665,53 @@ static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */ int hide_argv = 0; zend_try { - + CG(in_compilation) = 0; /* not initialized but needed for several options */ - EG(uninitialized_zval_ptr) = NULL; while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) { switch (c) { case 'i': /* php info & quit */ - if (php_request_startup(TSRMLS_C)==FAILURE) { + if (php_request_startup()==FAILURE) { goto err; } request_started = 1; - php_print_info(0xFFFFFFFF TSRMLS_CC); - php_output_end_all(TSRMLS_C); + php_print_info(0xFFFFFFFF); + php_output_end_all(); exit_status = (c == '?' && argc > 1 && !strchr(argv[1], c)); goto out; case 'v': /* show php version & quit */ - php_printf("PHP %s (%s) (built: %s %s) %s\nCopyright (c) 1997-2016 The PHP Group\n%s", + php_printf("PHP %s (%s) (built: %s %s) ( %s)\nCopyright (c) 1997-2016 The PHP Group\n%s", PHP_VERSION, cli_sapi_module.name, __DATE__, __TIME__, -#if ZEND_DEBUG && defined(HAVE_GCOV) - "(DEBUG GCOV)", -#elif ZEND_DEBUG - "(DEBUG)", -#elif defined(HAVE_GCOV) - "(GCOV)", +#if ZTS + "ZTS " #else - "", + "NTS " +#endif +#if ZEND_DEBUG + "DEBUG " #endif +#ifdef HAVE_GCOV + "GCOV " +#endif + , get_zend_version() ); - sapi_deactivate(TSRMLS_C); + sapi_deactivate(); goto out; case 'm': /* list compiled in modules */ - if (php_request_startup(TSRMLS_C)==FAILURE) { + if (php_request_startup()==FAILURE) { goto err; } request_started = 1; php_printf("[PHP Modules]\n"); - print_modules(TSRMLS_C); + print_modules(); php_printf("\n[Zend Modules]\n"); - print_extensions(TSRMLS_C); + print_extensions(); php_printf("\n"); - php_output_end_all(TSRMLS_C); + php_output_end_all(); exit_status=0; goto out; @@ -783,16 +775,6 @@ static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */ behavior=PHP_MODE_LINT; break; -#if 0 /* not yet operational, see also below ... */ - case '': /* generate indented source mode*/ - if (behavior == PHP_MODE_CLI_DIRECT || behavior == PHP_MODE_PROCESS_STDIN) { - param_error = "Source indenting only works for files.\n"; - break; - } - behavior=PHP_MODE_INDENT; - break; -#endif - case 'q': /* do not generate HTTP headers */ /* This is default so NOP */ break; @@ -810,7 +792,7 @@ static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */ behavior=PHP_MODE_CLI_DIRECT; exec_direct=php_optarg; break; - + case 'R': if (behavior == PHP_MODE_PROCESS_STDIN) { if (exec_run || script_file) { @@ -918,20 +900,18 @@ static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */ fflush(stdout); } - CG(interactive) = interactive; - /* only set script_file if not set already and not in direct mode and not at end of parameter list */ - if (argc > php_optind - && !script_file - && behavior!=PHP_MODE_CLI_DIRECT - && behavior!=PHP_MODE_PROCESS_STDIN - && strcmp(argv[php_optind-1],"--")) + if (argc > php_optind + && !script_file + && behavior!=PHP_MODE_CLI_DIRECT + && behavior!=PHP_MODE_PROCESS_STDIN + && strcmp(argv[php_optind-1],"--")) { script_file=argv[php_optind]; php_optind++; } if (script_file) { - if (cli_seek_file_begin(&file_handle, script_file, &lineno TSRMLS_CC) != SUCCESS) { + if (cli_seek_file_begin(&file_handle, script_file, &lineno) != SUCCESS) { goto err; } else { char real_path[MAXPATHLEN]; @@ -962,7 +942,7 @@ static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */ argv[php_optind-1] = (char*)file_handle.filename; SG(request_info).argv=argv+php_optind-1; - if (php_request_startup(TSRMLS_C)==FAILURE) { + if (php_request_startup()==FAILURE) { *arg_excp = arg_free; fclose(file_handle.handle.fp); PUTS("Could not startup.\n"); @@ -979,24 +959,24 @@ static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */ } } - zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC); + zend_is_auto_global_str(ZEND_STRL("_SERVER")); PG(during_request_startup) = 0; switch (behavior) { case PHP_MODE_STANDARD: if (strcmp(file_handle.filename, "-")) { - cli_register_file_handles(TSRMLS_C); + cli_register_file_handles(); } if (interactive && cli_shell_callbacks.cli_shell_run) { - exit_status = cli_shell_callbacks.cli_shell_run(TSRMLS_C); + exit_status = cli_shell_callbacks.cli_shell_run(); } else { - php_execute_script(&file_handle TSRMLS_CC); + php_execute_script(&file_handle); exit_status = EG(exit_status); } break; case PHP_MODE_LINT: - exit_status = php_lint_script(&file_handle TSRMLS_CC); + exit_status = php_lint_script(&file_handle); if (exit_status==SUCCESS) { zend_printf("No syntax errors detected in %s\n", file_handle.filename); } else { @@ -1004,8 +984,8 @@ static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */ } break; case PHP_MODE_STRIP: - if (open_file_for_scanning(&file_handle TSRMLS_CC)==SUCCESS) { - zend_strip(TSRMLS_C); + if (open_file_for_scanning(&file_handle)==SUCCESS) { + zend_strip(); } goto out; break; @@ -1013,87 +993,71 @@ static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */ { zend_syntax_highlighter_ini syntax_highlighter_ini; - if (open_file_for_scanning(&file_handle TSRMLS_CC)==SUCCESS) { + if (open_file_for_scanning(&file_handle)==SUCCESS) { php_get_highlight_struct(&syntax_highlighter_ini); - zend_highlight(&syntax_highlighter_ini TSRMLS_CC); + zend_highlight(&syntax_highlighter_ini); } goto out; } break; -#if 0 - /* Zeev might want to do something with this one day */ - case PHP_MODE_INDENT: - open_file_for_scanning(&file_handle TSRMLS_CC); - zend_indent(); - zend_file_handle_dtor(file_handle.handle TSRMLS_CC); - goto out; - break; -#endif case PHP_MODE_CLI_DIRECT: - cli_register_file_handles(TSRMLS_C); - if (zend_eval_string_ex(exec_direct, NULL, "Command line code", 1 TSRMLS_CC) == FAILURE) { + cli_register_file_handles(); + if (zend_eval_string_ex(exec_direct, NULL, "Command line code", 1) == FAILURE) { exit_status=254; } break; - + case PHP_MODE_PROCESS_STDIN: { char *input; size_t len, index = 0; - zval *argn, *argi; + zval argn, argi; - cli_register_file_handles(TSRMLS_C); + cli_register_file_handles(); - if (exec_begin && zend_eval_string_ex(exec_begin, NULL, "Command line begin code", 1 TSRMLS_CC) == FAILURE) { + if (exec_begin && zend_eval_string_ex(exec_begin, NULL, "Command line begin code", 1) == FAILURE) { exit_status=254; } - ALLOC_ZVAL(argi); - Z_TYPE_P(argi) = IS_LONG; - Z_LVAL_P(argi) = index; - INIT_PZVAL(argi); - zend_hash_update(&EG(symbol_table), "argi", sizeof("argi"), &argi, sizeof(zval *), NULL); while (exit_status == SUCCESS && (input=php_stream_gets(s_in_process, NULL, 0)) != NULL) { len = strlen(input); - while (len-- && (input[len]=='\n' || input[len]=='\r')) { + while (len > 0 && len-- && (input[len]=='\n' || input[len]=='\r')) { input[len] = '\0'; } - ALLOC_ZVAL(argn); - Z_TYPE_P(argn) = IS_STRING; - Z_STRLEN_P(argn) = ++len; - Z_STRVAL_P(argn) = estrndup(input, len); - INIT_PZVAL(argn); - zend_hash_update(&EG(symbol_table), "argn", sizeof("argn"), &argn, sizeof(zval *), NULL); - Z_LVAL_P(argi) = ++index; + ZVAL_STRINGL(&argn, input, len + 1); + zend_hash_str_update(&EG(symbol_table), "argn", sizeof("argn")-1, &argn); + ZVAL_LONG(&argi, ++index); + zend_hash_str_update(&EG(symbol_table), "argi", sizeof("argi")-1, &argi); if (exec_run) { - if (zend_eval_string_ex(exec_run, NULL, "Command line run code", 1 TSRMLS_CC) == FAILURE) { + if (zend_eval_string_ex(exec_run, NULL, "Command line run code", 1) == FAILURE) { exit_status=254; } } else { if (script_file) { - if (cli_seek_file_begin(&file_handle, script_file, &lineno TSRMLS_CC) != SUCCESS) { + if (cli_seek_file_begin(&file_handle, script_file, &lineno) != SUCCESS) { exit_status = 1; } else { CG(start_lineno) = lineno; - php_execute_script(&file_handle TSRMLS_CC); + php_execute_script(&file_handle); exit_status = EG(exit_status); } } } efree(input); } - if (exec_end && zend_eval_string_ex(exec_end, NULL, "Command line end code", 1 TSRMLS_CC) == FAILURE) { + if (exec_end && zend_eval_string_ex(exec_end, NULL, "Command line end code", 1) == FAILURE) { exit_status=254; } break; } + case PHP_MODE_REFLECTION_FUNCTION: case PHP_MODE_REFLECTION_CLASS: case PHP_MODE_REFLECTION_EXTENSION: case PHP_MODE_REFLECTION_ZEND_EXTENSION: { zend_class_entry *pce = NULL; - zval *arg, *ref; + zval arg, ref; zend_execute_data execute_data; switch (behavior) { @@ -1116,25 +1080,24 @@ static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */ pce = reflection_zend_extension_ptr; break; } - - MAKE_STD_ZVAL(arg); - ZVAL_STRING(arg, reflection_what, 1); - ALLOC_ZVAL(ref); - object_init_ex(ref, pce); - INIT_PZVAL(ref); + + ZVAL_STRING(&arg, reflection_what); + object_init_ex(&ref, pce); memset(&execute_data, 0, sizeof(zend_execute_data)); EG(current_execute_data) = &execute_data; - EX(function_state).function = pce->constructor; - zend_call_method_with_1_params(&ref, pce, &pce->constructor, "__construct", NULL, arg); + zend_call_method_with_1_params(&ref, pce, &pce->constructor, "__construct", NULL, &arg); if (EG(exception)) { - zval *msg = zend_read_property(zend_exception_get_default(TSRMLS_C), EG(exception), "message", sizeof("message")-1, 0 TSRMLS_CC); + zval tmp, *msg, rv; + + ZVAL_OBJ(&tmp, EG(exception)); + msg = zend_read_property(zend_ce_exception, &tmp, "message", sizeof("message")-1, 0, &rv); zend_printf("Exception: %s\n", Z_STRVAL_P(msg)); - zval_ptr_dtor(&EG(exception)); + zval_ptr_dtor(&tmp); EG(exception) = NULL; } else { - zend_call_method_with_1_params(NULL, reflection_ptr, NULL, "export", NULL, ref); + zend_call_method_with_1_params(NULL, reflection_ptr, NULL, "export", NULL, &ref); } zval_ptr_dtor(&ref); zval_ptr_dtor(&arg); @@ -1143,11 +1106,11 @@ static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */ } case PHP_MODE_REFLECTION_EXT_INFO: { - int len = strlen(reflection_what); + int len = (int)strlen(reflection_what); char *lcname = zend_str_tolower_dup(reflection_what, len); zend_module_entry *module; - if (zend_hash_find(&module_registry, lcname, len+1, (void**)&module) == FAILURE) { + if ((module = zend_hash_str_find_ptr(&module_registry, lcname, len)) == NULL) { if (!strcmp(reflection_what, "main")) { display_ini_entries(NULL); } else { @@ -1155,12 +1118,13 @@ static int do_cli(int argc, char **argv TSRMLS_DC) /* {{{ */ exit_status = 1; } } else { - php_info_print_module(module TSRMLS_CC); + php_info_print_module(module); } - + efree(lcname); break; } + case PHP_MODE_SHOW_INI_CONFIG: { zend_printf("Configuration File (php.ini) Path: %s\n", PHP_CONFIG_FILE_PATH); @@ -1184,8 +1148,8 @@ out: } return exit_status; err: - sapi_deactivate(TSRMLS_C); - zend_ini_deactivate(TSRMLS_C); + sapi_deactivate(); + zend_ini_deactivate(); exit_status = 1; goto out; } @@ -1199,9 +1163,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine int main(int argc, char *argv[]) #endif { -#ifdef ZTS - void ***tsrm_ls; -#endif #ifdef PHP_CLI_WIN32_NO_CONSOLE int argc = __argc; char **argv = __argv; @@ -1257,7 +1218,12 @@ int main(int argc, char *argv[]) #ifdef ZTS tsrm_startup(1, 1, 0, NULL); - tsrm_ls = ts_resource(0); + (void)ts_resource(0); + ZEND_TSRMLS_CACHE_UPDATE(); +#endif + +#ifdef ZEND_SIGNALS + zend_signal_startup(); #endif #ifdef PHP_WIN32 @@ -1280,7 +1246,7 @@ int main(int argc, char *argv[]) break; case 'd': { /* define ini entries on command line */ - int len = strlen(php_optarg); + int len = (int)strlen(php_optarg); char *val; if ((val = strchr(php_optarg, '='))) { @@ -1288,11 +1254,11 @@ int main(int argc, char *argv[]) if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') { ini_entries = realloc(ini_entries, ini_entries_len + len + sizeof("\"\"\n\0")); memcpy(ini_entries + ini_entries_len, php_optarg, (val - php_optarg)); - ini_entries_len += (val - php_optarg); + ini_entries_len += (int)(val - php_optarg); memcpy(ini_entries + ini_entries_len, "\"", 1); ini_entries_len++; memcpy(ini_entries + ini_entries_len, val, len - (val - php_optarg)); - ini_entries_len += len - (val - php_optarg); + ini_entries_len += len - (int)(val - php_optarg); memcpy(ini_entries + ini_entries_len, "\"\n\0", sizeof("\"\n\0")); ini_entries_len += sizeof("\n\0\"") - 2; } else { @@ -1365,7 +1331,7 @@ exit_loop: goto out; } module_started = 1; - + /* -e option */ if (use_extended_info) { CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO; @@ -1375,10 +1341,10 @@ exit_loop: #ifndef PHP_CLI_WIN32_NO_CONSOLE if (sapi_module == &cli_sapi_module) { #endif - exit_status = do_cli(argc, argv TSRMLS_CC); + exit_status = do_cli(argc, argv); #ifndef PHP_CLI_WIN32_NO_CONSOLE } else { - exit_status = do_cli_server(argc, argv TSRMLS_CC); + exit_status = do_cli_server(argc, argv); } #endif } zend_end_try(); @@ -1390,7 +1356,7 @@ out: free(ini_entries); } if (module_started) { - php_module_shutdown(TSRMLS_C); + php_module_shutdown(); } if (sapi_started) { sapi_shutdown(); diff --git a/sapi/cli/php_cli_process_title.c b/sapi/cli/php_cli_process_title.c index 4cb0118b96..9323e5e99a 100644 --- a/sapi/cli/php_cli_process_title.c +++ b/sapi/cli/php_cli_process_title.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -31,10 +31,10 @@ PHP_FUNCTION(cli_set_process_title) { char *title = NULL; - int title_len; + size_t title_len; int rc; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &title, &title_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &title, &title_len) == FAILURE) { return; } @@ -43,7 +43,7 @@ PHP_FUNCTION(cli_set_process_title) RETURN_TRUE; } - php_error_docref(NULL TSRMLS_CC, E_WARNING, "cli_set_process_title had an error: %s", ps_title_errno(rc)); + php_error_docref(NULL, E_WARNING, "cli_set_process_title had an error: %s", ps_title_errno(rc)); RETURN_FALSE; } /* }}} */ @@ -62,11 +62,11 @@ PHP_FUNCTION(cli_get_process_title) rc = get_ps_title(&length, &title); if (rc != PS_TITLE_SUCCESS) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "cli_get_process_title had an error: %s", ps_title_errno(rc)); + php_error_docref(NULL, E_WARNING, "cli_get_process_title had an error: %s", ps_title_errno(rc)); RETURN_NULL(); } - RETURN_STRINGL(title, length, 1); + RETURN_STRINGL(title, length); } /* }}} */ diff --git a/sapi/cli/php_cli_process_title.h b/sapi/cli/php_cli_process_title.h index 44037e8d39..f0a7e23b27 100644 --- a/sapi/cli/php_cli_process_title.h +++ b/sapi/cli/php_cli_process_title.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c index 82bd573b56..f94ac74741 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -68,11 +68,11 @@ #include "zend_hash.h" #include "zend_modules.h" #include "fopen_wrappers.h" +#include "http_status_codes.h" #include "zend_compile.h" #include "zend_execute.h" #include "zend_highlight.h" -#include "zend_indent.h" #include "zend_exceptions.h" #include "php_getopt.h" @@ -91,12 +91,8 @@ # define SOCK_EADDRINUSE WSAEADDRINUSE #endif -#ifndef S_ISDIR -#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR) -#endif - #include "ext/standard/file.h" /* for php_set_sock_blocking() :-( */ -#include "ext/standard/php_smart_str.h" +#include "zend_smart_str.h" #include "ext/standard/html.h" #include "ext/standard/url.h" /* for php_raw_url_decode() */ #include "ext/standard/php_string.h" /* for php_dirname() */ @@ -104,6 +100,7 @@ #include "php_http_parser.h" #include "php_cli_server.h" +#include "mime_type_map.h" #include "php_cli_process_title.h" @@ -138,7 +135,7 @@ typedef struct php_cli_server_request { size_t content_len; const char *ext; size_t ext_len; - struct stat sb; + zend_stat_t sb; } php_cli_server_request; typedef struct php_cli_server_chunk { @@ -194,6 +191,7 @@ typedef struct php_cli_server { size_t router_len; socklen_t socklen; HashTable clients; + HashTable extension_mime_types; } php_cli_server; typedef struct php_cli_server_http_response_status_code_pair { @@ -201,61 +199,6 @@ typedef struct php_cli_server_http_response_status_code_pair { const char *str; } php_cli_server_http_response_status_code_pair; -typedef struct php_cli_server_ext_mime_type_pair { - const char *ext; - const char *mime_type; -} php_cli_server_ext_mime_type_pair; - -static php_cli_server_http_response_status_code_pair status_map[] = { - { 100, "Continue" }, - { 101, "Switching Protocols" }, - { 200, "OK" }, - { 201, "Created" }, - { 202, "Accepted" }, - { 203, "Non-Authoritative Information" }, - { 204, "No Content" }, - { 205, "Reset Content" }, - { 206, "Partial Content" }, - { 300, "Multiple Choices" }, - { 301, "Moved Permanently" }, - { 302, "Found" }, - { 303, "See Other" }, - { 304, "Not Modified" }, - { 305, "Use Proxy" }, - { 307, "Temporary Redirect" }, - { 308, "Permanent Redirect" }, - { 400, "Bad Request" }, - { 401, "Unauthorized" }, - { 402, "Payment Required" }, - { 403, "Forbidden" }, - { 404, "Not Found" }, - { 405, "Method Not Allowed" }, - { 406, "Not Acceptable" }, - { 407, "Proxy Authentication Required" }, - { 408, "Request Timeout" }, - { 409, "Conflict" }, - { 410, "Gone" }, - { 411, "Length Required" }, - { 412, "Precondition Failed" }, - { 413, "Request Entity Too Large" }, - { 414, "Request-URI Too Long" }, - { 415, "Unsupported Media Type" }, - { 416, "Requested Range Not Satisfiable" }, - { 417, "Expectation Failed" }, - { 426, "Upgrade Required" }, - { 428, "Precondition Required" }, - { 429, "Too Many Requests" }, - { 431, "Request Header Fields Too Large" }, - { 451, "Unavailable For Legal Reasons"}, - { 500, "Internal Server Error" }, - { 501, "Not Implemented" }, - { 502, "Bad Gateway" }, - { 503, "Service Unavailable" }, - { 504, "Gateway Timeout" }, - { 505, "HTTP Version Not Supported" }, - { 511, "Network Authentication Required" }, -}; - static php_cli_server_http_response_status_code_pair template_map[] = { { 400, "<h1>%s</h1><p>Your browser sent a request that this server could not understand.</p>" }, { 404, "<h1>%s</h1><p>The requested resource <code class=\"url\">%s</code> was not found on this server.</p>" }, @@ -263,71 +206,15 @@ static php_cli_server_http_response_status_code_pair template_map[] = { { 501, "<h1>%s</h1><p>Request method not supported.</p>" } }; -static php_cli_server_ext_mime_type_pair mime_type_map[] = { - { "html", "text/html" }, - { "htm", "text/html" }, - { "js", "text/javascript" }, - { "css", "text/css" }, - { "gif", "image/gif" }, - { "jpg", "image/jpeg" }, - { "jpeg", "image/jpeg" }, - { "jpe", "image/jpeg" }, - { "pdf", "application/pdf" }, - { "png", "image/png" }, - { "svg", "image/svg+xml" }, - { "txt", "text/plain" }, - { "webm", "video/webm" }, - { "ogv", "video/ogg" }, - { "ogg", "audio/ogg" }, - { "3gp", "video/3gpp" }, /* This is standard video format used for MMS in phones */ - { "apk", "application/vnd.android.package-archive" }, - { "avi", "video/x-msvideo" }, - { "bmp", "image/x-ms-bmp" }, - { "csv", "text/comma-separated-values" }, - { "doc", "application/msword" }, - { "docx", "application/msword" }, - { "flac", "audio/flac" }, - { "gz", "application/x-gzip" }, - { "gzip", "application/x-gzip" }, - { "ics", "text/calendar" }, - { "kml", "application/vnd.google-earth.kml+xml" }, - { "kmz", "application/vnd.google-earth.kmz" }, - { "m4a", "audio/mp4" }, - { "mp3", "audio/mpeg" }, - { "mp4", "video/mp4" }, - { "mpg", "video/mpeg" }, - { "mpeg", "video/mpeg" }, - { "mov", "video/quicktime" }, - { "odp", "application/vnd.oasis.opendocument.presentation" }, - { "ods", "application/vnd.oasis.opendocument.spreadsheet" }, - { "odt", "application/vnd.oasis.opendocument.text" }, - { "oga", "audio/ogg" }, - { "pdf", "application/pdf" }, - { "pptx", "application/vnd.ms-powerpoint" }, - { "pps", "application/vnd.ms-powerpoint" }, - { "qt", "video/quicktime" }, - { "swf", "application/x-shockwave-flash" }, - { "tar", "application/x-tar" }, - { "text", "text/plain" }, - { "tif", "image/tiff" }, - { "wav", "audio/wav" }, - { "wmv", "video/x-ms-wmv" }, - { "xls", "application/vnd.ms-excel" }, - { "xlsx", "application/vnd.ms-excel" }, - { "zip", "application/x-zip-compressed" }, - { "xml", "application/xml" }, - { "xsl", "application/xml" }, - { "xsd", "application/xml" }, - { NULL, NULL } -}; - +#if HAVE_UNISTD_H static int php_cli_output_is_tty = OUTPUT_NOT_CHECKED; +#endif static size_t php_cli_server_client_send_through(php_cli_server_client *client, const char *str, size_t str_len); static php_cli_server_chunk *php_cli_server_chunk_heap_new_self_contained(size_t len); static void php_cli_server_buffer_append(php_cli_server_buffer *buffer, php_cli_server_chunk *chunk); -static void php_cli_server_logf(const char *format TSRMLS_DC, ...); -static void php_cli_server_log_response(php_cli_server_client *client, int status, const char *message TSRMLS_DC); +static void php_cli_server_logf(const char *format, ...); +static void php_cli_server_log_response(php_cli_server_client *client, int status, const char *message); ZEND_DECLARE_MODULE_GLOBALS(cli_server); @@ -372,9 +259,9 @@ int php_cli_server_get_system_time(char *buf) { } #endif -static void char_ptr_dtor_p(char **p) /* {{{ */ +static void char_ptr_dtor_p(zval *zv) /* {{{ */ { - pefree(*p, 1); + pefree(Z_PTR_P(zv), 1); } /* }}} */ static char *get_last_error() /* {{{ */ @@ -384,8 +271,8 @@ static char *get_last_error() /* {{{ */ static int status_comp(const void *a, const void *b) /* {{{ */ { - const php_cli_server_http_response_status_code_pair *pa = (const php_cli_server_http_response_status_code_pair *) a; - const php_cli_server_http_response_status_code_pair *pb = (const php_cli_server_http_response_status_code_pair *) b; + const http_response_status_code_pair *pa = (const http_response_status_code_pair *) a; + const http_response_status_code_pair *pb = (const http_response_status_code_pair *) b; if (pa->code < pb->code) { return -1; @@ -398,12 +285,10 @@ static int status_comp(const void *a, const void *b) /* {{{ */ static const char *get_status_string(int code) /* {{{ */ { - php_cli_server_http_response_status_code_pair needle, *result = NULL; - - needle.code = code; - needle.str = NULL; + http_response_status_code_pair needle = {code, NULL}, + *result = NULL; - result = bsearch(&needle, status_map, sizeof(status_map) / sizeof(needle), sizeof(needle), status_comp); + result = bsearch(&needle, http_status_map, http_status_map_len, sizeof(needle), status_comp); if (result) { return result->str; @@ -442,11 +327,11 @@ static void append_http_status_line(smart_str *buffer, int protocol_version, int } smart_str_appendl_ex(buffer, "HTTP", 4, persistent); smart_str_appendc_ex(buffer, '/', persistent); - smart_str_append_generic_ex(buffer, protocol_version / 100, persistent, int, _unsigned); + smart_str_append_long_ex(buffer, protocol_version / 100, persistent); smart_str_appendc_ex(buffer, '.', persistent); - smart_str_append_generic_ex(buffer, protocol_version % 100, persistent, int, _unsigned); + smart_str_append_long_ex(buffer, protocol_version % 100, persistent); smart_str_appendc_ex(buffer, ' ', persistent); - smart_str_append_generic_ex(buffer, response_code, persistent, int, _unsigned); + smart_str_append_long_ex(buffer, response_code, persistent); smart_str_appendc_ex(buffer, ' ', persistent); smart_str_appends_ex(buffer, get_status_string(response_code), persistent); smart_str_appendl_ex(buffer, "\r\n", 2, persistent); @@ -455,37 +340,29 @@ static void append_http_status_line(smart_str *buffer, int protocol_version, int static void append_essential_headers(smart_str* buffer, php_cli_server_client *client, int persistent) /* {{{ */ { { - char **val; - if (SUCCESS == zend_hash_find(&client->request.headers, "host", sizeof("host"), (void**)&val)) { + char *val; + if (NULL != (val = zend_hash_str_find_ptr(&client->request.headers, "host", sizeof("host")-1))) { smart_str_appendl_ex(buffer, "Host", sizeof("Host") - 1, persistent); smart_str_appendl_ex(buffer, ": ", sizeof(": ") - 1, persistent); - smart_str_appends_ex(buffer, *val, persistent); + smart_str_appends_ex(buffer, val, persistent); smart_str_appendl_ex(buffer, "\r\n", 2, persistent); } } smart_str_appendl_ex(buffer, "Connection: close\r\n", sizeof("Connection: close\r\n") - 1, persistent); } /* }}} */ -static const char *get_mime_type(const char *ext, size_t ext_len) /* {{{ */ +static const char *get_mime_type(const php_cli_server *server, const char *ext, size_t ext_len) /* {{{ */ { - php_cli_server_ext_mime_type_pair *pair; - for (pair = mime_type_map; pair->ext; pair++) { - size_t len = strlen(pair->ext); - if (len == ext_len && memcmp(pair->ext, ext, len) == 0) { - return pair->mime_type; - } - } - return NULL; + return (const char*)zend_hash_str_find_ptr(&server->extension_mime_types, ext, ext_len); } /* }}} */ PHP_FUNCTION(apache_request_headers) /* {{{ */ { php_cli_server_client *client; HashTable *headers; - char *key; - uint key_len; - char **value_pointer; - HashPosition pos; + zend_string *key; + char *value; + zval tmp; if (zend_parse_parameters_none() == FAILURE) { return; @@ -496,19 +373,17 @@ PHP_FUNCTION(apache_request_headers) /* {{{ */ array_init_size(return_value, zend_hash_num_elements(headers)); - zend_hash_internal_pointer_reset_ex(headers, &pos); - while (zend_hash_get_current_data_ex(headers, (void **)&value_pointer, &pos) == SUCCESS) { - zend_hash_get_current_key_ex(headers, &key, &key_len, NULL, 0, &pos); - add_assoc_string_ex(return_value, key, key_len, *value_pointer, 1); - zend_hash_move_forward_ex(headers, &pos); - } + ZEND_HASH_FOREACH_STR_KEY_PTR(headers, key, value) { + ZVAL_STRING(&tmp, value); + zend_symtable_update(Z_ARRVAL_P(return_value), key, &tmp); + } ZEND_HASH_FOREACH_END(); } /* }}} */ -static void add_response_header(sapi_header_struct *h, zval *return_value TSRMLS_DC) /* {{{ */ +static void add_response_header(sapi_header_struct *h, zval *return_value) /* {{{ */ { char *s, *p; - int len; + ptrdiff_t len; ALLOCA_FLAG(use_heap) if (h->header_len > 0) { @@ -525,7 +400,7 @@ static void add_response_header(sapi_header_struct *h, zval *return_value TSRMLS do { p++; } while (*p == ' ' || *p == '\t'); - add_assoc_stringl_ex(return_value, s, len+1, p, h->header_len - (p - h->header), 1); + add_assoc_stringl_ex(return_value, s, (uint)len, p, h->header_len - (p - h->header)); free_alloca(s, use_heap); } } @@ -539,18 +414,15 @@ PHP_FUNCTION(apache_response_headers) /* {{{ */ return; } - if (!&SG(sapi_headers).headers) { - RETURN_FALSE; - } array_init(return_value); - zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t)add_response_header, return_value TSRMLS_CC); + zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t)add_response_header, return_value); } /* }}} */ /* {{{ cli_server module */ -static void cli_server_init_globals(zend_cli_server_globals *cg TSRMLS_DC) +static void cli_server_init_globals(zend_cli_server_globals *cg) { cg->color = 0; } @@ -611,7 +483,7 @@ static int sapi_cli_server_startup(sapi_module_struct *sapi_module) /* {{{ */ return SUCCESS; } /* }}} */ -static int sapi_cli_server_ub_write(const char *str, uint str_length TSRMLS_DC) /* {{{ */ +static size_t sapi_cli_server_ub_write(const char *str, size_t str_length) /* {{{ */ { php_cli_server_client *client = SG(server_context); if (!client) { @@ -623,29 +495,28 @@ static int sapi_cli_server_ub_write(const char *str, uint str_length TSRMLS_DC) static void sapi_cli_server_flush(void *server_context) /* {{{ */ { php_cli_server_client *client = server_context; - TSRMLS_FETCH(); if (!client) { return; } - if (client->sock < 0) { + if (!ZEND_VALID_SOCKET(client->sock)) { php_handle_aborted_connection(); return; } if (!SG(headers_sent)) { - sapi_send_headers(TSRMLS_C); + sapi_send_headers(); SG(headers_sent) = 1; } } /* }}} */ -static int sapi_cli_server_discard_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) /* {{{ */{ +static int sapi_cli_server_discard_headers(sapi_headers_struct *sapi_headers) /* {{{ */{ return SAPI_HEADER_SENT_SUCCESSFULLY; } /* }}} */ -static int sapi_cli_server_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) /* {{{ */ +static int sapi_cli_server_send_headers(sapi_headers_struct *sapi_headers) /* {{{ */ { php_cli_server_client *client = SG(server_context); smart_str buffer = { 0 }; @@ -675,24 +546,24 @@ static int sapi_cli_server_send_headers(sapi_headers_struct *sapi_headers TSRMLS } smart_str_appendl(&buffer, "\r\n", 2); - php_cli_server_client_send_through(client, buffer.c, buffer.len); + php_cli_server_client_send_through(client, ZSTR_VAL(buffer.s), ZSTR_LEN(buffer.s)); smart_str_free(&buffer); return SAPI_HEADER_SENT_SUCCESSFULLY; } /* }}} */ -static char *sapi_cli_server_read_cookies(TSRMLS_D) /* {{{ */ +static char *sapi_cli_server_read_cookies(void) /* {{{ */ { php_cli_server_client *client = SG(server_context); - char **val; - if (FAILURE == zend_hash_find(&client->request.headers, "cookie", sizeof("cookie"), (void**)&val)) { + char *val; + if (NULL == (val = zend_hash_str_find_ptr(&client->request.headers, "cookie", sizeof("cookie")-1))) { return NULL; } - return *val; + return val; } /* }}} */ -static int sapi_cli_server_read_post(char *buf, uint count_bytes TSRMLS_DC) /* {{{ */ +static size_t sapi_cli_server_read_post(char *buf, size_t count_bytes) /* {{{ */ { php_cli_server_client *client = SG(server_context); if (client->request.content) { @@ -705,27 +576,27 @@ static int sapi_cli_server_read_post(char *buf, uint count_bytes TSRMLS_DC) /* { return 0; } /* }}} */ -static void sapi_cli_server_register_variable(zval *track_vars_array, const char *key, const char *val TSRMLS_DC) /* {{{ */ +static void sapi_cli_server_register_variable(zval *track_vars_array, const char *key, const char *val) /* {{{ */ { char *new_val = (char *)val; - uint new_val_len; + size_t new_val_len; if (NULL == val) { return; } - if (sapi_module.input_filter(PARSE_SERVER, (char*)key, &new_val, strlen(val), &new_val_len TSRMLS_CC)) { - php_register_variable_safe((char *)key, new_val, new_val_len, track_vars_array TSRMLS_CC); + if (sapi_module.input_filter(PARSE_SERVER, (char*)key, &new_val, strlen(val), &new_val_len)) { + php_register_variable_safe((char *)key, new_val, new_val_len, track_vars_array); } } /* }}} */ -static int sapi_cli_server_register_entry_cb(char **entry TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ { +static int sapi_cli_server_register_entry_cb(char **entry, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ { zval *track_vars_array = va_arg(args, zval *); - if (hash_key->nKeyLength) { + if (hash_key->key) { char *real_key, *key; uint i; - key = estrndup(hash_key->arKey, hash_key->nKeyLength); - for(i=0; i<hash_key->nKeyLength; i++) { + key = estrndup(ZSTR_VAL(hash_key->key), ZSTR_LEN(hash_key->key)); + for(i=0; i<ZSTR_LEN(hash_key->key); i++) { if (key[i] == '-') { key[i] = '_'; } else { @@ -734,9 +605,9 @@ static int sapi_cli_server_register_entry_cb(char **entry TSRMLS_DC, int num_arg } spprintf(&real_key, 0, "%s_%s", "HTTP", key); if (strcmp(key, "CONTENT_TYPE") == 0 || strcmp(key, "CONTENT_LENGTH") == 0) { - sapi_cli_server_register_variable(track_vars_array, key, *entry TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, key, *entry); } - sapi_cli_server_register_variable(track_vars_array, real_key, *entry TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, real_key, *entry); efree(key); efree(real_key); } @@ -745,10 +616,10 @@ static int sapi_cli_server_register_entry_cb(char **entry TSRMLS_DC, int num_arg } /* }}} */ -static void sapi_cli_server_register_variables(zval *track_vars_array TSRMLS_DC) /* {{{ */ +static void sapi_cli_server_register_variables(zval *track_vars_array) /* {{{ */ { php_cli_server_client *client = SG(server_context); - sapi_cli_server_register_variable(track_vars_array, "DOCUMENT_ROOT", client->server->document_root TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, "DOCUMENT_ROOT", client->server->document_root); { char *tmp; if ((tmp = strrchr(client->addr_str, ':'))) { @@ -757,61 +628,61 @@ static void sapi_cli_server_register_variables(zval *track_vars_array TSRMLS_DC) port[7] = '\0'; strncpy(addr, client->addr_str, tmp - client->addr_str); addr[tmp - client->addr_str] = '\0'; - sapi_cli_server_register_variable(track_vars_array, "REMOTE_ADDR", addr TSRMLS_CC); - sapi_cli_server_register_variable(track_vars_array, "REMOTE_PORT", port TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, "REMOTE_ADDR", addr); + sapi_cli_server_register_variable(track_vars_array, "REMOTE_PORT", port); } else { - sapi_cli_server_register_variable(track_vars_array, "REMOTE_ADDR", client->addr_str TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, "REMOTE_ADDR", client->addr_str); } } { char *tmp; spprintf(&tmp, 0, "PHP %s Development Server", PHP_VERSION); - sapi_cli_server_register_variable(track_vars_array, "SERVER_SOFTWARE", tmp TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, "SERVER_SOFTWARE", tmp); efree(tmp); } { char *tmp; spprintf(&tmp, 0, "HTTP/%d.%d", client->request.protocol_version / 100, client->request.protocol_version % 100); - sapi_cli_server_register_variable(track_vars_array, "SERVER_PROTOCOL", tmp TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, "SERVER_PROTOCOL", tmp); efree(tmp); } - sapi_cli_server_register_variable(track_vars_array, "SERVER_NAME", client->server->host TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, "SERVER_NAME", client->server->host); { char *tmp; spprintf(&tmp, 0, "%i", client->server->port); - sapi_cli_server_register_variable(track_vars_array, "SERVER_PORT", tmp TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, "SERVER_PORT", tmp); efree(tmp); } - sapi_cli_server_register_variable(track_vars_array, "REQUEST_URI", client->request.request_uri TSRMLS_CC); - sapi_cli_server_register_variable(track_vars_array, "REQUEST_METHOD", SG(request_info).request_method TSRMLS_CC); - sapi_cli_server_register_variable(track_vars_array, "SCRIPT_NAME", client->request.vpath TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, "REQUEST_URI", client->request.request_uri); + sapi_cli_server_register_variable(track_vars_array, "REQUEST_METHOD", SG(request_info).request_method); + sapi_cli_server_register_variable(track_vars_array, "SCRIPT_NAME", client->request.vpath); if (SG(request_info).path_translated) { - sapi_cli_server_register_variable(track_vars_array, "SCRIPT_FILENAME", SG(request_info).path_translated TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, "SCRIPT_FILENAME", SG(request_info).path_translated); } else if (client->server->router) { char *temp; spprintf(&temp, 0, "%s/%s", client->server->document_root, client->server->router); - sapi_cli_server_register_variable(track_vars_array, "SCRIPT_FILENAME", temp TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, "SCRIPT_FILENAME", temp); efree(temp); } if (client->request.path_info) { - sapi_cli_server_register_variable(track_vars_array, "PATH_INFO", client->request.path_info TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, "PATH_INFO", client->request.path_info); } if (client->request.path_info_len) { char *tmp; spprintf(&tmp, 0, "%s%s", client->request.vpath, client->request.path_info); - sapi_cli_server_register_variable(track_vars_array, "PHP_SELF", tmp TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, "PHP_SELF", tmp); efree(tmp); } else { - sapi_cli_server_register_variable(track_vars_array, "PHP_SELF", client->request.vpath TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, "PHP_SELF", client->request.vpath); } if (client->request.query_string) { - sapi_cli_server_register_variable(track_vars_array, "QUERY_STRING", client->request.query_string TSRMLS_CC); + sapi_cli_server_register_variable(track_vars_array, "QUERY_STRING", client->request.query_string); } - zend_hash_apply_with_arguments(&client->request.headers TSRMLS_CC, (apply_func_args_t)sapi_cli_server_register_entry_cb, 1, track_vars_array); + zend_hash_apply_with_arguments(&client->request.headers, (apply_func_args_t)sapi_cli_server_register_entry_cb, 1, track_vars_array); } /* }}} */ -static void sapi_cli_server_log_message(char *msg TSRMLS_DC) /* {{{ */ +static void sapi_cli_server_log_message(char *msg) /* {{{ */ { char buf[52]; @@ -870,7 +741,7 @@ static int php_cli_server_poller_ctor(php_cli_server_poller *poller) /* {{{ */ return SUCCESS; } /* }}} */ -static void php_cli_server_poller_add(php_cli_server_poller *poller, int mode, int fd) /* {{{ */ +static void php_cli_server_poller_add(php_cli_server_poller *poller, int mode, php_socket_t fd) /* {{{ */ { if (mode & POLLIN) { PHP_SAFE_FD_SET(fd, &poller->rfds); @@ -883,7 +754,7 @@ static void php_cli_server_poller_add(php_cli_server_poller *poller, int mode, i } } /* }}} */ -static void php_cli_server_poller_remove(php_cli_server_poller *poller, int mode, int fd) /* {{{ */ +static void php_cli_server_poller_remove(php_cli_server_poller *poller, int mode, php_socket_t fd) /* {{{ */ { if (mode & POLLIN) { PHP_SAFE_FD_CLR(fd, &poller->rfds); @@ -911,7 +782,7 @@ static int php_cli_server_poller_poll(php_cli_server_poller *poller, struct time return php_select(poller->max_fd + 1, &poller->active.rfds, &poller->active.wfds, NULL, tv); } /* }}} */ -static int php_cli_server_poller_iter_on_active(php_cli_server_poller *poller, void *opaque, int(*callback)(void *, int fd, int events)) /* {{{ */ +static int php_cli_server_poller_iter_on_active(php_cli_server_poller *poller, void *opaque, int(*callback)(void *, php_socket_t fd, int events)) /* {{{ */ { int retval = SUCCESS; #ifdef PHP_WIN32 @@ -919,7 +790,6 @@ static int php_cli_server_poller_iter_on_active(php_cli_server_poller *poller, v SOCKET fd; int events; } entries[FD_SETSIZE * 2]; - php_socket_t fd = 0; size_t i; struct socket_entry *n = entries, *m; @@ -1062,7 +932,7 @@ static php_cli_server_chunk *php_cli_server_chunk_immortal_new(const char *buf, return chunk; } /* }}} */ -static php_cli_server_chunk *php_cli_server_chunk_heap_new(char *block, char *buf, size_t len) /* {{{ */ +static php_cli_server_chunk *php_cli_server_chunk_heap_new(void *block, char *buf, size_t len) /* {{{ */ { php_cli_server_chunk *chunk = pemalloc(sizeof(php_cli_server_chunk), 1); if (!chunk) { @@ -1108,12 +978,20 @@ static int php_cli_server_content_sender_send(php_cli_server_content_sender *sen size_t _nbytes_sent_total = 0; for (chunk = sender->buffer.first; chunk; chunk = next) { +#ifdef PHP_WIN32 + int nbytes_sent; +#else ssize_t nbytes_sent; +#endif next = chunk->next; switch (chunk->type) { case PHP_CLI_SERVER_CHUNK_HEAP: +#ifdef PHP_WIN32 + nbytes_sent = send(fd, chunk->data.heap.p, (int)chunk->data.heap.len, 0); +#else nbytes_sent = send(fd, chunk->data.heap.p, chunk->data.heap.len, 0); +#endif if (nbytes_sent < 0) { *nbytes_sent_total = _nbytes_sent_total; return php_socket_errno(); @@ -1132,7 +1010,11 @@ static int php_cli_server_content_sender_send(php_cli_server_content_sender *sen break; case PHP_CLI_SERVER_CHUNK_IMMORTAL: +#ifdef PHP_WIN32 + nbytes_sent = send(fd, chunk->data.immortal.p, (int)chunk->data.immortal.len, 0); +#else nbytes_sent = send(fd, chunk->data.immortal.p, chunk->data.immortal.len, 0); +#endif if (nbytes_sent < 0) { *nbytes_sent_total = _nbytes_sent_total; return php_socket_errno(); @@ -1157,14 +1039,21 @@ static int php_cli_server_content_sender_send(php_cli_server_content_sender *sen static int php_cli_server_content_sender_pull(php_cli_server_content_sender *sender, int fd, size_t *nbytes_read) /* {{{ */ { +#ifdef PHP_WIN32 + int _nbytes_read; +#else ssize_t _nbytes_read; +#endif php_cli_server_chunk *chunk = php_cli_server_chunk_heap_new_self_contained(131072); +#ifdef PHP_WIN32 + _nbytes_read = read(fd, chunk->data.heap.p, (unsigned int)chunk->data.heap.len); +#else _nbytes_read = read(fd, chunk->data.heap.p, chunk->data.heap.len); +#endif if (_nbytes_read < 0) { char *errstr = get_last_error(); - TSRMLS_FETCH(); - php_cli_server_logf("%s" TSRMLS_CC, errstr); + php_cli_server_logf("%s", errstr); pefree(errstr, 1); php_cli_server_chunk_dtor(chunk); pefree(chunk, 1); @@ -1186,7 +1075,7 @@ static int php_cli_is_output_tty() /* {{{ */ } /* }}} */ #endif -static void php_cli_server_log_response(php_cli_server_client *client, int status, const char *message TSRMLS_DC) /* {{{ */ +static void php_cli_server_log_response(php_cli_server_client *client, int status, const char *message) /* {{{ */ { int color = 0, effective_status = status; char *basic_buf, *message_buf = "", *error_buf = ""; @@ -1252,9 +1141,9 @@ static void php_cli_server_log_response(php_cli_server_client *client, int statu } if (color) { - php_cli_server_logf("\x1b[3%dm%s%s%s\x1b[0m" TSRMLS_CC, color, basic_buf, message_buf, error_buf); + php_cli_server_logf("\x1b[3%dm%s%s%s\x1b[0m", color, basic_buf, message_buf, error_buf); } else { - php_cli_server_logf("%s%s%s" TSRMLS_CC, basic_buf, message_buf, error_buf); + php_cli_server_logf("%s%s%s", basic_buf, message_buf, error_buf); } efree(basic_buf); @@ -1266,15 +1155,12 @@ static void php_cli_server_log_response(php_cli_server_client *client, int statu } } /* }}} */ -static void php_cli_server_logf(const char *format TSRMLS_DC, ...) /* {{{ */ +static void php_cli_server_logf(const char *format, ...) /* {{{ */ { char *buf = NULL; va_list ap; -#ifdef ZTS - va_start(ap, tsrm_ls); -#else + va_start(ap, format); -#endif vspprintf(&buf, 0, format, ap); va_end(ap); @@ -1283,19 +1169,19 @@ static void php_cli_server_logf(const char *format TSRMLS_DC, ...) /* {{{ */ } if (sapi_module.log_message) { - sapi_module.log_message(buf TSRMLS_CC); + sapi_module.log_message(buf); } efree(buf); } /* }}} */ -static int php_network_listen_socket(const char *host, int *port, int socktype, int *af, socklen_t *socklen, char **errstr TSRMLS_DC) /* {{{ */ +static php_socket_t php_network_listen_socket(const char *host, int *port, int socktype, int *af, socklen_t *socklen, zend_string **errstr) /* {{{ */ { - int retval = SOCK_ERR; + php_socket_t retval = SOCK_ERR; int err = 0; struct sockaddr *sa = NULL, **p, **sal; - int num_addrs = php_network_getaddresses(host, socktype, &sal, errstr TSRMLS_CC); + int num_addrs = php_network_getaddresses(host, socktype, &sal, errstr); if (num_addrs == 0) { return -1; } @@ -1400,11 +1286,11 @@ out: php_network_freeaddresses(sal); } if (err) { - if (retval >= 0) { + if (ZEND_VALID_SOCKET(retval)) { closesocket(retval); } if (errstr) { - *errstr = php_socket_strerror(err, NULL, 0); + *errstr = php_socket_error_str(err); } return SOCK_ERR; } @@ -1413,6 +1299,9 @@ out: static int php_cli_server_request_ctor(php_cli_server_request *req) /* {{{ */ { +#ifdef ZTS +ZEND_TSRMLS_CACHE_UPDATE(); +#endif req->protocol_version = 0; req->request_uri = NULL; req->request_uri_len = 0; @@ -1424,7 +1313,7 @@ static int php_cli_server_request_ctor(php_cli_server_request *req) /* {{{ */ req->path_info_len = 0; req->query_string = NULL; req->query_string_len = 0; - zend_hash_init(&req->headers, 0, NULL, (void(*)(void*))char_ptr_dtor_p, 1); + zend_hash_init(&req->headers, 0, NULL, char_ptr_dtor_p, 1); zend_hash_init(&req->headers_original_case, 0, NULL, NULL, 1); req->content = NULL; req->content_len = 0; @@ -1459,7 +1348,7 @@ static void php_cli_server_request_dtor(php_cli_server_request *req) /* {{{ */ static void php_cli_server_request_translate_vpath(php_cli_server_request *request, const char *document_root, size_t document_root_len) /* {{{ */ { - struct stat sb; + zend_stat_t sb; static const char *index_files[] = { "index.php", "index.html", NULL }; char *buf = safe_pemalloc(1, request->vpath_len, 1 + document_root_len + 1 + sizeof("index.html"), 1); char *p = buf, *prev_path = NULL, *q, *vpath; @@ -1496,7 +1385,7 @@ static void php_cli_server_request_translate_vpath(php_cli_server_request *reque *p = '\0'; q = p; while (q > buf) { - if (!stat(buf, &sb)) { + if (!zend_stat(buf, &sb)) { if (sb.st_mode & S_IFDIR) { const char **file = index_files; if (q[-1] != DEFAULT_SLASH) { @@ -1505,7 +1394,7 @@ static void php_cli_server_request_translate_vpath(php_cli_server_request *reque while (*file) { size_t l = strlen(*file); memmove(q, *file, l + 1); - if (!stat(buf, &sb) && (sb.st_mode & S_IFREG)) { + if (!zend_stat(buf, &sb) && (sb.st_mode & S_IFREG)) { q += l; break; } @@ -1578,7 +1467,7 @@ static void normalize_vpath(char **retval, size_t *retval_len, const char *vpath return; } - decoded_vpath_end = decoded_vpath + php_raw_url_decode(decoded_vpath, vpath_len); + decoded_vpath_end = decoded_vpath + php_raw_url_decode(decoded_vpath, (int)vpath_len); #ifdef PHP_WIN32 { @@ -1707,13 +1596,12 @@ static int php_cli_server_client_read_request_on_header_value(php_http_parser *p } { /* strip off the colon */ - char *orig_header_name = estrndup(client->current_header_name, client->current_header_name_len); + zend_string *orig_header_name = zend_string_init(client->current_header_name, client->current_header_name_len, 1); char *lc_header_name = zend_str_tolower_dup(client->current_header_name, client->current_header_name_len); - - zend_hash_add(&client->request.headers, lc_header_name, client->current_header_name_len + 1, &value, sizeof(char *), NULL); - zend_hash_add(&client->request.headers_original_case, orig_header_name, client->current_header_name_len + 1, &value, sizeof(char *), NULL); + zend_hash_str_add_ptr(&client->request.headers, lc_header_name, client->current_header_name_len, value); + zend_hash_add_ptr(&client->request.headers_original_case, orig_header_name, value); efree(lc_header_name); - efree(orig_header_name); + zend_string_release(orig_header_name); } if (client->current_header_name_allocated) { @@ -1773,7 +1661,7 @@ static int php_cli_server_client_read_request_on_message_complete(php_http_parse return 0; } -static int php_cli_server_client_read_request(php_cli_server_client *client, char **errstr TSRMLS_DC) +static int php_cli_server_client_read_request(php_cli_server_client *client, char **errstr) { char buf[16384]; static const php_http_parser_settings settings = { @@ -1831,9 +1719,19 @@ static int php_cli_server_client_read_request(php_cli_server_client *client, cha static size_t php_cli_server_client_send_through(php_cli_server_client *client, const char *str, size_t str_len) /* {{{ */ { struct timeval tv = { 10, 0 }; - ssize_t nbytes_left = str_len; +#ifdef PHP_WIN32 + int nbytes_left = (int)str_len; +#else + ssize_t nbytes_left = (ssize_t)str_len; +#endif do { - ssize_t nbytes_sent = send(client->sock, str + str_len - nbytes_left, nbytes_left, 0); +#ifdef PHP_WIN32 + int nbytes_sent; +#else + ssize_t nbytes_sent; +#endif + + nbytes_sent = send(client->sock, str + str_len - nbytes_left, nbytes_left, 0); if (nbytes_sent < 0) { int err = php_socket_errno(); if (err == SOCK_EAGAIN) { @@ -1862,7 +1760,7 @@ static size_t php_cli_server_client_send_through(php_cli_server_client *client, static void php_cli_server_client_populate_request_info(const php_cli_server_client *client, sapi_request_info *request_info) /* {{{ */ { - char **val; + char *val; request_info->request_method = php_http_method_str(client->request.request_method); request_info->proto_num = client->request.protocol_version; @@ -1871,8 +1769,8 @@ static void php_cli_server_client_populate_request_info(const php_cli_server_cli request_info->query_string = client->request.query_string; request_info->content_length = client->request.content_len; request_info->auth_user = request_info->auth_password = request_info->auth_digest = NULL; - if (SUCCESS == zend_hash_find(&client->request.headers, "content-type", sizeof("content-type"), (void**)&val)) { - request_info->content_type = *val; + if (NULL != (val = zend_hash_str_find_ptr(&client->request.headers, "content-type", sizeof("content-type")-1))) { + request_info->content_type = val; } } /* }}} */ @@ -1880,19 +1778,19 @@ static void destroy_request_info(sapi_request_info *request_info) /* {{{ */ { } /* }}} */ -static int php_cli_server_client_ctor(php_cli_server_client *client, php_cli_server *server, int client_sock, struct sockaddr *addr, socklen_t addr_len TSRMLS_DC) /* {{{ */ +static int php_cli_server_client_ctor(php_cli_server_client *client, php_cli_server *server, php_socket_t client_sock, struct sockaddr *addr, socklen_t addr_len) /* {{{ */ { client->server = server; client->sock = client_sock; client->addr = addr; client->addr_len = addr_len; { - char *addr_str = 0; - long addr_str_len = 0; - php_network_populate_name_from_sockaddr(addr, addr_len, &addr_str, &addr_str_len, NULL, 0 TSRMLS_CC); - client->addr_str = pestrndup(addr_str, addr_str_len, 1); - client->addr_str_len = addr_str_len; - efree(addr_str); + zend_string *addr_str = 0; + + php_network_populate_name_from_sockaddr(addr, addr_len, &addr_str, NULL, 0); + client->addr_str = pestrndup(ZSTR_VAL(addr_str), ZSTR_LEN(addr_str), 1); + client->addr_str_len = ZSTR_LEN(addr_str); + zend_string_release(addr_str); } php_http_parser_init(&client->parser, PHP_HTTP_REQUEST); client->request_read = 0; @@ -1922,18 +1820,17 @@ static void php_cli_server_client_dtor(php_cli_server_client *client) /* {{{ */ } } /* }}} */ -static void php_cli_server_close_connection(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */ +static void php_cli_server_close_connection(php_cli_server *server, php_cli_server_client *client) /* {{{ */ { #ifdef DEBUG - php_cli_server_logf("%s Closing" TSRMLS_CC, client->addr_str); + php_cli_server_logf("%s Closing", client->addr_str); #endif zend_hash_index_del(&server->clients, client->sock); } /* }}} */ -static int php_cli_server_send_error_page(php_cli_server *server, php_cli_server_client *client, int status TSRMLS_DC) /* {{{ */ +static int php_cli_server_send_error_page(php_cli_server *server, php_cli_server_client *client, int status) /* {{{ */ { - char *escaped_request_uri = NULL; - size_t escaped_request_uri_len; + zend_string *escaped_request_uri = NULL; const char *status_string = get_status_string(status); const char *content_template = get_template_string(status); char *errstr = get_last_error(); @@ -1942,7 +1839,7 @@ static int php_cli_server_send_error_page(php_cli_server *server, php_cli_server php_cli_server_content_sender_ctor(&client->content_sender); client->content_sender_initialized = 1; - escaped_request_uri = php_escape_html_entities_ex((unsigned char *)client->request.request_uri, client->request.request_uri_len, &escaped_request_uri_len, 0, ENT_QUOTES, NULL, 0 TSRMLS_CC); + escaped_request_uri = php_escape_html_entities_ex((unsigned char *)client->request.request_uri, client->request.request_uri_len, 0, ENT_QUOTES, NULL, 0); { static const char prologue_template[] = "<!doctype html><html><head><title>%d %s</title>"; @@ -1950,7 +1847,7 @@ static int php_cli_server_send_error_page(php_cli_server *server, php_cli_server if (!chunk) { goto fail; } - snprintf(chunk->data.heap.p, chunk->data.heap.len, prologue_template, status, status_string, escaped_request_uri); + snprintf(chunk->data.heap.p, chunk->data.heap.len, prologue_template, status, status_string, ZSTR_VAL(escaped_request_uri)); chunk->data.heap.len = strlen(chunk->data.heap.p); php_cli_server_buffer_append(&client->content_sender.buffer, chunk); } @@ -1970,11 +1867,11 @@ static int php_cli_server_send_error_page(php_cli_server *server, php_cli_server php_cli_server_buffer_append(&client->content_sender.buffer, chunk); } { - php_cli_server_chunk *chunk = php_cli_server_chunk_heap_new_self_contained(strlen(content_template) + escaped_request_uri_len + 3 + strlen(status_string) + 1); + php_cli_server_chunk *chunk = php_cli_server_chunk_heap_new_self_contained(strlen(content_template) + ZSTR_LEN(escaped_request_uri) + 3 + strlen(status_string) + 1); if (!chunk) { goto fail; } - snprintf(chunk->data.heap.p, chunk->data.heap.len, content_template, status_string, escaped_request_uri); + snprintf(chunk->data.heap.p, chunk->data.heap.len, content_template, status_string, ZSTR_VAL(escaped_request_uri)); chunk->data.heap.len = strlen(chunk->data.heap.p); php_cli_server_buffer_append(&client->content_sender.buffer, chunk); } @@ -1991,46 +1888,46 @@ static int php_cli_server_send_error_page(php_cli_server *server, php_cli_server php_cli_server_chunk *chunk; smart_str buffer = { 0 }; append_http_status_line(&buffer, client->request.protocol_version, status, 1); - if (!buffer.c) { + if (!buffer.s) { /* out of memory */ goto fail; } append_essential_headers(&buffer, client, 1); smart_str_appends_ex(&buffer, "Content-Type: text/html; charset=UTF-8\r\n", 1); smart_str_appends_ex(&buffer, "Content-Length: ", 1); - smart_str_append_generic_ex(&buffer, php_cli_server_buffer_size(&client->content_sender.buffer), 1, size_t, _unsigned); + smart_str_append_unsigned_ex(&buffer, php_cli_server_buffer_size(&client->content_sender.buffer), 1); smart_str_appendl_ex(&buffer, "\r\n", 2, 1); smart_str_appendl_ex(&buffer, "\r\n", 2, 1); - chunk = php_cli_server_chunk_heap_new(buffer.c, buffer.c, buffer.len); + chunk = php_cli_server_chunk_heap_new(buffer.s, ZSTR_VAL(buffer.s), ZSTR_LEN(buffer.s)); if (!chunk) { - smart_str_free_ex(&buffer, 1); + smart_str_free(&buffer); goto fail; } php_cli_server_buffer_prepend(&client->content_sender.buffer, chunk); } - php_cli_server_log_response(client, status, errstr ? errstr : "?" TSRMLS_CC); + php_cli_server_log_response(client, status, errstr ? errstr : "?"); php_cli_server_poller_add(&server->poller, POLLOUT, client->sock); if (errstr) { pefree(errstr, 1); } - efree(escaped_request_uri); + zend_string_free(escaped_request_uri); return SUCCESS; fail: if (errstr) { pefree(errstr, 1); } - efree(escaped_request_uri); + zend_string_free(escaped_request_uri); return FAILURE; } /* }}} */ -static int php_cli_server_dispatch_script(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */ +static int php_cli_server_dispatch_script(php_cli_server *server, php_cli_server_client *client) /* {{{ */ { if (strlen(client->request.path_translated) != client->request.path_translated_len) { /* can't handle paths that contain nul bytes */ - return php_cli_server_send_error_page(server, client, 400 TSRMLS_CC); + return php_cli_server_send_error_page(server, client, 400); } { zend_file_handle zfd; @@ -2040,22 +1937,22 @@ static int php_cli_server_dispatch_script(php_cli_server *server, php_cli_server zfd.free_filename = 0; zfd.opened_path = NULL; zend_try { - php_execute_script(&zfd TSRMLS_CC); + php_execute_script(&zfd); } zend_end_try(); } - php_cli_server_log_response(client, SG(sapi_headers).http_response_code, NULL TSRMLS_CC); + php_cli_server_log_response(client, SG(sapi_headers).http_response_code, NULL); return SUCCESS; } /* }}} */ -static int php_cli_server_begin_send_static(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */ +static int php_cli_server_begin_send_static(php_cli_server *server, php_cli_server_client *client) /* {{{ */ { int fd; int status = 200; if (client->request.path_translated && strlen(client->request.path_translated) != client->request.path_translated_len) { /* can't handle paths that contain nul bytes */ - return php_cli_server_send_error_page(server, client, 400 TSRMLS_CC); + return php_cli_server_send_error_page(server, client, 400); } #ifdef PHP_WIN32 @@ -2073,7 +1970,7 @@ static int php_cli_server_begin_send_static(php_cli_server *server, php_cli_serv fd = client->request.path_translated ? open(client->request.path_translated, O_RDONLY): -1; if (fd < 0) { - return php_cli_server_send_error_page(server, client, 404 TSRMLS_CC); + return php_cli_server_send_error_page(server, client, 404); } php_cli_server_content_sender_ctor(&client->content_sender); @@ -2083,15 +1980,15 @@ static int php_cli_server_begin_send_static(php_cli_server *server, php_cli_serv { php_cli_server_chunk *chunk; smart_str buffer = { 0 }; - const char *mime_type = get_mime_type(client->request.ext, client->request.ext_len); + const char *mime_type = get_mime_type(server, client->request.ext, client->request.ext_len); if (!mime_type) { mime_type = "application/octet-stream"; } append_http_status_line(&buffer, client->request.protocol_version, status, 1); - if (!buffer.c) { + if (!buffer.s) { /* out of memory */ - php_cli_server_log_response(client, 500, NULL TSRMLS_CC); + php_cli_server_log_response(client, 500, NULL); return FAILURE; } append_essential_headers(&buffer, client, 1); @@ -2102,31 +1999,31 @@ static int php_cli_server_begin_send_static(php_cli_server *server, php_cli_serv } smart_str_appendl_ex(&buffer, "\r\n", 2, 1); smart_str_appends_ex(&buffer, "Content-Length: ", 1); - smart_str_append_generic_ex(&buffer, client->request.sb.st_size, 1, size_t, _unsigned); + smart_str_append_unsigned_ex(&buffer, client->request.sb.st_size, 1); smart_str_appendl_ex(&buffer, "\r\n", 2, 1); smart_str_appendl_ex(&buffer, "\r\n", 2, 1); - chunk = php_cli_server_chunk_heap_new(buffer.c, buffer.c, buffer.len); + chunk = php_cli_server_chunk_heap_new(buffer.s, ZSTR_VAL(buffer.s), ZSTR_LEN(buffer.s)); if (!chunk) { - smart_str_free_ex(&buffer, 1); - php_cli_server_log_response(client, 500, NULL TSRMLS_CC); + smart_str_free(&buffer); + php_cli_server_log_response(client, 500, NULL); return FAILURE; } php_cli_server_buffer_append(&client->content_sender.buffer, chunk); } - php_cli_server_log_response(client, 200, NULL TSRMLS_CC); + php_cli_server_log_response(client, 200, NULL); php_cli_server_poller_add(&server->poller, POLLOUT, client->sock); return SUCCESS; } /* }}} */ -static int php_cli_server_request_startup(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) { /* {{{ */ - char **auth; +static int php_cli_server_request_startup(php_cli_server *server, php_cli_server_client *client) { /* {{{ */ + char *auth; php_cli_server_client_populate_request_info(client, &SG(request_info)); - if (SUCCESS == zend_hash_find(&client->request.headers, "authorization", sizeof("authorization"), (void**)&auth)) { - php_handle_auth_data(*auth TSRMLS_CC); + if (NULL != (auth = zend_hash_str_find_ptr(&client->request.headers, "authorization", sizeof("authorization")-1))) { + php_handle_auth_data(auth); } SG(sapi_headers).http_response_code = 200; - if (FAILURE == php_request_startup(TSRMLS_C)) { + if (FAILURE == php_request_startup()) { /* should never be happen */ destroy_request_info(&SG(request_info)); return FAILURE; @@ -2137,9 +2034,9 @@ static int php_cli_server_request_startup(php_cli_server *server, php_cli_server } /* }}} */ -static int php_cli_server_request_shutdown(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) { /* {{{ */ +static int php_cli_server_request_shutdown(php_cli_server *server, php_cli_server_client *client) { /* {{{ */ php_request_shutdown(0); - php_cli_server_close_connection(server, client TSRMLS_CC); + php_cli_server_close_connection(server, client); destroy_request_info(&SG(request_info)); SG(server_context) = NULL; SG(rfc1867_uploaded_files) = NULL; @@ -2147,7 +2044,7 @@ static int php_cli_server_request_shutdown(php_cli_server *server, php_cli_serve } /* }}} */ -static int php_cli_server_dispatch_router(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */ +static int php_cli_server_dispatch_router(php_cli_server *server, php_cli_server_client *client) /* {{{ */ { int decline = 0; zend_file_handle zfd; @@ -2165,10 +2062,12 @@ static int php_cli_server_dispatch_router(php_cli_server *server, php_cli_server zfd.opened_path = NULL; zend_try { - zval *retval = NULL; - if (SUCCESS == zend_execute_scripts(ZEND_REQUIRE TSRMLS_CC, &retval, 1, &zfd)) { - if (retval) { - decline = Z_TYPE_P(retval) == IS_BOOL && !Z_LVAL_P(retval); + zval retval; + + ZVAL_UNDEF(&retval); + if (SUCCESS == zend_execute_scripts(ZEND_REQUIRE, &retval, 1, &zfd)) { + if (Z_TYPE(retval) != IS_UNDEF) { + decline = Z_TYPE(retval) == IS_FALSE; zval_ptr_dtor(&retval); } } else { @@ -2186,7 +2085,7 @@ static int php_cli_server_dispatch_router(php_cli_server *server, php_cli_server } /* }}} */ -static int php_cli_server_dispatch(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */ +static int php_cli_server_dispatch(php_cli_server *server, php_cli_server_client *client) /* {{{ */ { int is_static_file = 0; @@ -2196,33 +2095,33 @@ static int php_cli_server_dispatch(php_cli_server *server, php_cli_server_client } if (server->router || !is_static_file) { - if (FAILURE == php_cli_server_request_startup(server, client TSRMLS_CC)) { + if (FAILURE == php_cli_server_request_startup(server, client)) { SG(server_context) = NULL; - php_cli_server_close_connection(server, client TSRMLS_CC); + php_cli_server_close_connection(server, client); destroy_request_info(&SG(request_info)); return SUCCESS; } } if (server->router) { - if (!php_cli_server_dispatch_router(server, client TSRMLS_CC)) { - php_cli_server_request_shutdown(server, client TSRMLS_CC); + if (!php_cli_server_dispatch_router(server, client)) { + php_cli_server_request_shutdown(server, client); return SUCCESS; } } if (!is_static_file) { - if (SUCCESS == php_cli_server_dispatch_script(server, client TSRMLS_CC) - || SUCCESS != php_cli_server_send_error_page(server, client, 500 TSRMLS_CC)) { + if (SUCCESS == php_cli_server_dispatch_script(server, client) + || SUCCESS != php_cli_server_send_error_page(server, client, 500)) { if (SG(sapi_headers).http_response_code == 304) { SG(sapi_headers).send_default_content_type = 0; } - php_cli_server_request_shutdown(server, client TSRMLS_CC); + php_cli_server_request_shutdown(server, client); return SUCCESS; } } else { if (server->router) { - static int (*send_header_func)(sapi_headers_struct * TSRMLS_DC); + static int (*send_header_func)(sapi_headers_struct *); send_header_func = sapi_module.send_headers; /* do not generate default content type header */ SG(sapi_headers).send_default_content_type = 0; @@ -2233,8 +2132,8 @@ static int php_cli_server_dispatch(php_cli_server *server, php_cli_server_client SG(sapi_headers).send_default_content_type = 1; SG(rfc1867_uploaded_files) = NULL; } - if (SUCCESS != php_cli_server_begin_send_static(server, client TSRMLS_CC)) { - php_cli_server_close_connection(server, client TSRMLS_CC); + if (SUCCESS != php_cli_server_begin_send_static(server, client)) { + php_cli_server_close_connection(server, client); } SG(server_context) = NULL; return SUCCESS; @@ -2246,10 +2145,29 @@ static int php_cli_server_dispatch(php_cli_server *server, php_cli_server_client } /* }}} */ -static void php_cli_server_dtor(php_cli_server *server TSRMLS_DC) /* {{{ */ +static int php_cli_server_mime_type_ctor(php_cli_server *server, const php_cli_server_ext_mime_type_pair *mime_type_map) /* {{{ */ +{ + const php_cli_server_ext_mime_type_pair *pair; + + zend_hash_init(&server->extension_mime_types, 0, NULL, NULL, 1); + + for (pair = mime_type_map; pair->ext; pair++) { + size_t ext_len = 0, mime_type_len = 0; + + ext_len = strlen(pair->ext); + mime_type_len = strlen(pair->mime_type); + + zend_hash_str_add_mem(&server->extension_mime_types, pair->ext, ext_len, (void*)pair->mime_type, mime_type_len + 1); + } + + return SUCCESS; +} /* }}} */ + +static void php_cli_server_dtor(php_cli_server *server) /* {{{ */ { zend_hash_destroy(&server->clients); - if (server->server_sock >= 0) { + zend_hash_destroy(&server->extension_mime_types); + if (ZEND_VALID_SOCKET(server->server_sock)) { closesocket(server->server_sock); } if (server->host) { @@ -2263,19 +2181,21 @@ static void php_cli_server_dtor(php_cli_server *server TSRMLS_DC) /* {{{ */ } } /* }}} */ -static void php_cli_server_client_dtor_wrapper(php_cli_server_client **p) /* {{{ */ +static void php_cli_server_client_dtor_wrapper(zval *zv) /* {{{ */ { - closesocket((*p)->sock); - php_cli_server_poller_remove(&(*p)->server->poller, POLLIN | POLLOUT, (*p)->sock); - php_cli_server_client_dtor(*p); - pefree(*p, 1); + php_cli_server_client *p = Z_PTR_P(zv); + + closesocket(p->sock); + php_cli_server_poller_remove(&p->server->poller, POLLIN | POLLOUT, p->sock); + php_cli_server_client_dtor(p); + pefree(p, 1); } /* }}} */ -static int php_cli_server_ctor(php_cli_server *server, const char *addr, const char *document_root, const char *router TSRMLS_DC) /* {{{ */ +static int php_cli_server_ctor(php_cli_server *server, const char *addr, const char *document_root, const char *router) /* {{{ */ { int retval = SUCCESS; char *host = NULL; - char *errstr = NULL; + zend_string *errstr = NULL; char *_document_root = NULL; char *_router = NULL; int err = 0; @@ -2320,10 +2240,12 @@ static int php_cli_server_ctor(php_cli_server *server, const char *addr, const c goto out; } - server_sock = php_network_listen_socket(host, &port, SOCK_STREAM, &server->address_family, &server->socklen, &errstr TSRMLS_CC); + server_sock = php_network_listen_socket(host, &port, SOCK_STREAM, &server->address_family, &server->socklen, &errstr); if (server_sock == SOCK_ERR) { - php_cli_server_logf("Failed to listen on %s:%d (reason: %s)" TSRMLS_CC, host, port, errstr ? errstr: "?"); - efree(errstr); + php_cli_server_logf("Failed to listen on %s:%d (reason: %s)", host, port, errstr ? ZSTR_VAL(errstr) : "?"); + if (errstr) { + zend_string_release(errstr); + } retval = FAILURE; goto out; } @@ -2339,7 +2261,7 @@ static int php_cli_server_ctor(php_cli_server *server, const char *addr, const c server->host = host; server->port = port; - zend_hash_init(&server->clients, 0, NULL, (void(*)(void*))php_cli_server_client_dtor_wrapper, 1); + zend_hash_init(&server->clients, 0, NULL, php_cli_server_client_dtor_wrapper, 1); { size_t document_root_len = strlen(document_root); @@ -2366,6 +2288,11 @@ static int php_cli_server_ctor(php_cli_server *server, const char *addr, const c server->router_len = 0; } + if (php_cli_server_mime_type_ctor(server, mime_type_map) == FAILURE) { + retval = FAILURE; + goto out; + } + server->is_running = 1; out: if (retval != SUCCESS) { @@ -2385,20 +2312,20 @@ out: return retval; } /* }}} */ -static int php_cli_server_recv_event_read_request(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */ +static int php_cli_server_recv_event_read_request(php_cli_server *server, php_cli_server_client *client) /* {{{ */ { char *errstr = NULL; - int status = php_cli_server_client_read_request(client, &errstr TSRMLS_CC); + int status = php_cli_server_client_read_request(client, &errstr); if (status < 0) { - php_cli_server_logf("%s Invalid request (%s)" TSRMLS_CC, client->addr_str, errstr); + php_cli_server_logf("%s Invalid request (%s)", client->addr_str, errstr); efree(errstr); - php_cli_server_close_connection(server, client TSRMLS_CC); + php_cli_server_close_connection(server, client); return FAILURE; } else if (status == 1 && client->request.request_method == PHP_HTTP_NOT_IMPLEMENTED) { - return php_cli_server_send_error_page(server, client, 501 TSRMLS_CC); + return php_cli_server_send_error_page(server, client, 501); } else if (status == 1) { php_cli_server_poller_remove(&server->poller, POLLIN, client->sock); - php_cli_server_dispatch(server, client TSRMLS_CC); + php_cli_server_dispatch(server, client); } else { php_cli_server_poller_add(&server->poller, POLLIN, client->sock); } @@ -2406,13 +2333,13 @@ static int php_cli_server_recv_event_read_request(php_cli_server *server, php_cl return SUCCESS; } /* }}} */ -static int php_cli_server_send_event(php_cli_server *server, php_cli_server_client *client TSRMLS_DC) /* {{{ */ +static int php_cli_server_send_event(php_cli_server *server, php_cli_server_client *client) /* {{{ */ { if (client->content_sender_initialized) { if (client->file_fd >= 0 && !client->content_sender.buffer.first) { size_t nbytes_read; if (php_cli_server_content_sender_pull(&client->content_sender, client->file_fd, &nbytes_read)) { - php_cli_server_close_connection(server, client TSRMLS_CC); + php_cli_server_close_connection(server, client); return FAILURE; } if (nbytes_read == 0) { @@ -2424,12 +2351,12 @@ static int php_cli_server_send_event(php_cli_server *server, php_cli_server_clie size_t nbytes_sent; int err = php_cli_server_content_sender_send(&client->content_sender, client->sock, &nbytes_sent); if (err && err != SOCK_EAGAIN) { - php_cli_server_close_connection(server, client TSRMLS_CC); + php_cli_server_close_connection(server, client); return FAILURE; } } if (!client->content_sender.buffer.first && client->file_fd < 0) { - php_cli_server_close_connection(server, client TSRMLS_CC); + php_cli_server_close_connection(server, client); } } return SUCCESS; @@ -2437,20 +2364,14 @@ static int php_cli_server_send_event(php_cli_server *server, php_cli_server_clie /* }}} */ typedef struct php_cli_server_do_event_for_each_fd_callback_params { -#ifdef ZTS - void ***tsrm_ls; -#endif php_cli_server *server; - int(*rhandler)(php_cli_server*, php_cli_server_client* TSRMLS_DC); - int(*whandler)(php_cli_server*, php_cli_server_client* TSRMLS_DC); + int(*rhandler)(php_cli_server*, php_cli_server_client*); + int(*whandler)(php_cli_server*, php_cli_server_client*); } php_cli_server_do_event_for_each_fd_callback_params; -static int php_cli_server_do_event_for_each_fd_callback(void *_params, int fd, int event) /* {{{ */ +static int php_cli_server_do_event_for_each_fd_callback(void *_params, php_socket_t fd, int event) /* {{{ */ { php_cli_server_do_event_for_each_fd_callback_params *params = _params; -#ifdef ZTS - void ***tsrm_ls = params->tsrm_ls; -#endif php_cli_server *server = params->server; if (server->server_sock == fd) { php_cli_server_client *client = NULL; @@ -2461,50 +2382,47 @@ static int php_cli_server_do_event_for_each_fd_callback(void *_params, int fd, i return FAILURE; } client_sock = accept(server->server_sock, sa, &socklen); - if (client_sock < 0) { + if (!ZEND_VALID_SOCKET(client_sock)) { char *errstr; errstr = php_socket_strerror(php_socket_errno(), NULL, 0); - php_cli_server_logf("Failed to accept a client (reason: %s)" TSRMLS_CC, errstr); + php_cli_server_logf("Failed to accept a client (reason: %s)", errstr); efree(errstr); pefree(sa, 1); return SUCCESS; } - if (SUCCESS != php_set_sock_blocking(client_sock, 0 TSRMLS_CC)) { + if (SUCCESS != php_set_sock_blocking(client_sock, 0)) { pefree(sa, 1); closesocket(client_sock); return SUCCESS; } - if (!(client = pemalloc(sizeof(php_cli_server_client), 1)) || FAILURE == php_cli_server_client_ctor(client, server, client_sock, sa, socklen TSRMLS_CC)) { - php_cli_server_logf("Failed to create a new request object" TSRMLS_CC); + if (!(client = pemalloc(sizeof(php_cli_server_client), 1)) || FAILURE == php_cli_server_client_ctor(client, server, client_sock, sa, socklen)) { + php_cli_server_logf("Failed to create a new request object"); pefree(sa, 1); closesocket(client_sock); return SUCCESS; } #ifdef DEBUG - php_cli_server_logf("%s Accepted" TSRMLS_CC, client->addr_str); + php_cli_server_logf("%s Accepted", client->addr_str); #endif - zend_hash_index_update(&server->clients, client_sock, &client, sizeof(client), NULL); - php_cli_server_recv_event_read_request(server, client TSRMLS_CC); + zend_hash_index_update_ptr(&server->clients, client_sock, client); + php_cli_server_recv_event_read_request(server, client); } else { - php_cli_server_client **client; - if (SUCCESS == zend_hash_index_find(&server->clients, fd, (void **)&client)) { + php_cli_server_client *client; + if (NULL != (client = zend_hash_index_find_ptr(&server->clients, fd))) { if (event & POLLIN) { - params->rhandler(server, *client TSRMLS_CC); + params->rhandler(server, client); } if (event & POLLOUT) { - params->whandler(server, *client TSRMLS_CC); + params->whandler(server, client); } } } return SUCCESS; } /* }}} */ -static void php_cli_server_do_event_for_each_fd(php_cli_server *server, int(*rhandler)(php_cli_server*, php_cli_server_client* TSRMLS_DC), int(*whandler)(php_cli_server*, php_cli_server_client* TSRMLS_DC) TSRMLS_DC) /* {{{ */ +static void php_cli_server_do_event_for_each_fd(php_cli_server *server, int(*rhandler)(php_cli_server*, php_cli_server_client*), int(*whandler)(php_cli_server*, php_cli_server_client*)) /* {{{ */ { php_cli_server_do_event_for_each_fd_callback_params params = { -#ifdef ZTS - tsrm_ls, -#endif server, rhandler, whandler @@ -2513,7 +2431,7 @@ static void php_cli_server_do_event_for_each_fd(php_cli_server *server, int(*rha php_cli_server_poller_iter_on_active(&server->poller, ¶ms, php_cli_server_do_event_for_each_fd_callback); } /* }}} */ -static int php_cli_server_do_event_loop(php_cli_server *server TSRMLS_DC) /* {{{ */ +static int php_cli_server_do_event_loop(php_cli_server *server) /* {{{ */ { int retval = SUCCESS; while (server->is_running) { @@ -2522,14 +2440,14 @@ static int php_cli_server_do_event_loop(php_cli_server *server TSRMLS_DC) /* {{{ if (n > 0) { php_cli_server_do_event_for_each_fd(server, php_cli_server_recv_event_read_request, - php_cli_server_send_event TSRMLS_CC); + php_cli_server_send_event); } else if (n == 0) { /* do nothing */ } else { int err = php_socket_errno(); if (err != SOCK_EINTR) { char *errstr = php_socket_strerror(err, NULL, 0); - php_cli_server_logf("%s" TSRMLS_CC, errstr); + php_cli_server_logf("%s", errstr); efree(errstr); retval = FAILURE; goto out; @@ -2548,7 +2466,7 @@ static void php_cli_server_sigint_handler(int sig) /* {{{ */ } /* }}} */ -int do_cli_server(int argc, char **argv TSRMLS_DC) /* {{{ */ +int do_cli_server(int argc, char **argv) /* {{{ */ { char *php_optarg = NULL; int php_optind = 1; @@ -2571,9 +2489,9 @@ int do_cli_server(int argc, char **argv TSRMLS_DC) /* {{{ */ } if (document_root) { - struct stat sb; + zend_stat_t sb; - if (stat(document_root, &sb)) { + if (zend_stat(document_root, &sb)) { fprintf(stderr, "Directory %s does not exist.\n", document_root); return 1; } @@ -2599,7 +2517,7 @@ int do_cli_server(int argc, char **argv TSRMLS_DC) /* {{{ */ router = argv[php_optind]; } - if (FAILURE == php_cli_server_ctor(&server, server_bind_address, document_root, router TSRMLS_CC)) { + if (FAILURE == php_cli_server_ctor(&server, server_bind_address, document_root, router)) { return 1; } sapi_module.phpinfo_as_text = 0; @@ -2621,8 +2539,8 @@ int do_cli_server(int argc, char **argv TSRMLS_DC) /* {{{ */ #if defined(HAVE_SIGNAL_H) && defined(SIGINT) signal(SIGINT, php_cli_server_sigint_handler); #endif - php_cli_server_do_event_loop(&server TSRMLS_CC); - php_cli_server_dtor(&server TSRMLS_CC); + php_cli_server_do_event_loop(&server); + php_cli_server_dtor(&server); return 0; } /* }}} */ diff --git a/sapi/cli/php_cli_server.h b/sapi/cli/php_cli_server.h index 45cfa52d46..cdf30bce2a 100644 --- a/sapi/cli/php_cli_server.h +++ b/sapi/cli/php_cli_server.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -25,14 +25,15 @@ extern const zend_function_entry server_additional_functions[]; extern sapi_module_struct cli_server_sapi_module; -extern int do_cli_server(int argc, char **argv TSRMLS_DC); +extern int do_cli_server(int argc, char **argv); ZEND_BEGIN_MODULE_GLOBALS(cli_server) short color; ZEND_END_MODULE_GLOBALS(cli_server) #ifdef ZTS -#define CLI_SERVER_G(v) TSRMG(cli_server_globals_id, zend_cli_server_globals *, v) +#define CLI_SERVER_G(v) ZEND_TSRMG(cli_server_globals_id, zend_cli_server_globals *, v) +ZEND_TSRMLS_CACHE_EXTERN() #else #define CLI_SERVER_G(v) (cli_server_globals.v) #endif diff --git a/sapi/cli/php_http_parser.c b/sapi/cli/php_http_parser.c index 71730322e0..5f8eb3ce0b 100644 --- a/sapi/cli/php_http_parser.c +++ b/sapi/cli/php_http_parser.c @@ -92,6 +92,7 @@ static const char *method_strings[] = , "MKCALENDAR" , "PROPFIND" , "PROPPATCH" + , "SEARCH" , "UNLOCK" , "REPORT" , "MKACTIVITY" @@ -326,7 +327,8 @@ size_t php_http_parser_execute (php_http_parser *parser, const char *data, size_t len) { - char c, ch; + char ch; + signed char c; const char *p = data, *pe; size_t to_read; @@ -589,7 +591,7 @@ size_t php_http_parser_execute (php_http_parser *parser, case 'O': parser->method = PHP_HTTP_OPTIONS; break; case 'P': parser->method = PHP_HTTP_POST; /* or PROPFIND or PROPPATCH or PUT */ break; case 'R': parser->method = PHP_HTTP_REPORT; break; - case 'S': parser->method = PHP_HTTP_SUBSCRIBE; break; + case 'S': parser->method = PHP_HTTP_SUBSCRIBE; /* or SEARCH */ break; case 'T': parser->method = PHP_HTTP_TRACE; break; case 'U': parser->method = PHP_HTTP_UNLOCK; /* or UNSUBSCRIBE */ break; default: parser->method = PHP_HTTP_NOT_IMPLEMENTED; break; @@ -597,7 +599,6 @@ size_t php_http_parser_execute (php_http_parser *parser, state = s_req_method; break; } - case s_req_method: { const char *matcher; @@ -640,6 +641,8 @@ size_t php_http_parser_execute (php_http_parser *parser, parser->method = PHP_HTTP_PUT; } else if (index == 1 && parser->method == PHP_HTTP_POST && ch == 'A') { parser->method = PHP_HTTP_PATCH; + } else if (index == 1 && parser->method == PHP_HTTP_SUBSCRIBE && ch == 'E') { + parser->method = PHP_HTTP_SEARCH; } else if (index == 2 && parser->method == PHP_HTTP_UNLOCK && ch == 'S') { parser->method = PHP_HTTP_UNSUBSCRIBE; } else if (index == 4 && parser->method == PHP_HTTP_PROPFIND && ch == 'P') { @@ -1441,7 +1444,9 @@ size_t php_http_parser_execute (php_http_parser *parser, } case s_body_identity: - to_read = MIN(pe - p, (size_t)parser->content_length); + assert(pe >= p); + + to_read = MIN((size_t)(pe - p), (size_t)parser->content_length); if (to_read > 0) { if (settings->on_body) settings->on_body(parser, p, to_read); p += to_read - 1; @@ -1525,8 +1530,9 @@ size_t php_http_parser_execute (php_http_parser *parser, case s_chunk_data: { assert(parser->flags & F_CHUNKED); + assert(pe >= p); - to_read = MIN(pe - p, (size_t)(parser->content_length)); + to_read = MIN((size_t)(pe - p), (size_t)(parser->content_length)); if (to_read > 0) { if (settings->on_body) settings->on_body(parser, p, to_read); diff --git a/sapi/cli/php_http_parser.h b/sapi/cli/php_http_parser.h index f2e1246ca8..fa4873abeb 100644 --- a/sapi/cli/php_http_parser.h +++ b/sapi/cli/php_http_parser.h @@ -91,6 +91,7 @@ enum php_http_method , PHP_HTTP_MKCALENDAR , PHP_HTTP_PROPFIND , PHP_HTTP_PROPPATCH + , PHP_HTTP_SEARCH , PHP_HTTP_UNLOCK /* subversion */ , PHP_HTTP_REPORT diff --git a/sapi/cli/ps_title.c b/sapi/cli/ps_title.c index 3db77f76dc..2d95e494aa 100644 --- a/sapi/cli/ps_title.c +++ b/sapi/cli/ps_title.c @@ -109,6 +109,8 @@ extern char** environ; static char windows_error_details[64]; static char ps_buffer[MAX_PATH]; static const size_t ps_buffer_size = MAX_PATH; +typedef BOOL (WINAPI *MySetConsoleTitle)(LPCTSTR); +typedef DWORD (WINAPI *MyGetConsoleTitle)(LPTSTR, DWORD); #elif defined(PS_USE_CLOBBER_ARGV) static char *ps_buffer; /* will point to argv area */ static size_t ps_buffer_size; /* space determined at run time */ @@ -125,11 +127,13 @@ static size_t ps_buffer_cur_len; /* actual string length in ps_buffer */ static int save_argc; static char** save_argv; -/* +/* * This holds the 'locally' allocated environ from the save_ps_args method. * This is subsequently free'd at exit. */ +#if defined(PS_USE_CLOBBER_ARGV) static char** frozen_environ, **new_environ; +#endif /* * Call this method early, before any code has used the original argv passed in @@ -311,7 +315,7 @@ const char* ps_title_errno(int rc) #ifdef PS_USE_WIN32 case PS_TITLE_WINDOWS_ERROR: - sprintf(windows_error_details, "Windows error code: %d", GetLastError()); + sprintf(windows_error_details, "Windows error code: %lu", GetLastError()); return windows_error_details; #endif } @@ -365,8 +369,22 @@ int set_ps_title(const char* title) #ifdef PS_USE_WIN32 { - if (!SetConsoleTitle(ps_buffer)) + MySetConsoleTitle set_title = NULL; + HMODULE hMod = LoadLibrary("kernel32.dll"); + + if (!hMod) { + return PS_TITLE_WINDOWS_ERROR; + } + + /* NOTE we don't use _UNICODE*/ + set_title = (MySetConsoleTitle)GetProcAddress(hMod, "SetConsoleTitleA"); + if (!set_title) { + return PS_TITLE_WINDOWS_ERROR; + } + + if (!set_title(ps_buffer)) { return PS_TITLE_WINDOWS_ERROR; + } } #endif /* PS_USE_WIN32 */ @@ -386,8 +404,24 @@ int get_ps_title(int *displen, const char** string) return rc; #ifdef PS_USE_WIN32 - if (!(ps_buffer_cur_len = GetConsoleTitle(ps_buffer, ps_buffer_size))) - return PS_TITLE_WINDOWS_ERROR; + { + MyGetConsoleTitle get_title = NULL; + HMODULE hMod = LoadLibrary("kernel32.dll"); + + if (!hMod) { + return PS_TITLE_WINDOWS_ERROR; + } + + /* NOTE we don't use _UNICODE*/ + get_title = (MyGetConsoleTitle)GetProcAddress(hMod, "GetConsoleTitleA"); + if (!get_title) { + return PS_TITLE_WINDOWS_ERROR; + } + + if (!(ps_buffer_cur_len = get_title(ps_buffer, (DWORD)ps_buffer_size))) { + return PS_TITLE_WINDOWS_ERROR; + } + } #endif *displen = (int)ps_buffer_cur_len; *string = ps_buffer; diff --git a/sapi/cli/ps_title.h b/sapi/cli/ps_title.h index d0bb2322c2..ee13cbe187 100644 --- a/sapi/cli/ps_title.h +++ b/sapi/cli/ps_title.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ diff --git a/sapi/cli/tests/005.phpt b/sapi/cli/tests/005.phpt index dff654a963..5a1e8b8fb1 100644 --- a/sapi/cli/tests/005.phpt +++ b/sapi/cli/tests/005.phpt @@ -40,7 +40,7 @@ string(183) "Class [ <internal:Core> class stdClass ] { } " -string(1418) "Class [ <internal:Core> class Exception ] { +string(1607) "Class [ <internal:Core> class Exception implements Throwable ] { - Constants [0] { } @@ -77,28 +77,28 @@ string(1418) "Class [ <internal:Core> class Exception ] { Method [ <internal:Core> public method __wakeup ] { } - Method [ <internal:Core> final public method getMessage ] { + Method [ <internal:Core, prototype Throwable> final public method getMessage ] { } - Method [ <internal:Core> final public method getCode ] { + Method [ <internal:Core, prototype Throwable> final public method getCode ] { } - Method [ <internal:Core> final public method getFile ] { + Method [ <internal:Core, prototype Throwable> final public method getFile ] { } - Method [ <internal:Core> final public method getLine ] { + Method [ <internal:Core, prototype Throwable> final public method getLine ] { } - Method [ <internal:Core> final public method getTrace ] { + Method [ <internal:Core, prototype Throwable> final public method getTrace ] { } - Method [ <internal:Core> final public method getPrevious ] { + Method [ <internal:Core, prototype Throwable> final public method getPrevious ] { } - Method [ <internal:Core> final public method getTraceAsString ] { + Method [ <internal:Core, prototype Throwable> final public method getTraceAsString ] { } - Method [ <internal:Core> public method __toString ] { + Method [ <internal:Core, prototype Throwable> public method __toString ] { } } } diff --git a/sapi/cli/tests/006.phpt b/sapi/cli/tests/006.phpt index 3d5c916e9c..b24da56660 100644 --- a/sapi/cli/tests/006.phpt +++ b/sapi/cli/tests/006.phpt @@ -25,7 +25,7 @@ string(44) "Exception: Extension unknown does not exist " string(37) "Exception: Extension does not exist " -string(%d) "Extension [ <persistent> extension #%d pcre version <no_version> ] { +string(%d) "Extension [ <persistent> extension #%d pcre version %s ] { - INI { Entry [ pcre.backtrack_limit <ALL> ] @@ -34,9 +34,12 @@ string(%d) "Extension [ <persistent> extension #%d pcre version <no_version> ] { Entry [ pcre.recursion_limit <ALL> ] Current = '%d' } + Entry [ pcre.jit <ALL> ] + Current = '%d' + } } - - Constants [14] { + - Constants [15] { Constant [ integer PREG_PATTERN_ORDER ] { 1 } Constant [ integer PREG_SET_ORDER ] { 2 } Constant [ integer PREG_OFFSET_CAPTURE ] { 256 } @@ -50,6 +53,7 @@ string(%d) "Extension [ <persistent> extension #%d pcre version <no_version> ] { Constant [ integer PREG_RECURSION_LIMIT_ERROR ] { 3 } Constant [ integer PREG_BAD_UTF8_ERROR ] { 4 } Constant [ integer PREG_BAD_UTF8_OFFSET_ERROR ] { 5 } + Constant [ integer PREG_JIT_STACKLIMIT_ERROR ] { 6 } Constant [ string PCRE_VERSION ] { %s } } @@ -94,6 +98,15 @@ string(%d) "Extension [ <persistent> extension #%d pcre version <no_version> ] { Parameter #4 [ <optional> &$count ] } } + Function [ <internal:pcre> function preg_replace_callback_array ] { + + - Parameters [4] { + Parameter #0 [ <required> $pattern ] + Parameter #1 [ <required> $subject ] + Parameter #2 [ <optional> $limit ] + Parameter #3 [ <optional> &$count ] + } + } Function [ <internal:pcre> function preg_filter ] { - Parameters [5] { diff --git a/sapi/cli/tests/008.phpt b/sapi/cli/tests/008.phpt index e14338f5f5..0121d94a27 100644 --- a/sapi/cli/tests/008.phpt +++ b/sapi/cli/tests/008.phpt @@ -36,7 +36,10 @@ echo "Done\n"; --EXPECTF-- string(%d) " -Fatal error: Cannot access private property test::$pri in %s on line %d +Fatal error: Uncaught Error: Cannot access private property test::$pri in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d " string(33) "Could not open input file: wrong " diff --git a/sapi/cli/tests/bug43177.phpt b/sapi/cli/tests/bug43177.phpt index a97769cf8f..23af545908 100644 --- a/sapi/cli/tests/bug43177.phpt +++ b/sapi/cli/tests/bug43177.phpt @@ -11,7 +11,10 @@ php_cli_server_start(<<<'SCRIPT' ini_set('display_errors', 0); switch($_SERVER["REQUEST_URI"]) { case "/parse": - eval("this is a parse error"); + try { + eval("this is a parse error"); + } catch (ParseError $e) { + } echo "OK\n"; break; case "/fatal": diff --git a/sapi/cli/tests/bug61977.phpt b/sapi/cli/tests/bug61977.phpt index d897737c3c..218641a511 100644 --- a/sapi/cli/tests/bug61977.phpt +++ b/sapi/cli/tests/bug61977.phpt @@ -48,7 +48,7 @@ foo.html => Content-Type: text/html; charset=UTF-8 foo.htm => Content-Type: text/html; charset=UTF-8 foo.svg => Content-Type: image/svg+xml foo.css => Content-Type: text/css; charset=UTF-8 -foo.js => Content-Type: text/javascript; charset=UTF-8 +foo.js => Content-Type: application/javascript foo.png => Content-Type: image/png foo.webm => Content-Type: video/webm foo.ogv => Content-Type: video/ogg diff --git a/sapi/cli/tests/bug64529.phpt b/sapi/cli/tests/bug64529.phpt index 8452953baf..7331b8303e 100644 --- a/sapi/cli/tests/bug64529.phpt +++ b/sapi/cli/tests/bug64529.phpt @@ -5,6 +5,9 @@ Bug #64529 (Ran out of opcode space) if (substr(PHP_OS, 0, 3) == "WIN") { die("skip non windows test"); } +if (!extension_loaded("readline") || !readline_info("done")) { + die("skip readline support required"); +} exec('which expect', $output, $ret); if ($ret) { die("skip no expect installed"); diff --git a/sapi/cli/tests/bug70006.phpt b/sapi/cli/tests/bug70006.phpt new file mode 100644 index 0000000000..855c9e1f80 --- /dev/null +++ b/sapi/cli/tests/bug70006.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #70006 (cli - function with default arg = STDOUT crash output) +--SKIPIF-- +<?php +include "skipif.inc"; +?> +--FILE-- +<?php + +function foo1($stream = STDOUT) +{ + //do nothing +} +foo1(); +?> +okey +--EXPECT-- +okey diff --git a/sapi/cli/tests/bug71005.phpt b/sapi/cli/tests/bug71005.phpt new file mode 100644 index 0000000000..3a60dcf42f --- /dev/null +++ b/sapi/cli/tests/bug71005.phpt @@ -0,0 +1,46 @@ +--TEST-- +Bug #71005 (Segfault in php_cli_server_dispatch_router()) +--SKIPIF-- +<?php +include "skipif.inc"; +?> +--FILE-- +<?php + +$code = <<<'EOF' +set_exception_handler(function () { echo 'goodbye'; }); +throw new Exception; +EOF; + +include "php_cli_server.inc"; +php_cli_server_start($code); + +list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS); +$port = intval($port) ?: 80; + +$fp = fsockopen($host, $port, $errno, $errstr, 0.5); +if (!$fp) { + die("connect failed"); +} + +if(fwrite($fp, <<<HEADER +GET / HTTP/1.1 +Host: {$host} + + +HEADER +)) { + while (!feof($fp)) { + echo fgets($fp); + } +} + +?> +--EXPECTF-- +HTTP/1.1 200 OK +Host: %s +Connection: close +X-Powered-By: PHP/%s +Content-type: text/html; charset=UTF-8 + +goodbye diff --git a/sapi/cli/tests/bug71624.phpt b/sapi/cli/tests/bug71624.phpt new file mode 100644 index 0000000000..aa4c69da12 --- /dev/null +++ b/sapi/cli/tests/bug71624.phpt @@ -0,0 +1,43 @@ +--TEST-- +Bug #61977 Test that -R properly sets argi and argn +--SKIPIF-- +<?php +include "skipif.inc"; +?> +--FILE-- +<?php + +$php = getenv('TEST_PHP_EXECUTABLE'); + +$filename_txt = dirname(__FILE__) . DIRECTORY_SEPARATOR . "bug71624.test.txt"; + +$txt = 'foo +test +hello +'; + +file_put_contents($filename_txt, $txt); + +$test_args = ['$argi', '$argn']; +foreach ($test_args as $test_arg) { + if (substr(PHP_OS, 0, 3) == 'WIN') { + var_dump(`type "$filename_txt" | "$php" -n -R "echo $test_arg . PHP_EOL;"`); + } else { + var_dump(`cat "$filename_txt" | "$php" -n -R 'echo $test_arg . PHP_EOL;'`); + } +} + +@unlink($filename_txt); + +echo "Done\n"; +?> +--EXPECT-- +string(6) "1 +2 +3 +" +string(15) "foo +test +hello +" +Done diff --git a/sapi/cli/tests/php_cli_server_015.phpt b/sapi/cli/tests/php_cli_server_015.phpt index e3d8c4170d..af0a3f65a8 100644 --- a/sapi/cli/tests/php_cli_server_015.phpt +++ b/sapi/cli/tests/php_cli_server_015.phpt @@ -46,4 +46,8 @@ X-Powered-By: PHP/%s Content-type: text/html; charset=UTF-8 <br /> -<b>Fatal error</b>: Call to undefined function non_exists_function() in <b>%ssyntax_error.php</b> on line <b>%s</b><br /> +<b>Fatal error</b>: Uncaught Error: Call to undefined function non_exists_function() in %ssyntax_error.php:%d +Stack trace: +#0 %sindex.php(%d): require() +#1 {main} + thrown in <b>%ssyntax_error.php</b> on line <b>%d</b><br /> diff --git a/sapi/cli/tests/php_cli_server_020.phpt b/sapi/cli/tests/php_cli_server_020.phpt new file mode 100644 index 0000000000..4ed673d380 --- /dev/null +++ b/sapi/cli/tests/php_cli_server_020.phpt @@ -0,0 +1,40 @@ +--TEST-- +Use SEARCH as a HTTP verb +--SKIPIF-- +<?php +include "skipif.inc"; +?> +--FILE-- +<?php +include "php_cli_server.inc"; +php_cli_server_start('var_dump($_SERVER["REQUEST_METHOD"]);'); + +list($host, $port) = explode(':', PHP_CLI_SERVER_ADDRESS); +$port = intval($port) ?: 80; + +$fp = fsockopen($host, $port, $errno, $errstr, 0.5); +if (!$fp) { + die("connect failed"); +} + +if(fwrite($fp, <<<HEADER +SEARCH / HTTP/1.1 +Host: {$host} + + +HEADER +)) { + while (!feof($fp)) { + echo fgets($fp); + } +} + +?> +--EXPECTF-- +HTTP/1.1 200 OK +Host: %s +Connection: close +X-Powered-By: PHP/%s +Content-type: text/html; charset=UTF-8 + +string(6) "SEARCH" diff --git a/sapi/continuity/CREDITS b/sapi/continuity/CREDITS deleted file mode 100644 index 35335e9266..0000000000 --- a/sapi/continuity/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -Continuity -Alex Leigh (based on nsapi code) diff --git a/sapi/continuity/capi.c b/sapi/continuity/capi.c deleted file mode 100644 index 56ead37499..0000000000 --- a/sapi/continuity/capi.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 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: Alex Leigh <php (at) postfin (dot) com> | - +----------------------------------------------------------------------+ -*/ - -/* For more information on Continuity: http://www.ashpool.com/ */ - -/* - * This code is based on the PHP5 SAPI module for NSAPI by Jayakumar - * Muthukumarasamy - */ - -/* PHP includes */ -#define CONTINUITY 1 -#define CAPI_DEBUG - -/* Define for CDP specific extensions */ -#undef CONTINUITY_CDPEXT - -#include "php.h" -#include "php_variables.h" -#include "ext/standard/info.h" -#include "php_ini.h" -#include "php_globals.h" -#include "SAPI.h" -#include "php_main.h" -#include "php_version.h" -#include "TSRM.h" -#include "ext/standard/php_standard.h" - -/* - * CAPI includes - */ -#include <continuity.h> -#include <http.h> - -#define NSLS_D struct capi_request_context *request_context -#define NSLS_DC , NSLS_D -#define NSLS_C request_context -#define NSLS_CC , NSLS_C -#define NSG(v) (request_context->v) - -/* - * ZTS needs to be defined for CAPI to work - */ -#if !defined(ZTS) -#error "CAPI module needs ZTS to be defined" -#endif - -/* - * Structure to encapsulate the CAPI request in SAPI - */ -typedef struct capi_request_context { - httpTtrans *t; - int read_post_bytes; -} capi_request_context; - -/**************/ - -PHP_MINIT_FUNCTION(continuity); -PHP_MSHUTDOWN_FUNCTION(continuity); -PHP_RINIT_FUNCTION(continuity); -PHP_RSHUTDOWN_FUNCTION(continuity); -PHP_MINFO_FUNCTION(continuity); - -PHP_FUNCTION(continuity_virtual); -PHP_FUNCTION(continuity_request_headers); -PHP_FUNCTION(continuity_response_headers); - -const zend_function_entry continuity_functions[] = { - {NULL, NULL, NULL} -}; - -zend_module_entry continuity_module_entry = { - STANDARD_MODULE_HEADER, - "continuity", - continuity_functions, - PHP_MINIT(continuity), - PHP_MSHUTDOWN(continuity), - NULL, - NULL, - PHP_MINFO(continuity), - NO_VERSION_YET, - STANDARD_MODULE_PROPERTIES -}; - -PHP_MINIT_FUNCTION(continuity) -{ - return SUCCESS; -} - -PHP_MSHUTDOWN_FUNCTION(continuity) -{ - return SUCCESS; -} - -PHP_MINFO_FUNCTION(continuity) -{ - php_info_print_table_start(); - php_info_print_table_row(2, "Continuity Module Revision", "$Id$"); - php_info_print_table_row(2, "Server Version", conFget_build()); -#ifdef CONTINUITY_CDPEXT - php_info_print_table_row(2,"CDP Extensions", "enabled"); -#else - php_info_print_table_row(2,"CDP Extensions", "disabled"); -#endif - php_info_print_table_end(); - -/* DISPLAY_INI_ENTRIES(); */ -} - -/**************/ - -/* - * sapi_capi_ub_write: Write len bytes to the connection output. - */ -static int sapi_capi_ub_write(const char *str, unsigned int str_length TSRMLS_DC) -{ - int retval; - capi_request_context *rc; - - rc = (capi_request_context *) SG(server_context); - retval = httpFwrite(rc->t, (char *) str, str_length); - if (retval == -1 || retval == 0) - php_handle_aborted_connection(); - return retval; -} - -/* - * sapi_capi_header_handler: Add/update response headers with those provided - * by the PHP engine. - */ -static int sapi_capi_header_handler(sapi_header_struct * sapi_header, sapi_headers_struct * sapi_headers TSRMLS_DC) -{ - char *header_name, *header_content, *p; - capi_request_context *rc = (capi_request_context *) SG(server_context); - - lstFset_delete_key(rc->t->res_hdrs, "Content-Type"); - - header_name = sapi_header->header; - header_content = p = strchr(header_name, ':'); - if (p == NULL) { - return 0; - } - *p = 0; - do { - header_content++; - } while (*header_content == ' '); - - lstFset_add(rc->t->res_hdrs, header_name, header_content); - - *p = ':'; /* restore '*p' */ - - efree(sapi_header->header); - - return 0; /* don't use the default SAPI mechanism, CAPI - * duplicates this functionality */ -} - -/* - * sapi_capi_send_headers: Transmit the headers to the client. This has the - * effect of starting the response under Continuity. - */ -static int sapi_capi_send_headers(sapi_headers_struct * sapi_headers TSRMLS_DC) -{ - int retval; - capi_request_context *rc = (capi_request_context *) SG(server_context); - - /* - * We could probably just do this in the header_handler. But, I don't know - * what the implication of doing it there is. - */ - - if (SG(sapi_headers).send_default_content_type) { - /* lstFset_delete_key(rc->t->res_hdrs, "Content-Type"); */ - lstFset_update(rc->t->res_hdrs, "Content-Type", "text/html"); - } - httpFset_status(rc->t, SG(sapi_headers).http_response_code, NULL); - httpFstart_response(rc->t); - - return SAPI_HEADER_SENT_SUCCESSFULLY; - -} - -static int sapi_capi_read_post(char *buffer, uint count_bytes TSRMLS_DC) -{ - unsigned int max_read, total_read = 0; - capi_request_context *rc = (capi_request_context *) SG(server_context); - - if (rc->read_post_bytes == -1) { - max_read = MIN(count_bytes, SG(request_info).content_length); - } else { - if (rc->read_post_bytes == 0) - return 0; - max_read = MIN(count_bytes, (SG(request_info).content_length - rc->read_post_bytes)); - } - - total_read = httpFread(rc->t, buffer, max_read); - - if (total_read < 0) - total_read = -1; - else - rc->read_post_bytes = total_read; - - return total_read; -} - -/* - * sapi_capi_read_cookies: Return cookie information into PHP. - */ -static char *sapi_capi_read_cookies(TSRMLS_D) -{ - char *cookie_string; - capi_request_context *rc = (capi_request_context *) SG(server_context); - - cookie_string = lstFset_get(rc->t->req_hdrs, "cookie"); - return cookie_string; -} - -static void sapi_capi_register_server_variables(zval * track_vars_array TSRMLS_DC) -{ - capi_request_context *rc = (capi_request_context *) SG(server_context); - size_t i; - char *value; - char buf[128]; - - /* PHP_SELF and REQUEST_URI */ - value = lstFset_get(rc->t->vars, "uri"); - if (value != NULL) { - php_register_variable("PHP_SELF", value, track_vars_array TSRMLS_CC); - php_register_variable("REQUEST_URI", value, track_vars_array TSRMLS_CC); - } - - /* COUNTRY CODE */ - value = lstFset_get(rc->t->vars, "ccode"); - if(value!=NULL) - php_register_variable("COUNTRY_CODE", value, track_vars_array TSRMLS_CC); - - /* argv */ - value = lstFset_get(rc->t->vars, "query"); - if (value != NULL) - php_register_variable("argv", value, track_vars_array TSRMLS_CC); - - /* GATEWAY_INTERFACE */ - php_register_variable("GATEWAY_INTERFACE", "CGI/1.1", track_vars_array TSRMLS_CC); - - /* SERVER_NAME and HTTP_HOST */ - value = lstFset_get(rc->t->req_hdrs, "host"); - if (value != NULL) { - php_register_variable("HTTP_HOST", value, track_vars_array TSRMLS_CC); - /* TODO: This should probably scrub the port value if one is present. */ - php_register_variable("SERVER_NAME", value, track_vars_array TSRMLS_CC); - } - /* SERVER_SOFTWARE */ - value = lstFset_get(rc->t->res_hdrs, "Server"); - if (value != NULL) - php_register_variable("SERVER_SOFTWARE", value, track_vars_array TSRMLS_CC); - - /* SERVER_PROTOCOL */ - value = lstFset_get(rc->t->vars, "protocol"); - if (value != NULL) - php_register_variable("SERVER_PROTOCOL", value, track_vars_array TSRMLS_CC); - - /* REQUEST_METHOD */ - value = lstFset_get(rc->t->vars, "method"); - if (value != NULL) - php_register_variable("REQUEST_METHOD", value, track_vars_array TSRMLS_CC); - - /* QUERY_STRING */ - value = lstFset_get(rc->t->vars, "query"); - if (value != NULL) - php_register_variable("QUERY_STRING", value, track_vars_array TSRMLS_CC); - - /* DOCUMENT_ROOT */ - value = lstFset_get(rc->t->vars, "docroot"); - if (value != NULL) - php_register_variable("DOCUMENT_ROOT", value, track_vars_array TSRMLS_CC); - - /* HTTP_ACCEPT */ - value = lstFset_get(rc->t->req_hdrs, "accept"); - if (value != NULL) - php_register_variable("HTTP_ACCEPT", value, track_vars_array TSRMLS_CC); - - /* HTTP_ACCEPT_CHARSET */ - value = lstFset_get(rc->t->req_hdrs, "accept-charset"); - if (value != NULL) - php_register_variable("HTTP_ACCEPT_CHARSET", value, track_vars_array TSRMLS_CC); - - /* HTTP_ACCEPT_ENCODING */ - value = lstFset_get(rc->t->req_hdrs, "accept-encoding"); - if (value != NULL) - php_register_variable("HTTP_ACCEPT_ENCODING", value, track_vars_array TSRMLS_CC); - - /* HTTP_ACCEPT_LANGUAGE */ - value = lstFset_get(rc->t->req_hdrs, "accept-language"); - if (value != NULL) - php_register_variable("HTTP_ACCEPT_LANGUAGE", value, track_vars_array TSRMLS_CC); - - /* HTTP_CONNECTION */ - value = lstFset_get(rc->t->req_hdrs, "connection"); - if (value != NULL) - php_register_variable("HTTP_CONNECTION", value, track_vars_array TSRMLS_CC); - - /* HTTP_REFERER */ - value = lstFset_get(rc->t->req_hdrs, "referer"); - if (value != NULL) - php_register_variable("HTTP_REFERER", value, track_vars_array TSRMLS_CC); - - /* HTTP_USER_AGENT */ - value = lstFset_get(rc->t->req_hdrs, "user-agent"); - if (value != NULL) - php_register_variable("HTTP_USER_AGENT", value, track_vars_array TSRMLS_CC); - - /* REMOTE_ADDR */ - utlFip_to_str(rc->t->cli_ipv4_addr, buf, sizeof(buf)); - php_register_variable("REMOTE_ADDR", buf, track_vars_array TSRMLS_CC); - - /* REMOTE_PORT */ - - /* SCRIPT_FILENAME and PATH_TRANSLATED */ - value = lstFset_get(rc->t->vars, "path"); - if (value != NULL) { - php_register_variable("SCRIPT_FILENAME", value, track_vars_array TSRMLS_CC); - php_register_variable("PATH_TRANSLATED", value, track_vars_array TSRMLS_CC); - } - /* SERVER_ADMIN */ - /* Not applicable */ - - /* SERVER_PORT */ - -} - -static void capi_log_message(char *message TSRMLS_DC) -{ - capi_request_context *rc = (capi_request_context *) SG(server_context); - logFmsg(0, "mod/php: %s", message); -} - -static int php_capi_startup(sapi_module_struct *sapi_module); - -sapi_module_struct capi_sapi_module = { - "Continuity", /* name */ - "Continuity Server Enterprise Edition", /* pretty name */ - - php_capi_startup, /* startup */ - php_module_shutdown_wrapper, /* shutdown */ - - NULL, /* activate */ - NULL, /* deactivate */ - - sapi_capi_ub_write, /* unbuffered write */ - NULL, /* flush */ - NULL, /* get uid */ - NULL, /* getenv */ - - php_error, /* error handler */ - - sapi_capi_header_handler, /* header handler */ - sapi_capi_send_headers, /* send headers handler */ - NULL, /* send header handler */ - - sapi_capi_read_post, /* read POST data */ - sapi_capi_read_cookies, /* read Cookies */ - - sapi_capi_register_server_variables, /* register server variables */ - capi_log_message, /* Log message */ - NULL, /* Get request time */ - NULL, /* Child terminate */ - - NULL, /* Block interruptions */ - NULL, /* Unblock interruptions */ - - STANDARD_SAPI_MODULE_PROPERTIES -}; - -static int php_capi_startup(sapi_module_struct *sapi_module) { - if(php_module_startup(sapi_module,&continuity_module_entry,1)==FAILURE) { - return FAILURE; - } - return SUCCESS; -} - - -static char * - capi_strdup(char *str) -{ - if (str != NULL) - return strFcopy(str); - return NULL; -} - -static void capi_free(void *addr) -{ - if (addr != NULL) - free(addr); -} - -static void capi_request_ctor(NSLS_D TSRMLS_DC) -{ - char *query_string = lstFset_get(NSG(t->vars), "query"); - char *uri = lstFset_get(NSG(t->vars), "uri"); - char *path_info = lstFset_get(NSG(t->vars), "path-info"); - char *path_translated = lstFset_get(NSG(t->vars), "path"); - char *request_method = lstFset_get(NSG(t->vars), "method"); - char *content_type = lstFset_get(NSG(t->req_hdrs), "content-type"); - char *content_length = lstFset_get(NSG(t->req_hdrs), "content-length"); - - SG(request_info).query_string = capi_strdup(query_string); - SG(request_info).request_uri = capi_strdup(uri); - SG(request_info).request_method = capi_strdup(request_method); - SG(request_info).path_translated = capi_strdup(path_translated); - SG(request_info).content_type = capi_strdup(content_type); - SG(request_info).content_length = (content_length == NULL) ? 0 : strtoul(content_length, 0, 0); - SG(sapi_headers).http_response_code = 200; -} - -static void capi_request_dtor(NSLS_D TSRMLS_DC) -{ - capi_free(SG(request_info).query_string); - capi_free(SG(request_info).request_uri); - capi_free(SG(request_info).request_method); - capi_free(SG(request_info).path_translated); - capi_free(SG(request_info).content_type); -} - -int capi_module_main(NSLS_D TSRMLS_DC) -{ - zend_file_handle file_handle; - - if (php_request_startup(TSRMLS_C) == FAILURE) { - return FAILURE; - } - file_handle.type = ZEND_HANDLE_FILENAME; - file_handle.filename = SG(request_info).path_translated; - file_handle.free_filename = 0; - file_handle.opened_path = NULL; - - php_execute_script(&file_handle TSRMLS_CC); - php_request_shutdown(NULL); - - return SUCCESS; -} - -int phpFinit(lstTset * opt) -{ - php_core_globals *core_globals; - - tsrm_startup(128, 1, 0, NULL); - core_globals = ts_resource(core_globals_id); - - logFmsg(0, "mod/php: PHP Interface v3 (module)"); - logFmsg(0, "mod/php: Copyright (c) 1999-2016 The PHP Group. All rights reserved."); - - sapi_startup(&capi_sapi_module); - capi_sapi_module.startup(&capi_sapi_module); - - return STATUS_PROCEED; -} - -int phpFservice(httpTtrans * t, lstTset * opts) -{ - int retval; - capi_request_context *request_context; - - TSRMLS_FETCH(); - - request_context = (capi_request_context *) malloc(sizeof(capi_request_context)); - request_context->t = t; - request_context->read_post_bytes = -1; - - SG(server_context) = request_context; - - capi_request_ctor(NSLS_C TSRMLS_CC); - retval = capi_module_main(NSLS_C TSRMLS_CC); - capi_request_dtor(NSLS_C TSRMLS_CC); - - free(request_context); - - /* - * This call is ostensibly provided to free the memory from PHP/TSRM when - * the thread terminated, but, it leaks a structure in some hash list - * according to the developers. Not calling this will leak the entire - * interpreter, around 100k, but calling it and then terminating the - * thread will leak the struct (around a k). The only answer with the - * current TSRM implementation is to reuse the threads that allocate TSRM - * resources. - */ - /* ts_free_thread(); */ - - if (retval == SUCCESS) { - return STATUS_EXIT; - } else { - return STATUS_ERROR; - } -} diff --git a/sapi/continuity/config.m4 b/sapi/continuity/config.m4 deleted file mode 100644 index 8d2741921a..0000000000 --- a/sapi/continuity/config.m4 +++ /dev/null @@ -1,28 +0,0 @@ -dnl ## $Id$ -*- sh -*- - -PHP_ARG_WITH(continuity, for Continuity support, -[ --with-continuity=DIR Build PHP as Continuity Server module. - DIR is path to the installed Continuity Server root], no, no) - -if test "$PHP_CONTINUITY" != "no"; then - if test ! -d $PHP_CONTINUITY; then - AC_MSG_ERROR([Please specify the path to the root of your Continuity server using --with-continuity=DIR]) - fi - AC_MSG_CHECKING([for Continuity include files]) - if test -d $PHP_CONTINUITY/include ; then - CAPI_INCLUDE=$PHP_CONTINUITY/include - AC_MSG_RESULT([Continuity Binary Distribution]) - else - AC_MSG_ERROR([Cannot find your CAPI include files in either DIR/src or DIR/include]) - fi - - PHP_SELECT_SAPI(continuity, shared, capi.c) - PHP_ADD_INCLUDE($CAPI_INCLUDE) - PHP_BUILD_THREAD_SAFE - AC_DEFINE(HAVE_CONTINUITY, 1, [Whether you have a Continuity Server]) - INSTALL_IT="\$(INSTALL) -m 0755 $SAPI_SHARED \$(INSTALL_ROOT)$PHP_CONTINUITY/lib/" -fi - -dnl ## Local Variables: -dnl ## tab-width: 4 -dnl ## End: diff --git a/sapi/embed/config.m4 b/sapi/embed/config.m4 index 5ffb9b39bd..5be7af48f4 100644 --- a/sapi/embed/config.m4 +++ b/sapi/embed/config.m4 @@ -23,7 +23,7 @@ if test "$PHP_EMBED" != "no"; then ;; esac if test "$PHP_EMBED_TYPE" != "no"; then - PHP_SELECT_SAPI(embed, $PHP_EMBED_TYPE, php_embed.c) + PHP_SELECT_SAPI(embed, $PHP_EMBED_TYPE, php_embed.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) PHP_INSTALL_HEADERS([sapi/embed/php_embed.h]) fi AC_MSG_RESULT([$PHP_EMBED_TYPE]) diff --git a/sapi/embed/config.w32 b/sapi/embed/config.w32 index 64e44bdd94..ce41e253f0 100644 --- a/sapi/embed/config.w32 +++ b/sapi/embed/config.w32 @@ -6,6 +6,6 @@ ARG_ENABLE('embed', 'Embedded SAPI library', 'no'); var PHP_EMBED_PGO = false; if (PHP_EMBED != "no") { - SAPI('embed', 'php_embed.c', 'php' + PHP_VERSION + 'embed.lib'); + SAPI('embed', 'php_embed.c', 'php' + PHP_VERSION + 'embed.lib', '/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1'); PHP_INSTALL_HEADERS("sapi/embed", "php_embed.h"); } diff --git a/sapi/embed/php5embed.dsp b/sapi/embed/php5embed.dsp deleted file mode 100644 index 8564b11797..0000000000 --- a/sapi/embed/php5embed.dsp +++ /dev/null @@ -1,100 +0,0 @@ -# Microsoft Developer Studio Project File - Name="php5embed" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Static Library" 0x0104
-
-CFG=php5embed - 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 "php5embed.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 "php5embed.mak" CFG="php5embed - Win32 Debug_TS"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "php5embed - Win32 Debug_TS" (based on "Win32 (x86) Static Library")
-!MESSAGE "php5embed - Win32 Release_TS" (based on "Win32 (x86) Static Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "php5embed - 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 /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\TSRM" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D ZEND_DEBUG=1 /YX /FD /GZ /c
-# ADD BASE RSC /l 0x406 /d "_DEBUG"
-# ADD RSC /l 0x406 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo /out:"..\..\Debug_TS\php5embed.lib"
-
-!ELSEIF "$(CFG)" == "php5embed - 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 Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\TSRM" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D ZEND_DEBUG=0 /YX /FD /c
-# ADD BASE RSC /l 0x406 /d "NDEBUG"
-# ADD RSC /l 0x406 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo /out:"..\..\Release_TS\php5embed.lib"
-
-!ENDIF
-
-# Begin Target
-
-# Name "php5embed - Win32 Debug_TS"
-# Name "php5embed - Win32 Release_TS"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=php_embed.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# Begin Source File
-
-SOURCE=php_embed.h
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/sapi/embed/php_embed.c b/sapi/embed/php_embed.c index c6ff039060..18c2027271 100644 --- a/sapi/embed/php_embed.c +++ b/sapi/embed/php_embed.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -33,21 +33,25 @@ const char HARDCODED_INI[] = "max_execution_time=0\n" "max_input_time=-1\n\0"; -static char* php_embed_read_cookies(TSRMLS_D) +#if defined(PHP_WIN32) && defined(ZTS) +ZEND_TSRMLS_CACHE_DEFINE() +#endif + +static char* php_embed_read_cookies(void) { return NULL; } -static int php_embed_deactivate(TSRMLS_D) +static int php_embed_deactivate(void) { fflush(stdout); return SUCCESS; } -static inline size_t php_embed_single_write(const char *str, uint str_length) +static inline size_t php_embed_single_write(const char *str, size_t str_length) { #ifdef PHP_WRITE_STDOUT - long ret; + zend_long ret; ret = write(STDOUT_FILENO, str, str_length); if (ret <= 0) return 0; @@ -61,10 +65,10 @@ static inline size_t php_embed_single_write(const char *str, uint str_length) } -static int php_embed_ub_write(const char *str, uint str_length TSRMLS_DC) +static size_t php_embed_ub_write(const char *str, size_t str_length) { const char *ptr = str; - uint remaining = str_length; + size_t remaining = str_length; size_t ret; while (remaining > 0) { @@ -86,18 +90,18 @@ static void php_embed_flush(void *server_context) } } -static void php_embed_send_header(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC) +static void php_embed_send_header(sapi_header_struct *sapi_header, void *server_context) { } -static void php_embed_log_message(char *message TSRMLS_DC) +static void php_embed_log_message(char *message) { fprintf (stderr, "%s\n", message); } -static void php_embed_register_variables(zval *track_vars_array TSRMLS_DC) +static void php_embed_register_variables(zval *track_vars_array) { - php_import_environment_variables(track_vars_array TSRMLS_CC); + php_import_environment_variables(track_vars_array); } static int php_embed_startup(sapi_module_struct *sapi_module) @@ -108,35 +112,35 @@ static int php_embed_startup(sapi_module_struct *sapi_module) return SUCCESS; } -extern EMBED_SAPI_API sapi_module_struct php_embed_module = { +EMBED_SAPI_API sapi_module_struct php_embed_module = { "embed", /* name */ "PHP Embedded Library", /* pretty name */ - + php_embed_startup, /* startup */ php_module_shutdown_wrapper, /* shutdown */ - + NULL, /* activate */ php_embed_deactivate, /* deactivate */ - + php_embed_ub_write, /* unbuffered write */ php_embed_flush, /* flush */ NULL, /* get uid */ NULL, /* getenv */ - + php_error, /* error handler */ - + NULL, /* header handler */ NULL, /* send headers handler */ php_embed_send_header, /* send header handler */ - + NULL, /* read POST data */ php_embed_read_cookies, /* read Cookies */ - + php_embed_register_variables, /* register server variables */ php_embed_log_message, /* Log message */ NULL, /* Get request time */ NULL, /* Child terminate */ - + STANDARD_SAPI_MODULE_PROPERTIES }; /* }}} */ @@ -152,12 +156,9 @@ static const zend_function_entry additional_functions[] = { {NULL, NULL, NULL} }; -EMBED_SAPI_API int php_embed_init(int argc, char **argv PTSRMLS_DC) +EMBED_SAPI_API int php_embed_init(int argc, char **argv) { zend_llist global_vars; -#ifdef ZTS - void ***tsrm_ls = NULL; -#endif #ifdef HAVE_SIGNAL_H #if defined(SIGPIPE) && defined(SIG_IGN) @@ -172,8 +173,12 @@ EMBED_SAPI_API int php_embed_init(int argc, char **argv PTSRMLS_DC) #ifdef ZTS tsrm_startup(1, 1, 0, NULL); - tsrm_ls = ts_resource(0); - *ptsrm_ls = tsrm_ls; + (void)ts_resource(0); + ZEND_TSRMLS_CACHE_UPDATE(); +#endif + +#ifdef ZEND_SIGNALS + zend_signal_startup(); #endif sapi_startup(&php_embed_module); @@ -197,30 +202,30 @@ EMBED_SAPI_API int php_embed_init(int argc, char **argv PTSRMLS_DC) if (php_embed_module.startup(&php_embed_module)==FAILURE) { return FAILURE; } - - zend_llist_init(&global_vars, sizeof(char *), NULL, 0); + + zend_llist_init(&global_vars, sizeof(char *), NULL, 0); /* Set some Embedded PHP defaults */ SG(options) |= SAPI_OPTION_NO_CHDIR; SG(request_info).argc=argc; SG(request_info).argv=argv; - if (php_request_startup(TSRMLS_C)==FAILURE) { - php_module_shutdown(TSRMLS_C); + if (php_request_startup()==FAILURE) { + php_module_shutdown(); return FAILURE; } - + SG(headers_sent) = 1; SG(request_info).no_headers = 1; - php_register_variable("PHP_SELF", "-", NULL TSRMLS_CC); + php_register_variable("PHP_SELF", "-", NULL); return SUCCESS; } -EMBED_SAPI_API void php_embed_shutdown(TSRMLS_D) +EMBED_SAPI_API void php_embed_shutdown(void) { php_request_shutdown((void *) 0); - php_module_shutdown(TSRMLS_C); + php_module_shutdown(); sapi_shutdown(); #ifdef ZTS tsrm_shutdown(); diff --git a/sapi/embed/php_embed.h b/sapi/embed/php_embed.h index 4f45dab343..92a2f70be7 100644 --- a/sapi/embed/php_embed.h +++ b/sapi/embed/php_embed.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -27,45 +27,30 @@ #include <main/php_ini.h> #include <zend_ini.h> -#ifdef ZTS -#define PTSRMLS_D void ****ptsrm_ls -#define PTSRMLS_DC , PTSRMLS_D -#define PTSRMLS_C &tsrm_ls -#define PTSRMLS_CC , PTSRMLS_C - -#define PHP_EMBED_START_BLOCK(x,y) { \ - void ***tsrm_ls; \ - php_embed_init(x, y PTSRMLS_CC); \ - zend_first_try { - -#else -#define PTSRMLS_D -#define PTSRMLS_DC -#define PTSRMLS_C -#define PTSRMLS_CC - #define PHP_EMBED_START_BLOCK(x,y) { \ php_embed_init(x, y); \ zend_first_try { -#endif - #define PHP_EMBED_END_BLOCK() \ } zend_catch { \ /* int exit_status = EG(exit_status); */ \ } zend_end_try(); \ - php_embed_shutdown(TSRMLS_C); \ + php_embed_shutdown(); \ } #ifndef PHP_WIN32 #define EMBED_SAPI_API SAPI_API #else - #define EMBED_SAPI_API -#endif + #define EMBED_SAPI_API +#endif + +#ifdef ZTS +ZEND_TSRMLS_CACHE_EXTERN() +#endif -BEGIN_EXTERN_C() -EMBED_SAPI_API int php_embed_init(int argc, char **argv PTSRMLS_DC); -EMBED_SAPI_API void php_embed_shutdown(TSRMLS_D); +BEGIN_EXTERN_C() +EMBED_SAPI_API int php_embed_init(int argc, char **argv); +EMBED_SAPI_API void php_embed_shutdown(void); extern EMBED_SAPI_API sapi_module_struct php_embed_module; END_EXTERN_C() diff --git a/sapi/fpm/Makefile.frag b/sapi/fpm/Makefile.frag index d6e1a96fa6..b0b4b34658 100644 --- a/sapi/fpm/Makefile.frag +++ b/sapi/fpm/Makefile.frag @@ -1,6 +1,6 @@ fpm: $(SAPI_FPM_PATH) -$(SAPI_FPM_PATH): $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_FPM_OBJS) +$(SAPI_FPM_PATH): $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_FASTCGI_OBJS) $(PHP_FPM_OBJS) $(BUILD_FPM) install-fpm: $(SAPI_FPM_PATH) @@ -11,8 +11,9 @@ install-fpm: $(SAPI_FPM_PATH) @$(INSTALL) -m 0755 $(SAPI_FPM_PATH) $(INSTALL_ROOT)$(sbindir)/$(program_prefix)php-fpm$(program_suffix)$(EXEEXT) @echo "Installing PHP FPM config: $(INSTALL_ROOT)$(sysconfdir)/" && \ - $(mkinstalldirs) $(INSTALL_ROOT)$(sysconfdir) || : + $(mkinstalldirs) $(INSTALL_ROOT)$(sysconfdir)/php-fpm.d || : @$(INSTALL_DATA) sapi/fpm/php-fpm.conf $(INSTALL_ROOT)$(sysconfdir)/php-fpm.conf.default || : + @$(INSTALL_DATA) sapi/fpm/www.conf $(INSTALL_ROOT)$(sysconfdir)/php-fpm.d/www.conf.default || : @echo "Installing PHP FPM man page: $(INSTALL_ROOT)$(mandir)/man8/" @$(mkinstalldirs) $(INSTALL_ROOT)$(mandir)/man8 diff --git a/sapi/fpm/config.m4 b/sapi/fpm/config.m4 index 7bfa50bd3d..e6a1a49857 100644 --- a/sapi/fpm/config.m4 +++ b/sapi/fpm/config.m4 @@ -667,7 +667,7 @@ if test "$PHP_FPM" != "no"; then PHP_ADD_BUILD_DIR(sapi/fpm/fpm) PHP_ADD_BUILD_DIR(sapi/fpm/fpm/events) - PHP_OUTPUT(sapi/fpm/php-fpm.conf sapi/fpm/init.d.php-fpm sapi/fpm/php-fpm.service sapi/fpm/php-fpm.8 sapi/fpm/status.html) + PHP_OUTPUT(sapi/fpm/php-fpm.conf sapi/fpm/www.conf sapi/fpm/init.d.php-fpm sapi/fpm/php-fpm.service sapi/fpm/php-fpm.8 sapi/fpm/status.html) PHP_ADD_MAKEFILE_FRAGMENT([$abs_srcdir/sapi/fpm/Makefile.frag]) SAPI_FPM_PATH=sapi/fpm/php-fpm @@ -678,8 +678,7 @@ if test "$PHP_FPM" != "no"; then PHP_FPM_CFLAGS="-I$abs_srcdir/sapi/fpm" - PHP_FPM_FILES="fpm/fastcgi.c \ - fpm/fpm.c \ + PHP_FPM_FILES="fpm/fpm.c \ fpm/fpm_children.c \ fpm/fpm_cleanup.c \ fpm/fpm_clock.c \ @@ -713,13 +712,13 @@ if test "$PHP_FPM" != "no"; then case $host_alias in *aix*) - BUILD_FPM="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FPM_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FPM_OBJS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)" + BUILD_FPM="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FPM_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_FPM_OBJS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)" ;; *darwin*) - BUILD_FPM="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_FPM_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)" + BUILD_FPM="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_FASTCGI_OBJS:.lo=.o) \$(PHP_FPM_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)" ;; *) - BUILD_FPM="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FPM_OBJS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)" + BUILD_FPM="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_FPM_OBJS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)" ;; esac diff --git a/sapi/fpm/fpm/events/devpoll.c b/sapi/fpm/fpm/events/devpoll.c index 3bf22bf202..303978643a 100644 --- a/sapi/fpm/fpm/events/devpoll.c +++ b/sapi/fpm/fpm/events/devpoll.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -45,7 +45,7 @@ static struct fpm_event_module_s devpoll_module = { .clean = fpm_event_devpoll_clean, .wait = fpm_event_devpoll_wait, .add = fpm_event_devpoll_add, - .remove = fpm_event_devpoll_remove, + .remove = fpm_event_devpoll_remove, }; int dpfd = -1; @@ -76,7 +76,7 @@ static int fpm_event_devpoll_init(int max) /* {{{ */ /* open /dev/poll for future usages */ dpfd = open("/dev/poll", O_RDWR); - if (dpfd < 0) { + if (dpfd < 0) { zlog(ZLOG_ERROR, "Unable to open /dev/poll"); return -1; } @@ -120,7 +120,7 @@ static int fpm_event_devpoll_init(int max) /* {{{ */ static int fpm_event_devpoll_clean() /* {{{ */ { /* close /dev/poll if open */ - if (dpfd > -1) { + if (dpfd > -1) { close(dpfd); dpfd = -1; } @@ -176,7 +176,7 @@ static int fpm_event_devpoll_wait(struct fpm_event_queue_s *queue, unsigned long while (q) { /* found */ - if (q->ev && q->ev->fd == active_pollfds[i].fd) { + if (q->ev && q->ev->fd == active_pollfds[i].fd) { /* fire the event */ fpm_event_fire(q->ev); diff --git a/sapi/fpm/fpm/events/devpoll.h b/sapi/fpm/fpm/events/devpoll.h index 3549cddd9e..c77c734c9e 100644 --- a/sapi/fpm/fpm/events/devpoll.h +++ b/sapi/fpm/fpm/events/devpoll.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ diff --git a/sapi/fpm/fpm/events/epoll.c b/sapi/fpm/fpm/events/epoll.c index 9cd12ea721..b45f4f9b43 100644 --- a/sapi/fpm/fpm/events/epoll.c +++ b/sapi/fpm/fpm/events/epoll.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -41,7 +41,7 @@ static struct fpm_event_module_s epoll_module = { .clean = fpm_event_epoll_clean, .wait = fpm_event_epoll_wait, .add = fpm_event_epoll_add, - .remove = fpm_event_epoll_remove, + .remove = fpm_event_epoll_remove, }; static struct epoll_event *epollfds = NULL; @@ -164,6 +164,10 @@ static int fpm_event_epoll_add(struct fpm_event_s *ev) /* {{{ */ struct epoll_event e; /* fill epoll struct */ +#if SIZEOF_SIZE_T == 4 + /* Completely initialize event data to prevent valgrind reports */ + e.data.u64 = 0; +#endif e.events = EPOLLIN; e.data.fd = ev->fd; e.data.ptr = (void *)ev; diff --git a/sapi/fpm/fpm/events/epoll.h b/sapi/fpm/fpm/events/epoll.h index 12805685eb..9ffea786bd 100644 --- a/sapi/fpm/fpm/events/epoll.h +++ b/sapi/fpm/fpm/events/epoll.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ diff --git a/sapi/fpm/fpm/events/kqueue.c b/sapi/fpm/fpm/events/kqueue.c index aa7f051368..6397405de5 100644 --- a/sapi/fpm/fpm/events/kqueue.c +++ b/sapi/fpm/fpm/events/kqueue.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -44,7 +44,7 @@ static struct fpm_event_module_s kqueue_module = { .clean = fpm_event_kqueue_clean, .wait = fpm_event_kqueue_wait, .add = fpm_event_kqueue_add, - .remove = fpm_event_kqueue_remove, + .remove = fpm_event_kqueue_remove, }; static struct kevent *kevents = NULL; diff --git a/sapi/fpm/fpm/events/kqueue.h b/sapi/fpm/fpm/events/kqueue.h index df3f97ddfc..d336863260 100644 --- a/sapi/fpm/fpm/events/kqueue.h +++ b/sapi/fpm/fpm/events/kqueue.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ diff --git a/sapi/fpm/fpm/events/poll.c b/sapi/fpm/fpm/events/poll.c index 60dadeabda..484cb8890a 100644 --- a/sapi/fpm/fpm/events/poll.c +++ b/sapi/fpm/fpm/events/poll.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -42,7 +42,7 @@ static struct fpm_event_module_s poll_module = { .clean = fpm_event_poll_clean, .wait = fpm_event_poll_wait, .add = fpm_event_poll_add, - .remove = fpm_event_poll_remove, + .remove = fpm_event_poll_remove, }; static struct pollfd *pollfds = NULL; @@ -150,7 +150,7 @@ static int fpm_event_poll_wait(struct fpm_event_queue_s *queue, unsigned long in return -1; } } - + /* events have been triggered */ if (ret > 0) { diff --git a/sapi/fpm/fpm/events/poll.h b/sapi/fpm/fpm/events/poll.h index 7cd839990b..ce33ee5651 100644 --- a/sapi/fpm/fpm/events/poll.h +++ b/sapi/fpm/fpm/events/poll.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ diff --git a/sapi/fpm/fpm/events/port.c b/sapi/fpm/fpm/events/port.c index 501acbf81b..8eb2ace8ec 100644 --- a/sapi/fpm/fpm/events/port.c +++ b/sapi/fpm/fpm/events/port.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -42,7 +42,7 @@ static struct fpm_event_module_s port_module = { .clean = fpm_event_port_clean, .wait = fpm_event_port_wait, .add = fpm_event_port_add, - .remove = fpm_event_port_remove, + .remove = fpm_event_port_remove, }; port_event_t *events = NULL; diff --git a/sapi/fpm/fpm/events/port.h b/sapi/fpm/fpm/events/port.h index cd9b4de9f5..12b6b6b202 100644 --- a/sapi/fpm/fpm/events/port.h +++ b/sapi/fpm/fpm/events/port.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ diff --git a/sapi/fpm/fpm/events/select.c b/sapi/fpm/fpm/events/select.c index 6c98dc189b..b26047ca08 100644 --- a/sapi/fpm/fpm/events/select.c +++ b/sapi/fpm/fpm/events/select.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ diff --git a/sapi/fpm/fpm/events/select.h b/sapi/fpm/fpm/events/select.h index 77fccc8fdf..1de3837956 100644 --- a/sapi/fpm/fpm/events/select.h +++ b/sapi/fpm/fpm/events/select.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ diff --git a/sapi/fpm/fpm/fastcgi.c b/sapi/fpm/fpm/fastcgi.c deleted file mode 100644 index 778119e45a..0000000000 --- a/sapi/fpm/fpm/fastcgi.c +++ /dev/null @@ -1,1159 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Dmitry Stogov <dmitry@zend.com> | - +----------------------------------------------------------------------+ -*/ - -/* $Id: fastcgi.c 287777 2009-08-26 19:17:32Z pajoye $ */ - -#include "php.h" -#include "fastcgi.h" - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <errno.h> -#include <limits.h> - -#include <php_config.h> -#include "fpm.h" -#include "fpm_request.h" -#include "zlog.h" - -#ifdef _WIN32 - -#include <windows.h> - - struct sockaddr_un { - short sun_family; - char sun_path[MAXPATHLEN]; - }; - - static HANDLE fcgi_accept_mutex = INVALID_HANDLE_VALUE; - static int is_impersonate = 0; - -#define FCGI_LOCK(fd) \ - if (fcgi_accept_mutex != INVALID_HANDLE_VALUE) { \ - DWORD ret; \ - while ((ret = WaitForSingleObject(fcgi_accept_mutex, 1000)) == WAIT_TIMEOUT) { \ - if (in_shutdown) return -1; \ - } \ - if (ret == WAIT_FAILED) { \ - fprintf(stderr, "WaitForSingleObject() failed\n"); \ - return -1; \ - } \ - } - -#define FCGI_UNLOCK(fd) \ - if (fcgi_accept_mutex != INVALID_HANDLE_VALUE) { \ - ReleaseMutex(fcgi_accept_mutex); \ - } - -#else - -# include <sys/types.h> -# include <sys/stat.h> -# include <unistd.h> -# include <fcntl.h> -# include <sys/socket.h> -# include <sys/un.h> -# include <netinet/in.h> -# include <arpa/inet.h> -# include <netdb.h> -# include <signal.h> - -# define closesocket(s) close(s) - -# if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL) -# include <sys/poll.h> -# endif -# if defined(HAVE_SYS_SELECT_H) -# include <sys/select.h> -# endif - -#ifndef INADDR_NONE -#define INADDR_NONE ((unsigned long) -1) -#endif - -# ifndef HAVE_SOCKLEN_T - typedef unsigned int socklen_t; -# endif - -# ifdef USE_LOCKING -# define FCGI_LOCK(fd) \ - do { \ - struct flock lock; \ - lock.l_type = F_WRLCK; \ - lock.l_start = 0; \ - lock.l_whence = SEEK_SET; \ - lock.l_len = 0; \ - if (fcntl(fd, F_SETLKW, &lock) != -1) { \ - break; \ - } else if (errno != EINTR || in_shutdown) { \ - return -1; \ - } \ - } while (1) - -# define FCGI_UNLOCK(fd) \ - do { \ - int orig_errno = errno; \ - while (1) { \ - struct flock lock; \ - lock.l_type = F_UNLCK; \ - lock.l_start = 0; \ - lock.l_whence = SEEK_SET; \ - lock.l_len = 0; \ - if (fcntl(fd, F_SETLK, &lock) != -1) { \ - break; \ - } else if (errno != EINTR) { \ - return -1; \ - } \ - } \ - errno = orig_errno; \ - } while (0) -# else -# define FCGI_LOCK(fd) -# define FCGI_UNLOCK(fd) -# endif - -#endif - -typedef union _sa_t { - struct sockaddr sa; - struct sockaddr_un sa_unix; - struct sockaddr_in sa_inet; - struct sockaddr_in6 sa_inet6; -} sa_t; - -static HashTable fcgi_mgmt_vars; - -static int is_initialized = 0; -static int in_shutdown = 0; -static sa_t *allowed_clients = NULL; - -static sa_t client_sa; - -#ifdef _WIN32 - -static DWORD WINAPI fcgi_shutdown_thread(LPVOID arg) -{ - HANDLE shutdown_event = (HANDLE) arg; - WaitForSingleObject(shutdown_event, INFINITE); - in_shutdown = 1; - return 0; -} - -#else - -static void fcgi_signal_handler(int signo) -{ - if (signo == SIGUSR1 || signo == SIGTERM) { - in_shutdown = 1; - } -} - -static void fcgi_setup_signals(void) -{ - struct sigaction new_sa, old_sa; - - sigemptyset(&new_sa.sa_mask); - new_sa.sa_flags = 0; - new_sa.sa_handler = fcgi_signal_handler; - sigaction(SIGUSR1, &new_sa, NULL); - sigaction(SIGTERM, &new_sa, NULL); - sigaction(SIGPIPE, NULL, &old_sa); - if (old_sa.sa_handler == SIG_DFL) { - sigaction(SIGPIPE, &new_sa, NULL); - } -} -#endif - -int fcgi_init(void) -{ - if (!is_initialized) { - zend_hash_init(&fcgi_mgmt_vars, 0, NULL, fcgi_free_mgmt_var_cb, 1); - fcgi_set_mgmt_var("FCGI_MPXS_CONNS", sizeof("FCGI_MPXS_CONNS") - 1, "0", sizeof("0")-1); - - is_initialized = 1; -#ifdef _WIN32 -# if 0 - /* TODO: Support for TCP sockets */ - WSADATA wsaData; - - if (WSAStartup(MAKEWORD(2,0), &wsaData)) { - fprintf(stderr, "Error starting Windows Sockets. Error: %d", WSAGetLastError()); - return 0; - } -# endif - { - char *str; - DWORD pipe_mode = PIPE_READMODE_BYTE | PIPE_WAIT; - HANDLE pipe = GetStdHandle(STD_INPUT_HANDLE); - - SetNamedPipeHandleState(pipe, &pipe_mode, NULL, NULL); - - str = getenv("_FCGI_SHUTDOWN_EVENT_"); - if (str != NULL) { - HANDLE shutdown_event = (HANDLE) atoi(str); - if (!CreateThread(NULL, 0, fcgi_shutdown_thread, - shutdown_event, 0, NULL)) { - return -1; - } - } - str = getenv("_FCGI_MUTEX_"); - if (str != NULL) { - fcgi_accept_mutex = (HANDLE) atoi(str); - } - return 1; - } -#else - fcgi_setup_signals(); - return 1; -#endif - } - return 1; -} - -void fcgi_set_in_shutdown(int new_value) -{ - in_shutdown = new_value; -} - -void fcgi_shutdown(void) -{ - if (is_initialized) { - zend_hash_destroy(&fcgi_mgmt_vars); - } - if (allowed_clients) { - free(allowed_clients); - } -} - -void fcgi_set_allowed_clients(char *ip) -{ - char *cur, *end; - int n; - - if (ip) { - ip = strdup(ip); - cur = ip; - n = 0; - while (*cur) { - if (*cur == ',') n++; - cur++; - } - if (allowed_clients) free(allowed_clients); - allowed_clients = malloc(sizeof(sa_t) * (n+2)); - n = 0; - cur = ip; - while (cur) { - end = strchr(cur, ','); - if (end) { - *end = 0; - end++; - } - if (inet_pton(AF_INET, cur, &allowed_clients[n].sa_inet.sin_addr)>0) { - allowed_clients[n].sa.sa_family = AF_INET; - n++; - } else if (inet_pton(AF_INET6, cur, &allowed_clients[n].sa_inet6.sin6_addr)>0) { - allowed_clients[n].sa.sa_family = AF_INET6; - n++; - } else { - zlog(ZLOG_ERROR, "Wrong IP address '%s' in listen.allowed_clients", cur); - } - cur = end; - } - allowed_clients[n].sa.sa_family = 0; - free(ip); - if (!n) { - zlog(ZLOG_ERROR, "There are no allowed addresses for this pool"); - /* don't clear allowed_clients as it will create an "open for all" security issue */ - } - } -} - -void fcgi_init_request(fcgi_request *req, int listen_socket) -{ - memset(req, 0, sizeof(fcgi_request)); - req->listen_socket = listen_socket; - req->fd = -1; - req->id = -1; - - req->in_len = 0; - req->in_pad = 0; - - req->out_hdr = NULL; - req->out_pos = req->out_buf; - -#ifdef _WIN32 - req->tcp = !GetNamedPipeInfo((HANDLE)_get_osfhandle(req->listen_socket), NULL, NULL, NULL, NULL); -#endif -} - -static inline ssize_t safe_write(fcgi_request *req, const void *buf, size_t count) -{ - int ret; - size_t n = 0; - - do { - errno = 0; -#ifdef _WIN32 - if (!req->tcp) { - ret = write(req->fd, ((char*)buf)+n, count-n); - } else { - ret = send(req->fd, ((char*)buf)+n, count-n, 0); - if (ret <= 0) { - errno = WSAGetLastError(); - } - } -#else - ret = write(req->fd, ((char*)buf)+n, count-n); -#endif - if (ret > 0) { - n += ret; - } else if (ret <= 0 && errno != 0 && errno != EINTR) { - return ret; - } - } while (n != count); - return n; -} - -static inline ssize_t safe_read(fcgi_request *req, const void *buf, size_t count) -{ - int ret; - size_t n = 0; - - do { - errno = 0; -#ifdef _WIN32 - if (!req->tcp) { - ret = read(req->fd, ((char*)buf)+n, count-n); - } else { - ret = recv(req->fd, ((char*)buf)+n, count-n, 0); - if (ret <= 0) { - errno = WSAGetLastError(); - } - } -#else - ret = read(req->fd, ((char*)buf)+n, count-n); -#endif - if (ret > 0) { - n += ret; - } else if (ret == 0 && errno == 0) { - return n; - } else if (ret <= 0 && errno != 0 && errno != EINTR) { - return ret; - } - } while (n != count); - return n; -} - -static inline int fcgi_make_header(fcgi_header *hdr, fcgi_request_type type, int req_id, int len) -{ - int pad = ((len + 7) & ~7) - len; - - hdr->contentLengthB0 = (unsigned char)(len & 0xff); - hdr->contentLengthB1 = (unsigned char)((len >> 8) & 0xff); - hdr->paddingLength = (unsigned char)pad; - hdr->requestIdB0 = (unsigned char)(req_id & 0xff); - hdr->requestIdB1 = (unsigned char)((req_id >> 8) & 0xff); - hdr->reserved = 0; - hdr->type = type; - hdr->version = FCGI_VERSION_1; - if (pad) { - memset(((unsigned char*)hdr) + sizeof(fcgi_header) + len, 0, pad); - } - return pad; -} - -static inline size_t fcgi_get_params_len( int *result, unsigned char *p, unsigned char *end) -{ - size_t ret = 0; - - if (p < end) { - *result = p[0]; - if (*result < 128) { - ret = 1; - } - else if (p + 3 < end) { - *result = ((*result & 0x7f) << 24); - *result |= (p[1] << 16); - *result |= (p[2] << 8); - *result |= p[3]; - ret = 4; - } - } - if (*result < 0) { - ret = 0; - } - return ret; -} - -static inline int fcgi_param_get_eff_len( unsigned char *p, unsigned char *end, uint *eff_len) -{ - int ret = 1; - int zero_found = 0; - *eff_len = 0; - for (; p != end; ++p) { - if (*p == '\0') { - zero_found = 1; - } - else { - if (zero_found) { - ret = 0; - break; - } - if (*eff_len < ((uint)-1)) { - ++*eff_len; - } - else { - ret = 0; - break; - } - } - } - return ret; -} - -static int fcgi_get_params(fcgi_request *req, unsigned char *p, unsigned char *end) -{ - char buf[128]; - char *tmp = buf; - size_t buf_size = sizeof(buf); - int name_len = 0; - int val_len = 0; - uint eff_name_len = 0; - char *s; - int ret = 1; - size_t bytes_consumed; - - while (p < end) { - bytes_consumed = fcgi_get_params_len(&name_len, p, end); - if (!bytes_consumed) { - /* Malformated request */ - ret = 0; - break; - } - p += bytes_consumed; - bytes_consumed = fcgi_get_params_len(&val_len, p, end); - if (!bytes_consumed) { - /* Malformated request */ - ret = 0; - break; - } - p += bytes_consumed; - if (name_len > (INT_MAX - val_len) || /* would the addition overflow? */ - name_len + val_len > end - p) { /* would we exceed the buffer? */ - /* Malformated request */ - ret = 0; - break; - } - - /* - * get the effective length of the name in case it's not a valid string - * don't do this on the value because it can be binary data - */ - if (!fcgi_param_get_eff_len(p, p+name_len, &eff_name_len)){ - /* Malicious request */ - ret = 0; - break; - } - if (eff_name_len >= buf_size-1) { - if (eff_name_len > ((uint)-1)-64) { - ret = 0; - break; - } - buf_size = eff_name_len + 64; - tmp = (tmp == buf ? emalloc(buf_size): erealloc(tmp, buf_size)); - if (tmp == NULL) { - ret = 0; - break; - } - } - memcpy(tmp, p, eff_name_len); - tmp[eff_name_len] = 0; - s = estrndup((char*)p + name_len, val_len); - if (s == NULL) { - ret = 0; - break; - } - zend_hash_update(req->env, tmp, eff_name_len+1, &s, sizeof(char*), NULL); - p += name_len + val_len; - } - if (tmp != buf && tmp != NULL) { - efree(tmp); - } - return ret; -} - -static void fcgi_free_var(char **s) -{ - efree(*s); -} - -static int fcgi_read_request(fcgi_request *req) -{ - fcgi_header hdr; - int len, padding; - unsigned char buf[FCGI_MAX_LENGTH+8]; - - req->keep = 0; - req->closed = 0; - req->in_len = 0; - req->out_hdr = NULL; - req->out_pos = req->out_buf; - ALLOC_HASHTABLE(req->env); - zend_hash_init(req->env, 0, NULL, (void (*)(void *)) fcgi_free_var, 0); - - if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || - hdr.version < FCGI_VERSION_1) { - return 0; - } - - len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; - padding = hdr.paddingLength; - - while (hdr.type == FCGI_STDIN && len == 0) { - if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || - hdr.version < FCGI_VERSION_1) { - return 0; - } - - len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; - padding = hdr.paddingLength; - } - - if (len + padding > FCGI_MAX_LENGTH) { - return 0; - } - - req->id = (hdr.requestIdB1 << 8) + hdr.requestIdB0; - - if (hdr.type == FCGI_BEGIN_REQUEST && len == sizeof(fcgi_begin_request)) { - char *val; - - if (safe_read(req, buf, len+padding) != len+padding) { - return 0; - } - - req->keep = (((fcgi_begin_request*)buf)->flags & FCGI_KEEP_CONN); - switch ((((fcgi_begin_request*)buf)->roleB1 << 8) + ((fcgi_begin_request*)buf)->roleB0) { - case FCGI_RESPONDER: - val = estrdup("RESPONDER"); - zend_hash_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); - break; - case FCGI_AUTHORIZER: - val = estrdup("AUTHORIZER"); - zend_hash_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); - break; - case FCGI_FILTER: - val = estrdup("FILTER"); - zend_hash_update(req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); - break; - default: - return 0; - } - - if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || - hdr.version < FCGI_VERSION_1) { - return 0; - } - - len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; - padding = hdr.paddingLength; - - while (hdr.type == FCGI_PARAMS && len > 0) { - if (len + padding > FCGI_MAX_LENGTH) { - return 0; - } - - if (safe_read(req, buf, len+padding) != len+padding) { - req->keep = 0; - return 0; - } - - if (!fcgi_get_params(req, buf, buf+len)) { - req->keep = 0; - return 0; - } - - if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || - hdr.version < FCGI_VERSION_1) { - req->keep = 0; - return 0; - } - len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; - padding = hdr.paddingLength; - } - } else if (hdr.type == FCGI_GET_VALUES) { - unsigned char *p = buf + sizeof(fcgi_header); - HashPosition pos; - char * str_index; - uint str_length; - ulong num_index; - int key_type; - zval ** value; - - if (safe_read(req, buf, len+padding) != len+padding) { - req->keep = 0; - return 0; - } - - if (!fcgi_get_params(req, buf, buf+len)) { - req->keep = 0; - return 0; - } - - zend_hash_internal_pointer_reset_ex(req->env, &pos); - while ((key_type = zend_hash_get_current_key_ex(req->env, &str_index, &str_length, &num_index, 0, &pos)) != HASH_KEY_NON_EXISTENT) { - int zlen; - zend_hash_move_forward_ex(req->env, &pos); - if (key_type != HASH_KEY_IS_STRING) { - continue; - } - if (zend_hash_find(&fcgi_mgmt_vars, str_index, str_length, (void**) &value) != SUCCESS) { - continue; - } - --str_length; - zlen = Z_STRLEN_PP(value); - if ((p + 4 + 4 + str_length + zlen) >= (buf + sizeof(buf))) { - break; - } - if (str_length < 0x80) { - *p++ = str_length; - } else { - *p++ = ((str_length >> 24) & 0xff) | 0x80; - *p++ = (str_length >> 16) & 0xff; - *p++ = (str_length >> 8) & 0xff; - *p++ = str_length & 0xff; - } - if (zlen < 0x80) { - *p++ = zlen; - } else { - *p++ = ((zlen >> 24) & 0xff) | 0x80; - *p++ = (zlen >> 16) & 0xff; - *p++ = (zlen >> 8) & 0xff; - *p++ = zlen & 0xff; - } - memcpy(p, str_index, str_length); - p += str_length; - memcpy(p, Z_STRVAL_PP(value), zlen); - p += zlen; - } - len = p - buf - sizeof(fcgi_header); - len += fcgi_make_header((fcgi_header*)buf, FCGI_GET_VALUES_RESULT, 0, len); - if (safe_write(req, buf, sizeof(fcgi_header)+len) != (int)sizeof(fcgi_header)+len) { - req->keep = 0; - return 0; - } - return 0; - } else { - return 0; - } - - return 1; -} - -int fcgi_read(fcgi_request *req, char *str, int len) -{ - int ret, n, rest; - fcgi_header hdr; - unsigned char buf[255]; - - n = 0; - rest = len; - while (rest > 0) { - if (req->in_len == 0) { - if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || - hdr.version < FCGI_VERSION_1 || - hdr.type != FCGI_STDIN) { - req->keep = 0; - return 0; - } - req->in_len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; - req->in_pad = hdr.paddingLength; - if (req->in_len == 0) { - return n; - } - } - - if (req->in_len >= rest) { - ret = safe_read(req, str, rest); - } else { - ret = safe_read(req, str, req->in_len); - } - if (ret < 0) { - req->keep = 0; - return ret; - } else if (ret > 0) { - req->in_len -= ret; - rest -= ret; - n += ret; - str += ret; - if (req->in_len == 0) { - if (req->in_pad) { - if (safe_read(req, buf, req->in_pad) != req->in_pad) { - req->keep = 0; - return ret; - } - } - } else { - return n; - } - } else { - return n; - } - } - return n; -} - -void fcgi_close(fcgi_request *req, int force, int destroy) -{ - if (destroy && req->env) { - zend_hash_destroy(req->env); - FREE_HASHTABLE(req->env); - req->env = NULL; - } - -#ifdef _WIN32 - if (is_impersonate && !req->tcp) { - RevertToSelf(); - } -#endif - - if ((force || !req->keep) && req->fd >= 0) { -#ifdef _WIN32 - if (!req->tcp) { - HANDLE pipe = (HANDLE)_get_osfhandle(req->fd); - - if (!force) { - FlushFileBuffers(pipe); - } - DisconnectNamedPipe(pipe); - } else { - if (!force) { - char buf[8]; - - shutdown(req->fd, 1); - while (recv(req->fd, buf, sizeof(buf), 0) > 0) {} - } - closesocket(req->fd); - } -#else - if (!force) { - char buf[8]; - - shutdown(req->fd, 1); - while (recv(req->fd, buf, sizeof(buf), 0) > 0) {} - } - close(req->fd); -#endif - req->fd = -1; - fpm_request_finished(); - } -} - -static int fcgi_is_allowed() { - int i; - - if (client_sa.sa.sa_family == AF_UNIX) { - return 1; - } - if (!allowed_clients) { - return 1; - } - if (client_sa.sa.sa_family == AF_INET) { - for (i=0 ; allowed_clients[i].sa.sa_family ; i++) { - if (allowed_clients[i].sa.sa_family == AF_INET - && !memcmp(&client_sa.sa_inet.sin_addr, &allowed_clients[i].sa_inet.sin_addr, 4)) { - return 1; - } - } - } - if (client_sa.sa.sa_family == AF_INET6) { - for (i=0 ; allowed_clients[i].sa.sa_family ; i++) { - if (allowed_clients[i].sa.sa_family == AF_INET6 - && !memcmp(&client_sa.sa_inet6.sin6_addr, &allowed_clients[i].sa_inet6.sin6_addr, 12)) { - return 1; - } -#ifdef IN6_IS_ADDR_V4MAPPED - if (allowed_clients[i].sa.sa_family == AF_INET - && IN6_IS_ADDR_V4MAPPED(&client_sa.sa_inet6.sin6_addr) - && !memcmp(((char *)&client_sa.sa_inet6.sin6_addr)+12, &allowed_clients[i].sa_inet.sin_addr, 4)) { - return 1; - } -#endif - } - } - - zlog(ZLOG_ERROR, "Connection disallowed: IP address '%s' has been dropped.", fcgi_get_last_client_ip()); - return 0; -} - -int fcgi_accept_request(fcgi_request *req) -{ -#ifdef _WIN32 - HANDLE pipe; - OVERLAPPED ov; -#endif - - while (1) { - if (req->fd < 0) { - while (1) { - if (in_shutdown) { - return -1; - } -#ifdef _WIN32 - if (!req->tcp) { - pipe = (HANDLE)_get_osfhandle(req->listen_socket); - FCGI_LOCK(req->listen_socket); - ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if (!ConnectNamedPipe(pipe, &ov)) { - errno = GetLastError(); - if (errno == ERROR_IO_PENDING) { - while (WaitForSingleObject(ov.hEvent, 1000) == WAIT_TIMEOUT) { - if (in_shutdown) { - CloseHandle(ov.hEvent); - FCGI_UNLOCK(req->listen_socket); - return -1; - } - } - } else if (errno != ERROR_PIPE_CONNECTED) { - } - } - CloseHandle(ov.hEvent); - req->fd = req->listen_socket; - FCGI_UNLOCK(req->listen_socket); - } else { - SOCKET listen_socket = (SOCKET)_get_osfhandle(req->listen_socket); -#else - { - int listen_socket = req->listen_socket; -#endif - sa_t sa; - socklen_t len = sizeof(sa); - - fpm_request_accepting(); - - FCGI_LOCK(req->listen_socket); - req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len); - FCGI_UNLOCK(req->listen_socket); - - client_sa = sa; - if (req->fd >= 0 && !fcgi_is_allowed()) { - closesocket(req->fd); - req->fd = -1; - continue; - } - } - -#ifdef _WIN32 - if (req->fd < 0 && (in_shutdown || errno != EINTR)) { -#else - if (req->fd < 0 && (in_shutdown || (errno != EINTR && errno != ECONNABORTED))) { -#endif - return -1; - } - -#ifdef _WIN32 - break; -#else - if (req->fd >= 0) { -#if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL) - struct pollfd fds; - int ret; - - fpm_request_reading_headers(); - - fds.fd = req->fd; - fds.events = POLLIN; - fds.revents = 0; - do { - errno = 0; - ret = poll(&fds, 1, 5000); - } while (ret < 0 && errno == EINTR); - if (ret > 0 && (fds.revents & POLLIN)) { - break; - } - fcgi_close(req, 1, 0); -#else - fpm_request_reading_headers(); - - if (req->fd < FD_SETSIZE) { - struct timeval tv = {5,0}; - fd_set set; - int ret; - - FD_ZERO(&set); - FD_SET(req->fd, &set); - do { - errno = 0; - ret = select(req->fd + 1, &set, NULL, NULL, &tv) >= 0; - } while (ret < 0 && errno == EINTR); - if (ret > 0 && FD_ISSET(req->fd, &set)) { - break; - } - fcgi_close(req, 1, 0); - } else { - zlog(ZLOG_ERROR, "Too many open file descriptors. FD_SETSIZE limit exceeded."); - fcgi_close(req, 1, 0); - } -#endif - } -#endif - } - } else if (in_shutdown) { - return -1; - } - if (fcgi_read_request(req)) { -#ifdef _WIN32 - if (is_impersonate && !req->tcp) { - pipe = (HANDLE)_get_osfhandle(req->fd); - if (!ImpersonateNamedPipeClient(pipe)) { - fcgi_close(req, 1, 1); - continue; - } - } -#endif - return req->fd; - } else { - fcgi_close(req, 1, 1); - } - } -} - -static inline fcgi_header* open_packet(fcgi_request *req, fcgi_request_type type) -{ - req->out_hdr = (fcgi_header*) req->out_pos; - req->out_hdr->type = type; - req->out_pos += sizeof(fcgi_header); - return req->out_hdr; -} - -static inline void close_packet(fcgi_request *req) -{ - if (req->out_hdr) { - int len = req->out_pos - ((unsigned char*)req->out_hdr + sizeof(fcgi_header)); - - req->out_pos += fcgi_make_header(req->out_hdr, (fcgi_request_type)req->out_hdr->type, req->id, len); - req->out_hdr = NULL; - } -} - -int fcgi_flush(fcgi_request *req, int close) -{ - int len; - - close_packet(req); - - len = req->out_pos - req->out_buf; - - if (close) { - fcgi_end_request_rec *rec = (fcgi_end_request_rec*)(req->out_pos); - - fcgi_make_header(&rec->hdr, FCGI_END_REQUEST, req->id, sizeof(fcgi_end_request)); - rec->body.appStatusB3 = 0; - rec->body.appStatusB2 = 0; - rec->body.appStatusB1 = 0; - rec->body.appStatusB0 = 0; - rec->body.protocolStatus = FCGI_REQUEST_COMPLETE; - len += sizeof(fcgi_end_request_rec); - } - - if (safe_write(req, req->out_buf, len) != len) { - req->keep = 0; - req->out_pos = req->out_buf; - return 0; - } - - req->out_pos = req->out_buf; - return 1; -} - -ssize_t fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len) -{ - int limit, rest; - - if (len <= 0) { - return 0; - } - - if (req->out_hdr && req->out_hdr->type != type) { - close_packet(req); - } - - /* Optimized version */ - limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf); - if (!req->out_hdr) { - limit -= sizeof(fcgi_header); - if (limit < 0) limit = 0; - } - - if (len < limit) { - if (!req->out_hdr) { - open_packet(req, type); - } - memcpy(req->out_pos, str, len); - req->out_pos += len; - } else if (len - limit < sizeof(req->out_buf) - sizeof(fcgi_header)) { - if (!req->out_hdr) { - open_packet(req, type); - } - if (limit > 0) { - memcpy(req->out_pos, str, limit); - req->out_pos += limit; - } - if (!fcgi_flush(req, 0)) { - return -1; - } - if (len > limit) { - open_packet(req, type); - memcpy(req->out_pos, str + limit, len - limit); - req->out_pos += len - limit; - } - } else { - int pos = 0; - int pad; - - close_packet(req); - while ((len - pos) > 0xffff) { - open_packet(req, type); - fcgi_make_header(req->out_hdr, type, req->id, 0xfff8); - req->out_hdr = NULL; - if (!fcgi_flush(req, 0)) { - return -1; - } - if (safe_write(req, str + pos, 0xfff8) != 0xfff8) { - req->keep = 0; - return -1; - } - pos += 0xfff8; - } - - pad = (((len - pos) + 7) & ~7) - (len - pos); - rest = pad ? 8 - pad : 0; - - open_packet(req, type); - fcgi_make_header(req->out_hdr, type, req->id, (len - pos) - rest); - req->out_hdr = NULL; - if (!fcgi_flush(req, 0)) { - return -1; - } - if (safe_write(req, str + pos, (len - pos) - rest) != (len - pos) - rest) { - req->keep = 0; - return -1; - } - if (pad) { - open_packet(req, type); - memcpy(req->out_pos, str + len - rest, rest); - req->out_pos += rest; - } - } - - return len; -} - -int fcgi_finish_request(fcgi_request *req, int force_close) -{ - int ret = 1; - - if (req->fd >= 0) { - if (!req->closed) { - ret = fcgi_flush(req, 1); - req->closed = 1; - } - fcgi_close(req, force_close, 1); - } - return ret; -} - -char* fcgi_getenv(fcgi_request *req, const char* var, int var_len) -{ - char **val; - - if (!req) return NULL; - - if (zend_hash_find(req->env, (char*)var, var_len+1, (void**)&val) == SUCCESS) { - return *val; - } - return NULL; -} - -char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val) -{ - if (var && req) { - if (val == NULL) { - zend_hash_del(req->env, var, var_len+1); - } else { - char **ret; - - val = estrdup(val); - if (zend_hash_update(req->env, var, var_len+1, &val, sizeof(char*), (void**)&ret) == SUCCESS) { - return *ret; - } - } - } - return NULL; -} - -void fcgi_set_mgmt_var(const char * name, size_t name_len, const char * value, size_t value_len) -{ - zval * zvalue; - zvalue = pemalloc(sizeof(*zvalue), 1); - Z_TYPE_P(zvalue) = IS_STRING; - Z_STRVAL_P(zvalue) = pestrndup(value, value_len, 1); - Z_STRLEN_P(zvalue) = value_len; - zend_hash_add(&fcgi_mgmt_vars, name, name_len + 1, &zvalue, sizeof(zvalue), NULL); -} - -void fcgi_free_mgmt_var_cb(void * ptr) -{ - zval ** var = (zval **)ptr; - pefree(Z_STRVAL_PP(var), 1); - pefree(*var, 1); -} - -const char *fcgi_get_last_client_ip() /* {{{ */ -{ - static char str[INET6_ADDRSTRLEN]; - - /* Ipv4 */ - if (client_sa.sa.sa_family == AF_INET) { - return inet_ntop(client_sa.sa.sa_family, &client_sa.sa_inet.sin_addr, str, INET6_ADDRSTRLEN); - } -#ifdef IN6_IS_ADDR_V4MAPPED - /* Ipv4-Mapped-Ipv6 */ - if (client_sa.sa.sa_family == AF_INET6 - && IN6_IS_ADDR_V4MAPPED(&client_sa.sa_inet6.sin6_addr)) { - return inet_ntop(AF_INET, ((char *)&client_sa.sa_inet6.sin6_addr)+12, str, INET6_ADDRSTRLEN); - } -#endif - /* Ipv6 */ - if (client_sa.sa.sa_family == AF_INET6) { - return inet_ntop(client_sa.sa.sa_family, &client_sa.sa_inet6.sin6_addr, str, INET6_ADDRSTRLEN); - } - /* Unix socket */ - return NULL; -} -/* }}} */ -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/sapi/fpm/fpm/fastcgi.h b/sapi/fpm/fpm/fastcgi.h deleted file mode 100644 index 4da1c355ae..0000000000 --- a/sapi/fpm/fpm/fastcgi.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | http://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Authors: Dmitry Stogov <dmitry@zend.com> | - +----------------------------------------------------------------------+ -*/ - -/* $Id: fastcgi.h 272370 2008-12-31 11:15:49Z sebastian $ */ - -/* FastCGI protocol */ - -#define FCGI_VERSION_1 1 - -#define FCGI_MAX_LENGTH 0xffff - -#define FCGI_KEEP_CONN 1 - -typedef enum _fcgi_role { - FCGI_RESPONDER = 1, - FCGI_AUTHORIZER = 2, - FCGI_FILTER = 3 -} fcgi_role; - -typedef enum _fcgi_request_type { - FCGI_BEGIN_REQUEST = 1, /* [in] */ - FCGI_ABORT_REQUEST = 2, /* [in] (not supported) */ - FCGI_END_REQUEST = 3, /* [out] */ - FCGI_PARAMS = 4, /* [in] environment variables */ - FCGI_STDIN = 5, /* [in] post data */ - FCGI_STDOUT = 6, /* [out] response */ - FCGI_STDERR = 7, /* [out] errors */ - FCGI_DATA = 8, /* [in] filter data (not supported) */ - FCGI_GET_VALUES = 9, /* [in] */ - FCGI_GET_VALUES_RESULT = 10 /* [out] */ -} fcgi_request_type; - -typedef enum _fcgi_protocol_status { - FCGI_REQUEST_COMPLETE = 0, - FCGI_CANT_MPX_CONN = 1, - FCGI_OVERLOADED = 2, - FCGI_UNKNOWN_ROLE = 3 -} dcgi_protocol_status; - -typedef struct _fcgi_header { - unsigned char version; - unsigned char type; - unsigned char requestIdB1; - unsigned char requestIdB0; - unsigned char contentLengthB1; - unsigned char contentLengthB0; - unsigned char paddingLength; - unsigned char reserved; -} fcgi_header; - -typedef struct _fcgi_begin_request { - unsigned char roleB1; - unsigned char roleB0; - unsigned char flags; - unsigned char reserved[5]; -} fcgi_begin_request; - -typedef struct _fcgi_begin_request_rec { - fcgi_header hdr; - fcgi_begin_request body; -} fcgi_begin_request_rec; - -typedef struct _fcgi_end_request { - unsigned char appStatusB3; - unsigned char appStatusB2; - unsigned char appStatusB1; - unsigned char appStatusB0; - unsigned char protocolStatus; - unsigned char reserved[3]; -} fcgi_end_request; - -typedef struct _fcgi_end_request_rec { - fcgi_header hdr; - fcgi_end_request body; -} fcgi_end_request_rec; - -/* FastCGI client API */ - -typedef struct _fcgi_request { - int listen_socket; -#ifdef _WIN32 - int tcp; -#endif - int fd; - int id; - int keep; - int closed; - - int in_len; - int in_pad; - - fcgi_header *out_hdr; - unsigned char *out_pos; - unsigned char out_buf[1024*8]; - unsigned char reserved[sizeof(fcgi_end_request_rec)]; - - HashTable *env; -} fcgi_request; - -int fcgi_init(void); -void fcgi_shutdown(void); -void fcgi_init_request(fcgi_request *req, int listen_socket); -int fcgi_accept_request(fcgi_request *req); -int fcgi_finish_request(fcgi_request *req, int force_close); - -void fcgi_set_in_shutdown(int); -void fcgi_set_allowed_clients(char *); -void fcgi_close(fcgi_request *req, int force, int destroy); - -char* fcgi_getenv(fcgi_request *req, const char* var, int var_len); -char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val); - -int fcgi_read(fcgi_request *req, char *str, int len); - -ssize_t fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len); -int fcgi_flush(fcgi_request *req, int close); - -void fcgi_set_mgmt_var(const char * name, size_t name_len, const char * value, size_t value_len); -void fcgi_free_mgmt_var_cb(void * ptr); - -const char *fcgi_get_last_client_ip(); - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/sapi/fpm/fpm/fpm.c b/sapi/fpm/fpm/fpm.c index 96a29c5f10..e43eb5a86d 100644 --- a/sapi/fpm/fpm/fpm.c +++ b/sapi/fpm/fpm/fpm.c @@ -24,7 +24,7 @@ #include "zlog.h" struct fpm_globals_s fpm_globals = { - .parent_pid = 0, + .parent_pid = 0, .argc = 0, .argv = NULL, .config = NULL, diff --git a/sapi/fpm/fpm/fpm_conf.c b/sapi/fpm/fpm/fpm_conf.c index d812452e43..9a619ce887 100644 --- a/sapi/fpm/fpm/fpm_conf.c +++ b/sapi/fpm/fpm/fpm_conf.c @@ -55,7 +55,7 @@ #define GO(field) offsetof(struct fpm_global_config_s, field) #define WPO(field) offsetof(struct fpm_worker_pool_config_s, field) -static int fpm_conf_load_ini_file(char *filename TSRMLS_DC); +static int fpm_conf_load_ini_file(char *filename); static char *fpm_conf_set_integer(zval *value, void **config, intptr_t offset); #if 0 /* not used for now */ static char *fpm_conf_set_long(zval *value, void **config, intptr_t offset); @@ -88,7 +88,7 @@ static char *ini_filename = NULL; static int ini_lineno = 0; static char *ini_include = NULL; -/* +/* * Please keep the same order as in fpm_conf.h and in php-fpm.conf.in */ static struct ini_value_parser_s ini_fpm_global_options[] = { @@ -114,7 +114,7 @@ static struct ini_value_parser_s ini_fpm_global_options[] = { { 0, 0, 0 } }; -/* +/* * Please keep the same order as in fpm_conf.h and in php-fpm.conf.in */ static struct ini_value_parser_s ini_fpm_pool_options[] = { @@ -510,7 +510,7 @@ static char *fpm_conf_set_rlimit_core(zval *value, void **config, intptr_t offse error = fpm_conf_set_integer(value, &subconf, 0); - if (error) { + if (error) { return error; } @@ -604,7 +604,7 @@ static void *fpm_worker_pool_config_alloc() /* {{{ */ wp->config = malloc(sizeof(struct fpm_worker_pool_config_s)); - if (!wp->config) { + if (!wp->config) { fpm_worker_pool_free(wp); return 0; } @@ -1151,7 +1151,7 @@ int fpm_conf_write_pid() /* {{{ */ } /* }}} */ -static int fpm_conf_post_process(int force_daemon TSRMLS_DC) /* {{{ */ +static int fpm_conf_post_process(int force_daemon) /* {{{ */ { struct fpm_worker_pool_s *wp; @@ -1222,7 +1222,7 @@ static int fpm_conf_post_process(int force_daemon TSRMLS_DC) /* {{{ */ if (!wp->config->access_log || !*wp->config->access_log) { continue; } - if (0 > fpm_log_write(wp->config->access_format TSRMLS_CC)) { + if (0 > fpm_log_write(wp->config->access_format)) { zlog(ZLOG_ERROR, "[pool %s] wrong format for access.format '%s'", wp->config->name, wp->config->access_format); return -1; } @@ -1247,7 +1247,7 @@ static void fpm_conf_cleanup(int which, void *arg) /* {{{ */ } /* }}} */ -static void fpm_conf_ini_parser_include(char *inc, void *arg TSRMLS_DC) /* {{{ */ +static void fpm_conf_ini_parser_include(char *inc, void *arg) /* {{{ */ { char *filename; int *error = (int *)arg;; @@ -1258,7 +1258,7 @@ static void fpm_conf_ini_parser_include(char *inc, void *arg TSRMLS_DC) /* {{{ * if (!inc || !arg) return; if (*error) return; /* We got already an error. Switch to the end. */ - spprintf(&filename, 0, "%s", ini_filename); + spprintf(&filename, 0, "%s", ini_filename); #ifdef HAVE_GLOB { @@ -1269,7 +1269,7 @@ static void fpm_conf_ini_parser_include(char *inc, void *arg TSRMLS_DC) /* {{{ * zlog(ZLOG_WARNING, "Nothing matches the include pattern '%s' from %s at line %d.", inc, filename, ini_lineno); efree(filename); return; - } + } #endif /* GLOB_NOMATCH */ zlog(ZLOG_ERROR, "Unable to globalize '%s' (ret=%d) from %s at line %d.", inc, i, filename, ini_lineno); *error = 1; @@ -1281,7 +1281,7 @@ static void fpm_conf_ini_parser_include(char *inc, void *arg TSRMLS_DC) /* {{{ * int len = strlen(g.gl_pathv[i]); if (len < 1) continue; if (g.gl_pathv[i][len - 1] == '/') continue; /* don't parse directories */ - if (0 > fpm_conf_load_ini_file(g.gl_pathv[i] TSRMLS_CC)) { + if (0 > fpm_conf_load_ini_file(g.gl_pathv[i])) { zlog(ZLOG_ERROR, "Unable to include %s from %s at line %d", g.gl_pathv[i], filename, ini_lineno); *error = 1; efree(filename); @@ -1291,7 +1291,7 @@ static void fpm_conf_ini_parser_include(char *inc, void *arg TSRMLS_DC) /* {{{ * globfree(&g); } #else /* HAVE_GLOB */ - if (0 > fpm_conf_load_ini_file(inc TSRMLS_CC)) { + if (0 > fpm_conf_load_ini_file(inc)) { zlog(ZLOG_ERROR, "Unable to include %s from %s at line %d", inc, filename, ini_lineno); *error = 1; efree(filename); @@ -1303,7 +1303,7 @@ static void fpm_conf_ini_parser_include(char *inc, void *arg TSRMLS_DC) /* {{{ * } /* }}} */ -static void fpm_conf_ini_parser_section(zval *section, void *arg TSRMLS_DC) /* {{{ */ +static void fpm_conf_ini_parser_section(zval *section, void *arg) /* {{{ */ { struct fpm_worker_pool_s *wp; struct fpm_worker_pool_config_s *config; @@ -1341,7 +1341,7 @@ static void fpm_conf_ini_parser_section(zval *section, void *arg TSRMLS_DC) /* { } /* }}} */ -static void fpm_conf_ini_parser_entry(zval *name, zval *value, void *arg TSRMLS_DC) /* {{{ */ +static void fpm_conf_ini_parser_entry(zval *name, zval *value, void *arg) /* {{{ */ { struct ini_value_parser_s *parser; void *config = NULL; @@ -1398,7 +1398,7 @@ static void fpm_conf_ini_parser_entry(zval *name, zval *value, void *arg TSRMLS_ } /* }}} */ -static void fpm_conf_ini_parser_array(zval *name, zval *key, zval *value, void *arg TSRMLS_DC) /* {{{ */ +static void fpm_conf_ini_parser_array(zval *name, zval *key, zval *value, void *arg) /* {{{ */ { int *error = (int *)arg; char *err = NULL; @@ -1454,7 +1454,7 @@ static void fpm_conf_ini_parser_array(zval *name, zval *key, zval *value, void * } /* }}} */ -static void fpm_conf_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback_type, void *arg TSRMLS_DC) /* {{{ */ +static void fpm_conf_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback_type, void *arg) /* {{{ */ { int *error; @@ -1464,13 +1464,13 @@ static void fpm_conf_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback switch(callback_type) { case ZEND_INI_PARSER_ENTRY: - fpm_conf_ini_parser_entry(arg1, arg2, error TSRMLS_CC); + fpm_conf_ini_parser_entry(arg1, arg2, error); break;; case ZEND_INI_PARSER_SECTION: - fpm_conf_ini_parser_section(arg1, error TSRMLS_CC); + fpm_conf_ini_parser_section(arg1, error); break;; case ZEND_INI_PARSER_POP_ENTRY: - fpm_conf_ini_parser_array(arg1, arg3, arg2, error TSRMLS_CC); + fpm_conf_ini_parser_array(arg1, arg3, arg2, error); break;; default: zlog(ZLOG_ERROR, "[%s:%d] Unknown INI syntax", ini_filename, ini_lineno); @@ -1480,10 +1480,11 @@ static void fpm_conf_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback } /* }}} */ -int fpm_conf_load_ini_file(char *filename TSRMLS_DC) /* {{{ */ +int fpm_conf_load_ini_file(char *filename) /* {{{ */ { int error = 0; - char buf[1024+1]; + char *buf = NULL, *newbuf = NULL; + int bufsize = 0; int fd, n; int nb_read = 1; char c = '*'; @@ -1510,40 +1511,58 @@ int fpm_conf_load_ini_file(char *filename TSRMLS_DC) /* {{{ */ ini_lineno = 0; while (nb_read > 0) { int tmp; - memset(buf, 0, sizeof(char) * (1024 + 1)); - for (n = 0; n < 1024 && (nb_read = read(fd, &c, sizeof(char))) == sizeof(char) && c != '\n'; n++) { + ini_lineno++; + ini_filename = filename; + for (n = 0; (nb_read = read(fd, &c, sizeof(char))) == sizeof(char) && c != '\n'; n++) { + if (n == bufsize) { + bufsize += 1024; + newbuf = (char*) realloc(buf, sizeof(char) * (bufsize + 2)); + if (newbuf == NULL) { + ini_recursion--; + close(fd); + free(buf); + return -1; + } + buf = newbuf; + } + buf[n] = c; } + if (n == 0) { + continue; + } + /* always append newline and null terminate */ buf[n++] = '\n'; - ini_lineno++; - ini_filename = filename; - tmp = zend_parse_ini_string(buf, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t)fpm_conf_ini_parser, &error TSRMLS_CC); + buf[n] = '\0'; + tmp = zend_parse_ini_string(buf, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t)fpm_conf_ini_parser, &error); ini_filename = filename; if (error || tmp == FAILURE) { if (ini_include) free(ini_include); ini_recursion--; close(fd); + free(buf); return -1; } if (ini_include) { char *tmp = ini_include; ini_include = NULL; fpm_evaluate_full_path(&tmp, NULL, NULL, 0); - fpm_conf_ini_parser_include(tmp, &error TSRMLS_CC); + fpm_conf_ini_parser_include(tmp, &error); if (error) { free(tmp); ini_recursion--; close(fd); + free(buf); return -1; } free(tmp); } } + free(buf); ini_recursion--; close(fd); return ret; - } /* }}} */ @@ -1644,7 +1663,6 @@ static void fpm_conf_dump() /* {{{ */ int fpm_conf_init_main(int test_conf, int force_daemon) /* {{{ */ { int ret; - TSRMLS_FETCH(); if (fpm_globals.prefix && *fpm_globals.prefix) { if (!fpm_conf_is_dir(fpm_globals.prefix)) { @@ -1680,14 +1698,14 @@ int fpm_conf_init_main(int test_conf, int force_daemon) /* {{{ */ } } - ret = fpm_conf_load_ini_file(fpm_globals.config TSRMLS_CC); + ret = fpm_conf_load_ini_file(fpm_globals.config); if (0 > ret) { zlog(ZLOG_ERROR, "failed to load configuration file '%s'", fpm_globals.config); return -1; } - if (0 > fpm_conf_post_process(force_daemon TSRMLS_CC)) { + if (0 > fpm_conf_post_process(force_daemon)) { zlog(ZLOG_ERROR, "failed to post process the configuration"); return -1; } diff --git a/sapi/fpm/fpm/fpm_env.c b/sapi/fpm/fpm/fpm_env.c index 3bdb346341..73affab236 100644 --- a/sapi/fpm/fpm/fpm_env.c +++ b/sapi/fpm/fpm/fpm_env.c @@ -32,7 +32,7 @@ int setenv(char *name, char *value, int clobber) /* {{{ */ if (clobber == 0 && getenv(name) != 0) { return 0; } - + if ((cp = malloc(strlen(name) + strlen(value) + 2)) == 0) { return 1; } @@ -106,11 +106,11 @@ static char * nvmatch(char *s1, char *s2) /* {{{ */ { while(*s1 == *s2++) { - if(*s1++ == '=') { + if(*s1++ == '=') { return s2; } } - if(*s1 == '\0' && *(s2-1) == '=') { + if(*s1 == '\0' && *(s2-1) == '=') { return s2; } return NULL; @@ -270,7 +270,7 @@ int fpm_env_init_main() /* {{{ */ #endif spprintf(&title, 0, "master process (%s)", fpm_globals.config); - fpm_env_setproctitle(title); + fpm_env_setproctitle(title); efree(title); return 0; } diff --git a/sapi/fpm/fpm/fpm_events.c b/sapi/fpm/fpm/fpm_events.c index ce5d543f9b..ca45cb1665 100644 --- a/sapi/fpm/fpm/fpm_events.c +++ b/sapi/fpm/fpm/fpm_events.c @@ -171,7 +171,7 @@ static int fpm_event_queue_add(struct fpm_event_queue_s **queue, struct fpm_even module->add(ev); } - return 0; + return 0; } /* }}} */ @@ -464,7 +464,7 @@ void fpm_event_fire(struct fpm_event_s *ev) /* {{{ */ return; } - (*ev->callback)( (struct fpm_event_s *) ev, ev->which, ev->arg); + (*ev->callback)( (struct fpm_event_s *) ev, ev->which, ev->arg); } /* }}} */ diff --git a/sapi/fpm/fpm/fpm_log.c b/sapi/fpm/fpm/fpm_log.c index 187fe9bd07..5aad9a08c9 100644 --- a/sapi/fpm/fpm/fpm_log.c +++ b/sapi/fpm/fpm/fpm_log.c @@ -34,14 +34,14 @@ int fpm_log_open(int reopen) /* {{{ */ { struct fpm_worker_pool_s *wp; int ret = 1; - + int fd; for (wp = fpm_worker_all_pools; wp; wp = wp->next) { if (!wp->config->access_log) { continue; } ret = 0; - + fd = open(wp->config->access_log, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR); if (0 > fd) { zlog(ZLOG_SYSERROR, "failed to open access log (%s)", wp->config->access_log); @@ -97,7 +97,7 @@ int fpm_log_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ } /* }}} */ -int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */ +int fpm_log_write(char *log_format) /* {{{ */ { char *s, *b; char buffer[FPM_LOG_BUFFER+1]; @@ -410,7 +410,7 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */ { char *start; size_t l; - + start = ++s; while (*s != '\0') { diff --git a/sapi/fpm/fpm/fpm_log.h b/sapi/fpm/fpm/fpm_log.h index f0199d9cb6..d85d368da5 100644 --- a/sapi/fpm/fpm/fpm_log.h +++ b/sapi/fpm/fpm/fpm_log.h @@ -7,7 +7,7 @@ #include "fpm_worker_pool.h" int fpm_log_init_child(struct fpm_worker_pool_s *wp); -int fpm_log_write(char *log_format TSRMLS_DC); +int fpm_log_write(char *log_format); int fpm_log_open(int reopen); #endif diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c index d12ac01859..940d6c788d 100644 --- a/sapi/fpm/fpm/fpm_main.c +++ b/sapi/fpm/fpm/fpm_main.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -93,10 +93,11 @@ int __riscosify_control = __RISCOSIFY_STRICT_UNIX_SPECS; #include "zend_compile.h" #include "zend_execute.h" #include "zend_highlight.h" -#include "zend_indent.h" #include "php_getopt.h" +#include "http_status_codes.h" + #include "fastcgi.h" #include <php_config.h> @@ -113,7 +114,7 @@ int __riscosify_control = __RISCOSIFY_STRICT_UNIX_SPECS; struct sigaction act, old_term, old_quit, old_int; #endif -static void (*php_php_import_environment_variables)(zval *array_ptr TSRMLS_DC); +static void (*php_php_import_environment_variables)(zval *array_ptr); #ifndef PHP_WIN32 /* these globals used for forking children on unix systems */ @@ -127,8 +128,8 @@ static int parent = 1; static int request_body_fd; static int fpm_is_running = 0; -static char *sapi_cgibin_getenv(char *name, size_t name_len TSRMLS_DC); -static void fastcgi_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback_type, void *arg TSRMLS_DC); +static char *sapi_cgibin_getenv(char *name, size_t name_len); +static void fastcgi_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback_type, void *arg); #define PHP_MODE_STANDARD 1 #define PHP_MODE_HIGHLIGHT 2 @@ -188,10 +189,12 @@ typedef struct _user_config_cache_entry { HashTable *user_config; } user_config_cache_entry; -static void user_config_cache_entry_dtor(user_config_cache_entry *entry) +static void user_config_cache_entry_dtor(zval *el) { + user_config_cache_entry *entry = (user_config_cache_entry *)Z_PTR_P(el); zend_hash_destroy(entry->user_config); free(entry->user_config); + free(entry); } /* }}} */ @@ -216,61 +219,67 @@ static php_cgi_globals_struct php_cgi_globals; #define TRANSLATE_SLASHES(path) #endif -static int print_module_info(zend_module_entry *module, void *arg TSRMLS_DC) +static int print_module_info(zval *zv) /* {{{ */ { + zend_module_entry *module = Z_PTR_P(zv); php_printf("%s\n", module->name); return 0; } +/* }}} */ -static int module_name_cmp(const void *a, const void *b TSRMLS_DC) +static int module_name_cmp(const void *a, const void *b) /* {{{ */ { - Bucket *f = *((Bucket **) a); - Bucket *s = *((Bucket **) b); + Bucket *f = (Bucket *) a; + Bucket *s = (Bucket *) b; - return strcasecmp( ((zend_module_entry *)f->pData)->name, - ((zend_module_entry *)s->pData)->name); + return strcasecmp( ((zend_module_entry *) Z_PTR(f->val))->name, + ((zend_module_entry *) Z_PTR(s->val))->name); } +/* }}} */ -static void print_modules(TSRMLS_D) +static void print_modules(void) /* {{{ */ { HashTable sorted_registry; - zend_module_entry tmp; zend_hash_init(&sorted_registry, 50, NULL, NULL, 1); - zend_hash_copy(&sorted_registry, &module_registry, NULL, &tmp, sizeof(zend_module_entry)); - zend_hash_sort(&sorted_registry, zend_qsort, module_name_cmp, 0 TSRMLS_CC); - zend_hash_apply_with_argument(&sorted_registry, (apply_func_arg_t) print_module_info, NULL TSRMLS_CC); + zend_hash_copy(&sorted_registry, &module_registry, NULL); + zend_hash_sort(&sorted_registry, module_name_cmp, 0); + zend_hash_apply(&sorted_registry, print_module_info); zend_hash_destroy(&sorted_registry); } +/* }}} */ -static int print_extension_info(zend_extension *ext, void *arg TSRMLS_DC) +static int print_extension_info(zend_extension *ext, void *arg) /* {{{ */ { php_printf("%s\n", ext->name); return 0; } +/* }}} */ -static int extension_name_cmp(const zend_llist_element **f, const zend_llist_element **s TSRMLS_DC) +static int extension_name_cmp(const zend_llist_element **f, const zend_llist_element **s) /* {{{ */ { return strcmp( ((zend_extension *)(*f)->data)->name, ((zend_extension *)(*s)->data)->name); } +/* }}} */ -static void print_extensions(TSRMLS_D) +static void print_extensions(void) /* {{{ */ { zend_llist sorted_exts; zend_llist_copy(&sorted_exts, &zend_extensions); sorted_exts.dtor = NULL; - zend_llist_sort(&sorted_exts, extension_name_cmp TSRMLS_CC); - zend_llist_apply_with_argument(&sorted_exts, (llist_apply_with_arg_func_t) print_extension_info, NULL TSRMLS_CC); + zend_llist_sort(&sorted_exts, extension_name_cmp); + zend_llist_apply_with_argument(&sorted_exts, (llist_apply_with_arg_func_t) print_extension_info, NULL); zend_llist_destroy(&sorted_exts); } +/* }}} */ -#ifndef STDOUT_FILENO -#define STDOUT_FILENO 1 +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 #endif -static inline size_t sapi_cgibin_single_write(const char *str, uint str_length TSRMLS_DC) +static inline size_t sapi_cgibin_single_write(const char *str, uint str_length) /* {{{ */ { ssize_t ret; @@ -285,8 +294,8 @@ static inline size_t sapi_cgibin_single_write(const char *str, uint str_length T } /* sapi has not started, output to stdout instead of fcgi */ -#ifdef PHP_WRITE_STDOUT - ret = write(STDOUT_FILENO, str, str_length); +#ifdef PHP_WRITE_STDOUT + ret = write(STDOUT_FILENO, str, str_length); if (ret <= 0) { return 0; } @@ -295,15 +304,16 @@ static inline size_t sapi_cgibin_single_write(const char *str, uint str_length T return fwrite(str, 1, MIN(str_length, 16384), stdout); #endif } +/* }}} */ -static int sapi_cgibin_ub_write(const char *str, uint str_length TSRMLS_DC) +static size_t sapi_cgibin_ub_write(const char *str, size_t str_length) /* {{{ */ { const char *ptr = str; uint remaining = str_length; size_t ret; while (remaining > 0) { - ret = sapi_cgibin_single_write(ptr, remaining TSRMLS_CC); + ret = sapi_cgibin_single_write(ptr, remaining); if (!ret) { php_handle_aborted_connection(); return str_length - remaining; @@ -314,9 +324,9 @@ static int sapi_cgibin_ub_write(const char *str, uint str_length TSRMLS_DC) return str_length; } +/* }}} */ - -static void sapi_cgibin_flush(void *server_context) +static void sapi_cgibin_flush(void *server_context) /* {{{ */ { /* fpm has started, let use fcgi instead of stdout */ if (fpm_is_running) { @@ -336,61 +346,11 @@ static void sapi_cgibin_flush(void *server_context) php_handle_aborted_connection(); } } +/* }}} */ #define SAPI_CGI_MAX_HEADER_LENGTH 1024 -typedef struct _http_error { - int code; - const char* msg; -} http_error; - -static const http_error http_error_codes[] = { - {100, "Continue"}, - {101, "Switching Protocols"}, - {200, "OK"}, - {201, "Created"}, - {202, "Accepted"}, - {203, "Non-Authoritative Information"}, - {204, "No Content"}, - {205, "Reset Content"}, - {206, "Partial Content"}, - {300, "Multiple Choices"}, - {301, "Moved Permanently"}, - {302, "Moved Temporarily"}, - {303, "See Other"}, - {304, "Not Modified"}, - {305, "Use Proxy"}, - {400, "Bad Request"}, - {401, "Unauthorized"}, - {402, "Payment Required"}, - {403, "Forbidden"}, - {404, "Not Found"}, - {405, "Method Not Allowed"}, - {406, "Not Acceptable"}, - {407, "Proxy Authentication Required"}, - {408, "Request Time-out"}, - {409, "Conflict"}, - {410, "Gone"}, - {411, "Length Required"}, - {412, "Precondition Failed"}, - {413, "Request Entity Too Large"}, - {414, "Request-URI Too Large"}, - {415, "Unsupported Media Type"}, - {428, "Precondition Required"}, - {429, "Too Many Requests"}, - {431, "Request Header Fields Too Large"}, - {451, "Unavailable For Legal Reasons"}, - {500, "Internal Server Error"}, - {501, "Not Implemented"}, - {502, "Bad Gateway"}, - {503, "Service Unavailable"}, - {504, "Gateway Time-out"}, - {505, "HTTP Version not supported"}, - {511, "Network Authentication Required"}, - {0, NULL} -}; - -static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) +static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers) /* {{{ */ { char buf[SAPI_CGI_MAX_HEADER_LENGTH]; sapi_header_struct *h; @@ -440,7 +400,7 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos); } if (!has_status) { - http_error *err = (http_error*)http_error_codes; + http_response_status_code_pair *err = (http_response_status_code_pair*)http_status_map; while (err->code != 0) { if (err->code == SG(sapi_headers).http_response_code) { @@ -448,8 +408,8 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) } err++; } - if (err->msg) { - len = slprintf(buf, sizeof(buf), "Status: %d %s\r\n", SG(sapi_headers).http_response_code, err->msg); + if (err->str) { + len = slprintf(buf, sizeof(buf), "Status: %d %s\r\n", SG(sapi_headers).http_response_code, err->str); } else { len = slprintf(buf, sizeof(buf), "Status: %d\r\n", SG(sapi_headers).http_response_code); } @@ -467,7 +427,7 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) while (h) { /* prevent CRLFCRLF */ if (h->header_len) { - if (h->header_len > sizeof("Status:") - 1 && + if (h->header_len > sizeof("Status:") - 1 && strncasecmp(h->header, "Status:", sizeof("Status:") - 1) == 0 ) { if (!ignore_status) { @@ -491,12 +451,26 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) return SAPI_HEADER_SENT_SUCCESSFULLY; } +/* }}} */ #ifndef STDIN_FILENO # define STDIN_FILENO 0 #endif -static int sapi_cgi_read_post(char *buffer, uint count_bytes TSRMLS_DC) +#ifndef HAVE_ATTRIBUTE_WEAK +static void fpm_fcgi_log(int type, const char *fmt, ...) /* {{{ */ +#else +void fcgi_log(int type, const char *fmt, ...) +#endif +{ + va_list args; + va_start(args, fmt); + vzlog("", 0, type, fmt, args); + va_end(args); +} +/* }}} */ + +static size_t sapi_cgi_read_post(char *buffer, size_t count_bytes) /* {{{ */ { uint read_bytes = 0; int tmp_read_bytes; @@ -508,8 +482,7 @@ static int sapi_cgi_read_post(char *buffer, uint count_bytes TSRMLS_DC) while (read_bytes < count_bytes) { fcgi_request *request = (fcgi_request*) SG(server_context); if (request_body_fd == -1) { - char *request_body_filename = sapi_cgibin_getenv((char *) "REQUEST_BODY_FILE", - sizeof("REQUEST_BODY_FILE") - 1 TSRMLS_CC); + char *request_body_filename = FCGI_GETENV(request, "REQUEST_BODY_FILE"); if (request_body_filename && *request_body_filename) { request_body_fd = open(request_body_filename, O_RDONLY); @@ -535,8 +508,9 @@ static int sapi_cgi_read_post(char *buffer, uint count_bytes TSRMLS_DC) } return read_bytes; } +/* }}} */ -static char *sapi_cgibin_getenv(char *name, size_t name_len TSRMLS_DC) +static char *sapi_cgibin_getenv(char *name, size_t name_len) /* {{{ */ { /* if fpm has started, use fcgi env */ if (fpm_is_running) { @@ -547,8 +521,10 @@ static char *sapi_cgibin_getenv(char *name, size_t name_len TSRMLS_DC) /* if fpm has not started yet, use std env */ return getenv(name); } +/* }}} */ -static char *_sapi_cgibin_putenv(char *name, char *value TSRMLS_DC) +#if 0 +static char *_sapi_cgibin_putenv(char *name, char *value) /* {{{ */ { int name_len; @@ -560,77 +536,71 @@ static char *_sapi_cgibin_putenv(char *name, char *value TSRMLS_DC) fcgi_request *request = (fcgi_request*) SG(server_context); return fcgi_putenv(request, name, name_len, value); } +/* }}} */ +#endif -static char *sapi_cgi_read_cookies(TSRMLS_D) +static char *sapi_cgi_read_cookies(void) /* {{{ */ { - return sapi_cgibin_getenv((char *) "HTTP_COOKIE", sizeof("HTTP_COOKIE") - 1 TSRMLS_CC); + fcgi_request *request = (fcgi_request*) SG(server_context); + + return FCGI_GETENV(request, "HTTP_COOKIE"); } +/* }}} */ -void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC) +static void cgi_php_load_env_var(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg) /* {{{ */ { - fcgi_request *request; - HashPosition pos; - char *var, **val; - uint var_len; - ulong idx; - int filter_arg; + zval *array_ptr = (zval*)arg; + int filter_arg = (Z_ARR_P(array_ptr) == Z_ARR(PG(http_globals)[TRACK_VARS_ENV]))?PARSE_ENV:PARSE_SERVER; + size_t new_val_len; + + if (sapi_module.input_filter(filter_arg, var, &val, strlen(val), &new_val_len)) { + php_register_variable_safe(var, val, new_val_len, array_ptr); + } +} +/* }}} */ +void cgi_php_import_environment_variables(zval *array_ptr) /* {{{ */ +{ + fcgi_request *request = NULL; - if (PG(http_globals)[TRACK_VARS_ENV] && - array_ptr != PG(http_globals)[TRACK_VARS_ENV] && - Z_TYPE_P(PG(http_globals)[TRACK_VARS_ENV]) == IS_ARRAY && - zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_ENV])) > 0 + if (Z_TYPE(PG(http_globals)[TRACK_VARS_ENV]) == IS_ARRAY && + Z_ARR_P(array_ptr) != Z_ARR(PG(http_globals)[TRACK_VARS_ENV]) && + zend_hash_num_elements(Z_ARRVAL(PG(http_globals)[TRACK_VARS_ENV])) > 0 ) { zval_dtor(array_ptr); - *array_ptr = *PG(http_globals)[TRACK_VARS_ENV]; - INIT_PZVAL(array_ptr); - zval_copy_ctor(array_ptr); + ZVAL_DUP(array_ptr, &PG(http_globals)[TRACK_VARS_ENV]); return; - } else if (PG(http_globals)[TRACK_VARS_SERVER] && - array_ptr != PG(http_globals)[TRACK_VARS_SERVER] && - Z_TYPE_P(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY && - zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER])) > 0 + } else if (Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY && + Z_ARR_P(array_ptr) != Z_ARR(PG(http_globals)[TRACK_VARS_SERVER]) && + zend_hash_num_elements(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER])) > 0 ) { zval_dtor(array_ptr); - *array_ptr = *PG(http_globals)[TRACK_VARS_SERVER]; - INIT_PZVAL(array_ptr); - zval_copy_ctor(array_ptr); + ZVAL_DUP(array_ptr, &PG(http_globals)[TRACK_VARS_SERVER]); return; } /* call php's original import as a catch-all */ - php_php_import_environment_variables(array_ptr TSRMLS_CC); + php_php_import_environment_variables(array_ptr); request = (fcgi_request*) SG(server_context); - filter_arg = (array_ptr == PG(http_globals)[TRACK_VARS_ENV])?PARSE_ENV:PARSE_SERVER; - - for (zend_hash_internal_pointer_reset_ex(request->env, &pos); - zend_hash_get_current_key_ex(request->env, &var, &var_len, &idx, 0, &pos) == HASH_KEY_IS_STRING && - zend_hash_get_current_data_ex(request->env, (void **) &val, &pos) == SUCCESS; - zend_hash_move_forward_ex(request->env, &pos) - ) { - unsigned int new_val_len; - - if (sapi_module.input_filter(filter_arg, var, val, strlen(*val), &new_val_len TSRMLS_CC)) { - php_register_variable_safe(var, *val, new_val_len, array_ptr TSRMLS_CC); - } - } + fcgi_loadenv(request, cgi_php_load_env_var, array_ptr); } +/* }}} */ -static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC) +static void sapi_cgi_register_variables(zval *track_vars_array) /* {{{ */ { - unsigned int php_self_len; + size_t php_self_len; char *php_self; /* In CGI mode, we consider the environment to be a part of the server * variables */ - php_import_environment_variables(track_vars_array TSRMLS_CC); + php_import_environment_variables(track_vars_array); if (CGIG(fix_pathinfo)) { char *script_name = SG(request_info).request_uri; unsigned int script_name_len = script_name ? strlen(script_name) : 0; - char *path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO") - 1 TSRMLS_CC); + char *path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO") - 1); unsigned int path_info_len = path_info ? strlen(path_info) : 0; php_self_len = script_name_len + path_info_len; @@ -645,18 +615,19 @@ static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC) } /* Build the special-case PHP_SELF variable for the CGI version */ - if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len TSRMLS_CC)) { - php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array TSRMLS_CC); + if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len)) { + php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array); } efree(php_self); } else { php_self = SG(request_info).request_uri ? SG(request_info).request_uri : ""; php_self_len = strlen(php_self); - if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len TSRMLS_CC)) { - php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array TSRMLS_CC); + if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len)) { + php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array); } } } +/* }}} */ /* {{{ sapi_cgi_log_fastcgi * @@ -664,7 +635,6 @@ static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC) */ void sapi_cgi_log_fastcgi(int level, char *message, size_t len) { - TSRMLS_FETCH(); fcgi_request *request = (fcgi_request*) SG(server_context); @@ -697,20 +667,19 @@ static void sapi_cgi_log_message(char *message) /* {{{ php_cgi_ini_activate_user_config */ -static void php_cgi_ini_activate_user_config(char *path, int path_len, const char *doc_root, int doc_root_len, int start TSRMLS_DC) +static void php_cgi_ini_activate_user_config(char *path, int path_len, const char *doc_root, int doc_root_len, int start) { char *ptr; - user_config_cache_entry *new_entry, *entry; - time_t request_time = sapi_get_request_time(TSRMLS_C); + time_t request_time = sapi_get_request_time(); + user_config_cache_entry *entry = zend_hash_str_find_ptr(&CGIG(user_config_cache), path, path_len); /* Find cached config entry: If not found, create one */ - if (zend_hash_find(&CGIG(user_config_cache), path, path_len + 1, (void **) &entry) == FAILURE) { - new_entry = pemalloc(sizeof(user_config_cache_entry), 1); - new_entry->expires = 0; - new_entry->user_config = (HashTable *) pemalloc(sizeof(HashTable), 1); - zend_hash_init(new_entry->user_config, 0, NULL, (dtor_func_t) config_zval_dtor, 1); - zend_hash_update(&CGIG(user_config_cache), path, path_len + 1, new_entry, sizeof(user_config_cache_entry), (void **) &entry); - free(new_entry); + if (!entry) { + entry = pemalloc(sizeof(user_config_cache_entry), 1); + entry->expires = 0; + entry->user_config = (HashTable *) pemalloc(sizeof(HashTable), 1); + zend_hash_init(entry->user_config, 0, NULL, config_zval_dtor, 1); + zend_hash_str_update_ptr(&CGIG(user_config_cache), path, path_len, entry); } /* Check whether cache entry has expired and rescan if it is */ @@ -724,7 +693,7 @@ static void php_cgi_ini_activate_user_config(char *path, int path_len, const cha zend_hash_clean(entry->user_config); if (!IS_ABSOLUTE_PATH(path, path_len)) { - real_path = tsrm_realpath(path, NULL TSRMLS_CC); + real_path = tsrm_realpath(path, NULL); if (real_path == NULL) { return; } @@ -744,35 +713,36 @@ static void php_cgi_ini_activate_user_config(char *path, int path_len, const cha } /* we have to test if path is part of DOCUMENT_ROOT. - if it is inside the docroot, we scan the tree up to the docroot + if it is inside the docroot, we scan the tree up to the docroot to find more user.ini, if not we only scan the current path. */ #ifdef PHP_WIN32 if (strnicmp(s1, s2, s_len) == 0) { -#else +#else if (strncmp(s1, s2, s_len) == 0) { #endif ptr = s2 + start; /* start is the point where doc_root ends! */ while ((ptr = strchr(ptr, DEFAULT_SLASH)) != NULL) { *ptr = 0; - php_parse_user_ini_file(path, PG(user_ini_filename), entry->user_config TSRMLS_CC); + php_parse_user_ini_file(path, PG(user_ini_filename), entry->user_config); *ptr = '/'; ptr++; } } else { - php_parse_user_ini_file(path, PG(user_ini_filename), entry->user_config TSRMLS_CC); + php_parse_user_ini_file(path, PG(user_ini_filename), entry->user_config); } entry->expires = request_time + PG(user_ini_cache_ttl); } /* Activate ini entries with values from the user config hash */ - php_ini_activate_config(entry->user_config, PHP_INI_PERDIR, PHP_INI_STAGE_HTACCESS TSRMLS_CC); + php_ini_activate_config(entry->user_config, PHP_INI_PERDIR, PHP_INI_STAGE_HTACCESS); } /* }}} */ -static int sapi_cgi_activate(TSRMLS_D) +static int sapi_cgi_activate(void) /* {{{ */ { + fcgi_request *request = (fcgi_request*) SG(server_context); char *path, *doc_root, *server_name; uint path_len, doc_root_len, server_name_len; @@ -783,13 +753,13 @@ static int sapi_cgi_activate(TSRMLS_D) if (php_ini_has_per_host_config()) { /* Activate per-host-system-configuration defined in php.ini and stored into configuration_hash during startup */ - server_name = sapi_cgibin_getenv("SERVER_NAME", sizeof("SERVER_NAME") - 1 TSRMLS_CC); + server_name = FCGI_GETENV(request, "SERVER_NAME"); /* SERVER_NAME should also be defined at this stage..but better check it anyway */ if (server_name) { server_name_len = strlen(server_name); server_name = estrndup(server_name, server_name_len); zend_str_tolower(server_name, server_name_len); - php_ini_activate_per_host_config(server_name, server_name_len + 1 TSRMLS_CC); + php_ini_activate_per_host_config(server_name, server_name_len); efree(server_name); } } @@ -813,11 +783,11 @@ static int sapi_cgi_activate(TSRMLS_D) path[path_len] = 0; /* Activate per-dir-system-configuration defined in php.ini and stored into configuration_hash during startup */ - php_ini_activate_per_dir_config(path, path_len TSRMLS_CC); /* Note: for global settings sake we check from root to path */ + php_ini_activate_per_dir_config(path, path_len); /* Note: for global settings sake we check from root to path */ /* Load and activate user ini files in path starting from DOCUMENT_ROOT */ if (PG(user_ini_filename) && *PG(user_ini_filename)) { - doc_root = sapi_cgibin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT") - 1 TSRMLS_CC); + doc_root = FCGI_GETENV(request, "DOCUMENT_ROOT"); /* DOCUMENT_ROOT should also be defined at this stage..but better check it anyway */ if (doc_root) { doc_root_len = strlen(doc_root); @@ -829,7 +799,7 @@ static int sapi_cgi_activate(TSRMLS_D) doc_root = estrndup(doc_root, doc_root_len); zend_str_tolower(doc_root, doc_root_len); #endif - php_cgi_ini_activate_user_config(path, path_len, doc_root, doc_root_len, doc_root_len - 1 TSRMLS_CC); + php_cgi_ini_activate_user_config(path, path_len, doc_root, doc_root_len, doc_root_len - 1); } } @@ -841,8 +811,9 @@ static int sapi_cgi_activate(TSRMLS_D) return SUCCESS; } +/* }}} */ -static int sapi_cgi_deactivate(TSRMLS_D) +static int sapi_cgi_deactivate(void) /* {{{ */ { /* flush only when SAPI was started. The reasons are: 1. SAPI Deactivate is called from two places: module init and request shutdown @@ -859,14 +830,16 @@ static int sapi_cgi_deactivate(TSRMLS_D) } return SUCCESS; } +/* }}} */ -static int php_cgi_startup(sapi_module_struct *sapi_module) +static int php_cgi_startup(sapi_module_struct *sapi_module) /* {{{ */ { if (php_module_startup(sapi_module, &cgi_module_entry, 1) == FAILURE) { return FAILURE; } return SUCCESS; } +/* }}} */ /* {{{ sapi_module_struct cgi_sapi_module */ @@ -903,17 +876,6 @@ static sapi_module_struct cgi_sapi_module = { }; /* }}} */ -/* {{{ arginfo ext/standard/dl.c */ -ZEND_BEGIN_ARG_INFO(arginfo_dl, 0) - ZEND_ARG_INFO(0, extension_filename) -ZEND_END_ARG_INFO() -/* }}} */ - -static const zend_function_entry additional_functions[] = { - ZEND_FE(dl, arginfo_dl) - {NULL, NULL, NULL} -}; - /* {{{ php_cgi_usage */ static void php_cgi_usage(char *argv0) @@ -1055,10 +1017,11 @@ static int is_valid_path(const char *path) Comments in the code below refer to using the above URL in a request */ -static void init_request_info(TSRMLS_D) +static void init_request_info(void) { - char *env_script_filename = sapi_cgibin_getenv("SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME") - 1 TSRMLS_CC); - char *env_path_translated = sapi_cgibin_getenv("PATH_TRANSLATED", sizeof("PATH_TRANSLATED") - 1 TSRMLS_CC); + fcgi_request *request = (fcgi_request*) SG(server_context); + char *env_script_filename = FCGI_GETENV(request, "SCRIPT_FILENAME"); + char *env_path_translated = FCGI_GETENV(request, "PATH_TRANSLATED"); char *script_path_translated = env_script_filename; char *ini; int apache_was_here = 0; @@ -1086,25 +1049,25 @@ static void init_request_info(TSRMLS_D) * of the script will be retreived later via argc/argv */ if (script_path_translated) { const char *auth; - char *content_length = sapi_cgibin_getenv("CONTENT_LENGTH", sizeof("CONTENT_LENGTH") - 1 TSRMLS_CC); - char *content_type = sapi_cgibin_getenv("CONTENT_TYPE", sizeof("CONTENT_TYPE") - 1 TSRMLS_CC); - char *env_path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO") - 1 TSRMLS_CC); - char *env_script_name = sapi_cgibin_getenv("SCRIPT_NAME", sizeof("SCRIPT_NAME") - 1 TSRMLS_CC); + char *content_length = FCGI_GETENV(request, "CONTENT_LENGTH"); + char *content_type = FCGI_GETENV(request, "CONTENT_TYPE"); + char *env_path_info = FCGI_GETENV(request, "PATH_INFO"); + char *env_script_name = FCGI_GETENV(request, "SCRIPT_NAME"); /* Hack for buggy IIS that sets incorrect PATH_INFO */ - char *env_server_software = sapi_cgibin_getenv("SERVER_SOFTWARE", sizeof("SERVER_SOFTWARE") - 1 TSRMLS_CC); + char *env_server_software = FCGI_GETENV(request, "SERVER_SOFTWARE"); if (env_server_software && env_script_name && env_path_info && strncmp(env_server_software, "Microsoft-IIS", sizeof("Microsoft-IIS") - 1) == 0 && strncmp(env_path_info, env_script_name, strlen(env_script_name)) == 0 ) { - env_path_info = _sapi_cgibin_putenv("ORIG_PATH_INFO", env_path_info TSRMLS_CC); + env_path_info = FCGI_PUTENV(request, "ORIG_PATH_INFO", env_path_info); env_path_info += strlen(env_script_name); if (*env_path_info == 0) { env_path_info = NULL; } - env_path_info = _sapi_cgibin_putenv("PATH_INFO", env_path_info TSRMLS_CC); + env_path_info = FCGI_PUTENV(request, "PATH_INFO", env_path_info); } #define APACHE_PROXY_FCGI_PREFIX "proxy:fcgi://" @@ -1163,8 +1126,8 @@ static void init_request_info(TSRMLS_D) if (CGIG(fix_pathinfo)) { struct stat st; char *real_path = NULL; - char *env_redirect_url = sapi_cgibin_getenv("REDIRECT_URL", sizeof("REDIRECT_URL") - 1 TSRMLS_CC); - char *env_document_root = sapi_cgibin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT") - 1 TSRMLS_CC); + char *env_redirect_url = FCGI_GETENV(request, "REDIRECT_URL"); + char *env_document_root = FCGI_GETENV(request, "DOCUMENT_ROOT"); char *orig_path_translated = env_path_translated; char *orig_path_info = env_path_info; char *orig_script_name = env_script_name; @@ -1172,7 +1135,7 @@ static void init_request_info(TSRMLS_D) int script_path_translated_len; if (!env_document_root && PG(doc_root)) { - env_document_root = _sapi_cgibin_putenv("DOCUMENT_ROOT", PG(doc_root) TSRMLS_CC); + env_document_root = FCGI_PUTENV(request, "DOCUMENT_ROOT", PG(doc_root)); /* fix docroot */ TRANSLATE_SLASHES(env_document_root); } @@ -1210,7 +1173,7 @@ static void init_request_info(TSRMLS_D) #ifdef PHP_WIN32 script_path_translated[script_path_translated_len-1] == '\\' || #endif - (real_path = tsrm_realpath(script_path_translated, NULL TSRMLS_CC)) == NULL) + (real_path = tsrm_realpath(script_path_translated, NULL)) == NULL) ) { char *pt = estrndup(script_path_translated, script_path_translated_len); int len = script_path_translated_len; @@ -1253,15 +1216,15 @@ static void init_request_info(TSRMLS_D) if (orig_path_info) { char old; - _sapi_cgibin_putenv("ORIG_PATH_INFO", orig_path_info TSRMLS_CC); + FCGI_PUTENV(request, "ORIG_PATH_INFO", orig_path_info); old = path_info[0]; path_info[0] = 0; if (!orig_script_name || strcmp(orig_script_name, env_path_info) != 0) { if (orig_script_name) { - _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC); + FCGI_PUTENV(request, "ORIG_SCRIPT_NAME", orig_script_name); } - SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_path_info TSRMLS_CC); + SG(request_info).request_uri = FCGI_PUTENV(request, "SCRIPT_NAME", env_path_info); } else { SG(request_info).request_uri = orig_script_name; } @@ -1273,19 +1236,19 @@ static void init_request_info(TSRMLS_D) */ int snlen = strlen(env_script_name); if (snlen>slen && !strcmp(env_script_name+snlen-slen, path_info)) { - _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC); + FCGI_PUTENV(request, "ORIG_SCRIPT_NAME", orig_script_name); env_script_name[snlen-slen] = 0; - SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name TSRMLS_CC); + SG(request_info).request_uri = FCGI_PUTENV(request, "SCRIPT_NAME", env_script_name); } } - env_path_info = _sapi_cgibin_putenv("PATH_INFO", path_info TSRMLS_CC); + env_path_info = FCGI_PUTENV(request, "PATH_INFO", path_info); } if (!orig_script_filename || strcmp(orig_script_filename, pt) != 0) { if (orig_script_filename) { - _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC); + FCGI_PUTENV(request, "ORIG_SCRIPT_FILENAME", orig_script_filename); } - script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", pt TSRMLS_CC); + script_path_translated = FCGI_PUTENV(request, "SCRIPT_FILENAME", pt); } TRANSLATE_SLASHES(pt); @@ -1315,9 +1278,9 @@ static void init_request_info(TSRMLS_D) } path_translated[path_translated_len] = '\0'; if (orig_path_translated) { - _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC); + FCGI_PUTENV(request, "ORIG_PATH_TRANSLATED", orig_path_translated); } - env_path_translated = _sapi_cgibin_putenv("PATH_TRANSLATED", path_translated TSRMLS_CC); + env_path_translated = FCGI_PUTENV(request, "PATH_TRANSLATED", path_translated); efree(path_translated); } else if ( env_script_name && strstr(pt, env_script_name) @@ -1334,9 +1297,9 @@ static void init_request_info(TSRMLS_D) } path_translated[path_translated_len] = '\0'; if (orig_path_translated) { - _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC); + FCGI_PUTENV(request, "ORIG_PATH_TRANSLATED", orig_path_translated); } - env_path_translated = _sapi_cgibin_putenv("PATH_TRANSLATED", path_translated TSRMLS_CC); + env_path_translated = FCGI_PUTENV(request, "PATH_TRANSLATED", path_translated); efree(path_translated); } break; @@ -1352,18 +1315,18 @@ static void init_request_info(TSRMLS_D) * have failed anyway... we output 'no input file' now. */ if (orig_script_filename) { - _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC); + FCGI_PUTENV(request, "ORIG_SCRIPT_FILENAME", orig_script_filename); } - script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", NULL TSRMLS_CC); + script_path_translated = FCGI_PUTENV(request, "SCRIPT_FILENAME", NULL); SG(sapi_headers).http_response_code = 404; } if (!SG(request_info).request_uri) { if (!orig_script_name || strcmp(orig_script_name, env_script_name) != 0) { if (orig_script_name) { - _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC); + FCGI_PUTENV(request, "ORIG_SCRIPT_NAME", orig_script_name); } - SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name TSRMLS_CC); + SG(request_info).request_uri = FCGI_PUTENV(request, "SCRIPT_NAME", env_script_name); } else { SG(request_info).request_uri = orig_script_name; } @@ -1377,27 +1340,27 @@ static void init_request_info(TSRMLS_D) (script_path_translated != orig_script_filename && strcmp(script_path_translated, orig_script_filename) != 0)) { if (orig_script_filename) { - _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC); + FCGI_PUTENV(request, "ORIG_SCRIPT_FILENAME", orig_script_filename); } - script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", script_path_translated TSRMLS_CC); + script_path_translated = FCGI_PUTENV(request, "SCRIPT_FILENAME", script_path_translated); } if (!apache_was_here && env_redirect_url) { /* if we used PATH_TRANSLATED to work around Apache mod_fastcgi (but not mod_proxy_fcgi, * hence !apache_was_here) weirdness, strip info accordingly */ if (orig_path_info) { - _sapi_cgibin_putenv("ORIG_PATH_INFO", orig_path_info TSRMLS_CC); - _sapi_cgibin_putenv("PATH_INFO", NULL TSRMLS_CC); + FCGI_PUTENV(request, "ORIG_PATH_INFO", orig_path_info); + FCGI_PUTENV(request, "PATH_INFO", NULL); } if (orig_path_translated) { - _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC); - _sapi_cgibin_putenv("PATH_TRANSLATED", NULL TSRMLS_CC); + FCGI_PUTENV(request, "ORIG_PATH_TRANSLATED", orig_path_translated); + FCGI_PUTENV(request, "PATH_TRANSLATED", NULL); } } if (env_script_name != orig_script_name) { if (orig_script_name) { - _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC); + FCGI_PUTENV(request, "ORIG_SCRIPT_NAME", orig_script_name); } - SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name TSRMLS_CC); + SG(request_info).request_uri = FCGI_PUTENV(request, "SCRIPT_NAME", env_script_name); } else { SG(request_info).request_uri = env_script_name; } @@ -1419,39 +1382,48 @@ static void init_request_info(TSRMLS_D) SG(request_info).path_translated = estrdup(script_path_translated); } - SG(request_info).request_method = sapi_cgibin_getenv("REQUEST_METHOD", sizeof("REQUEST_METHOD") - 1 TSRMLS_CC); + SG(request_info).request_method = FCGI_GETENV(request, "REQUEST_METHOD"); /* FIXME - Work out proto_num here */ - SG(request_info).query_string = sapi_cgibin_getenv("QUERY_STRING", sizeof("QUERY_STRING") - 1 TSRMLS_CC); + SG(request_info).query_string = FCGI_GETENV(request, "QUERY_STRING"); SG(request_info).content_type = (content_type ? content_type : "" ); SG(request_info).content_length = (content_length ? atol(content_length) : 0); /* The CGI RFC allows servers to pass on unvalidated Authorization data */ - auth = sapi_cgibin_getenv("HTTP_AUTHORIZATION", sizeof("HTTP_AUTHORIZATION") - 1 TSRMLS_CC); - php_handle_auth_data(auth TSRMLS_CC); + auth = FCGI_GETENV(request, "HTTP_AUTHORIZATION"); + php_handle_auth_data(auth); } /* INI stuff */ - ini = sapi_cgibin_getenv("PHP_VALUE", sizeof("PHP_VALUE") - 1 TSRMLS_CC); + ini = FCGI_GETENV(request, "PHP_VALUE"); if (ini) { int mode = ZEND_INI_USER; char *tmp; spprintf(&tmp, 0, "%s\n", ini); - zend_parse_ini_string(tmp, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t)fastcgi_ini_parser, &mode TSRMLS_CC); + zend_parse_ini_string(tmp, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t)fastcgi_ini_parser, &mode); efree(tmp); } - ini = sapi_cgibin_getenv("PHP_ADMIN_VALUE", sizeof("PHP_ADMIN_VALUE") - 1 TSRMLS_CC); + ini = FCGI_GETENV(request, "PHP_ADMIN_VALUE"); if (ini) { int mode = ZEND_INI_SYSTEM; char *tmp; spprintf(&tmp, 0, "%s\n", ini); - zend_parse_ini_string(tmp, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t)fastcgi_ini_parser, &mode TSRMLS_CC); + zend_parse_ini_string(tmp, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t)fastcgi_ini_parser, &mode); efree(tmp); } } /* }}} */ -static void fastcgi_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback_type, void *arg TSRMLS_DC) /* {{{ */ +static fcgi_request *fpm_init_request(int listen_fd) /* {{{ */ { + fcgi_request *req = fcgi_init_request(listen_fd, + fpm_request_accepting, + fpm_request_reading_headers, + fpm_request_finished); + return req; +} +/* }}} */ + +static void fastcgi_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback_type, void *arg) /* {{{ */ { int *mode = (int *)arg; char *key; @@ -1504,7 +1476,7 @@ PHP_INI_END() /* {{{ php_cgi_globals_ctor */ -static void php_cgi_globals_ctor(php_cgi_globals_struct *php_cgi_globals TSRMLS_DC) +static void php_cgi_globals_ctor(php_cgi_globals_struct *php_cgi_globals) { php_cgi_globals->rfc2616_headers = 0; php_cgi_globals->nph = 0; @@ -1513,7 +1485,7 @@ static void php_cgi_globals_ctor(php_cgi_globals_struct *php_cgi_globals TSRMLS_ php_cgi_globals->fix_pathinfo = 1; php_cgi_globals->discard_path = 0; php_cgi_globals->fcgi_logging = 1; - zend_hash_init(&php_cgi_globals->user_config_cache, 0, NULL, (dtor_func_t) user_config_cache_entry_dtor, 1); + zend_hash_init(&php_cgi_globals->user_config_cache, 0, NULL, user_config_cache_entry_dtor, 1); php_cgi_globals->error_header = NULL; php_cgi_globals->fpm_config = NULL; } @@ -1526,7 +1498,7 @@ static PHP_MINIT_FUNCTION(cgi) #ifdef ZTS ts_allocate_id(&php_cgi_globals_id, sizeof(php_cgi_globals_struct), (ts_allocate_ctor) php_cgi_globals_ctor, NULL); #else - php_cgi_globals_ctor(&php_cgi_globals TSRMLS_CC); + php_cgi_globals_ctor(&php_cgi_globals); #endif REGISTER_INI_ENTRIES(); return SUCCESS; @@ -1560,13 +1532,13 @@ PHP_FUNCTION(fastcgi_finish_request) /* {{{ */ { fcgi_request *request = (fcgi_request*) SG(server_context); - if (request->fd >= 0) { + if (!fcgi_is_closed(request)) { - php_output_end_all(TSRMLS_C); - php_header(TSRMLS_C); + php_output_end_all(); + php_header(); fcgi_flush(request, 1); - fcgi_close(request, 0, 0); + fcgi_close(request, 0, 1); RETURN_TRUE; } @@ -1614,7 +1586,7 @@ int main(int argc, char *argv[]) int max_requests = 500; int requests = 0; int fcgi_fd = 0; - fcgi_request request; + fcgi_request *request; char *fpm_config = NULL; char *fpm_prefix = NULL; char *fpm_pid = NULL; @@ -1640,10 +1612,18 @@ int main(int argc, char *argv[]) tsrm_ls = ts_resource(0); #endif +#ifdef ZEND_SIGNALS + zend_signal_startup(); +#endif + sapi_startup(&cgi_sapi_module); cgi_sapi_module.php_ini_path_override = NULL; cgi_sapi_module.php_ini_ignore_cwd = 1; - + +#ifndef HAVE_ATTRIBUTE_WEAK + fcgi_set_logger(fpm_fcgi_log); +#endif + fcgi_init(); #ifdef PHP_WIN32 @@ -1714,21 +1694,21 @@ int main(int argc, char *argv[]) use_extended_info = 1; break; - case 't': + case 't': test_conf++; break; case 'm': /* list compiled in modules */ cgi_sapi_module.startup(&cgi_sapi_module); - php_output_activate(TSRMLS_C); + php_output_activate(); SG(headers_sent) = 1; php_printf("[PHP Modules]\n"); - print_modules(TSRMLS_C); + print_modules(); php_printf("\n[Zend Modules]\n"); - print_extensions(TSRMLS_C); + print_extensions(); php_printf("\n"); - php_output_end_all(TSRMLS_C); - php_output_deactivate(TSRMLS_C); + php_output_end_all(); + php_output_deactivate(); fcgi_shutdown(); exit_status = FPM_EXIT_OK; goto out; @@ -1757,20 +1737,20 @@ int main(int argc, char *argv[]) case 'h': case '?': cgi_sapi_module.startup(&cgi_sapi_module); - php_output_activate(TSRMLS_C); + php_output_activate(); SG(headers_sent) = 1; php_cgi_usage(argv[0]); - php_output_end_all(TSRMLS_C); - php_output_deactivate(TSRMLS_C); + php_output_end_all(); + php_output_deactivate(); fcgi_shutdown(); exit_status = (c == 'h') ? FPM_EXIT_OK : FPM_EXIT_USAGE; goto out; case 'v': /* show php version & quit */ cgi_sapi_module.startup(&cgi_sapi_module); - if (php_request_startup(TSRMLS_C) == FAILURE) { + if (php_request_startup() == FAILURE) { SG(server_context) = NULL; - php_module_shutdown(TSRMLS_C); + php_module_shutdown(); return FPM_EXIT_SOFTWARE; } SG(headers_sent) = 1; @@ -1791,14 +1771,14 @@ int main(int argc, char *argv[]) if (php_information) { cgi_sapi_module.phpinfo_as_text = 1; cgi_sapi_module.startup(&cgi_sapi_module); - if (php_request_startup(TSRMLS_C) == FAILURE) { + if (php_request_startup() == FAILURE) { SG(server_context) = NULL; - php_module_shutdown(TSRMLS_C); + php_module_shutdown(); return FPM_EXIT_SOFTWARE; } SG(headers_sent) = 1; SG(request_info).no_headers = 1; - php_print_info(0xFFFFFFFF TSRMLS_CC); + php_print_info(0xFFFFFFFF); php_request_shutdown((void *) 0); fcgi_shutdown(); exit_status = FPM_EXIT_OK; @@ -1808,11 +1788,11 @@ int main(int argc, char *argv[]) /* No other args are permitted here as there is no interactive mode */ if (argc != php_optind) { cgi_sapi_module.startup(&cgi_sapi_module); - php_output_activate(TSRMLS_C); + php_output_activate(); SG(headers_sent) = 1; php_cgi_usage(argv[0]); - php_output_end_all(TSRMLS_C); - php_output_deactivate(TSRMLS_C); + php_output_end_all(); + php_output_deactivate(); fcgi_shutdown(); exit_status = FPM_EXIT_USAGE; goto out; @@ -1825,7 +1805,7 @@ int main(int argc, char *argv[]) SG(request_info).path_translated = NULL; #endif - cgi_sapi_module.additional_functions = additional_functions; + cgi_sapi_module.additional_functions = NULL; cgi_sapi_module.executable_location = argv[0]; /* startup after we get the above ini override se we get things right */ @@ -1835,7 +1815,7 @@ int main(int argc, char *argv[]) #endif return FPM_EXIT_SOFTWARE; } - + if (use_extended_info) { CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO; } @@ -1910,39 +1890,38 @@ consult the installation file that came with this distribution, or visit \n\ php_import_environment_variables = cgi_php_import_environment_variables; /* library is already initialized, now init our request */ - fcgi_init_request(&request, fcgi_fd); + request = fpm_init_request(fcgi_fd); zend_first_try { - while (fcgi_accept_request(&request) >= 0) { + while (EXPECTED(fcgi_accept_request(request) >= 0)) { char *primary_script = NULL; request_body_fd = -1; - SG(server_context) = (void *) &request; - init_request_info(TSRMLS_C); - CG(interactive) = 0; + SG(server_context) = (void *) request; + init_request_info(); fpm_request_info(); /* request startup only after we've done all we can to * get path_translated */ - if (php_request_startup(TSRMLS_C) == FAILURE) { - fcgi_finish_request(&request, 1); + if (UNEXPECTED(php_request_startup() == FAILURE)) { + fcgi_finish_request(request, 1); SG(server_context) = NULL; - php_module_shutdown(TSRMLS_C); + php_module_shutdown(); return FPM_EXIT_SOFTWARE; } /* check if request_method has been sent. * if not, it's certainly not an HTTP over fcgi request */ - if (!SG(request_info).request_method) { + if (UNEXPECTED(!SG(request_info).request_method)) { goto fastcgi_request_done; } - if (fpm_status_handle_request(TSRMLS_C)) { + if (UNEXPECTED(fpm_status_handle_request())) { goto fastcgi_request_done; } /* If path_translated is NULL, terminate here with a 404 */ - if (!SG(request_info).path_translated) { + if (UNEXPECTED(!SG(request_info).path_translated)) { zend_try { zlog(ZLOG_DEBUG, "Primary script unknown"); SG(sapi_headers).http_response_code = 404; @@ -1952,20 +1931,20 @@ consult the installation file that came with this distribution, or visit \n\ goto fastcgi_request_done; } - if (fpm_php_limit_extensions(SG(request_info).path_translated)) { + if (UNEXPECTED(fpm_php_limit_extensions(SG(request_info).path_translated))) { SG(sapi_headers).http_response_code = 403; PUTS("Access denied.\n"); goto fastcgi_request_done; } - /* + /* * have to duplicate SG(request_info).path_translated to be able to log errrors * php_fopen_primary_script seems to delete SG(request_info).path_translated on failure */ primary_script = estrdup(SG(request_info).path_translated); /* path_translated exists, we can continue ! */ - if (php_fopen_primary_script(&file_handle TSRMLS_CC) == FAILURE) { + if (UNEXPECTED(php_fopen_primary_script(&file_handle) == FAILURE)) { zend_try { zlog(ZLOG_ERROR, "Unable to open primary script: %s (%s)", primary_script, strerror(errno)); if (errno == EACCES) { @@ -1986,43 +1965,44 @@ consult the installation file that came with this distribution, or visit \n\ fpm_request_executing(); - php_execute_script(&file_handle TSRMLS_CC); + php_execute_script(&file_handle); fastcgi_request_done: - if (primary_script) { + if (EXPECTED(primary_script)) { efree(primary_script); } - if (request_body_fd != -1) { + if (UNEXPECTED(request_body_fd != -1)) { close(request_body_fd); } request_body_fd = -2; - if (EG(exit_status) == 255) { + if (UNEXPECTED(EG(exit_status) == 255)) { if (CGIG(error_header) && *CGIG(error_header)) { sapi_header_line ctr = {0}; ctr.line = CGIG(error_header); ctr.line_len = strlen(CGIG(error_header)); - sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC); + sapi_header_op(SAPI_HEADER_REPLACE, &ctr); } } - fpm_request_end(TSRMLS_C); - fpm_log_write(NULL TSRMLS_CC); + fpm_request_end(); + fpm_log_write(NULL); - STR_FREE(SG(request_info).path_translated); + efree(SG(request_info).path_translated); SG(request_info).path_translated = NULL; php_request_shutdown((void *) 0); requests++; - if (max_requests && (requests == max_requests)) { - fcgi_finish_request(&request, 1); + if (UNEXPECTED(max_requests && (requests == max_requests))) { + fcgi_finish_request(request, 1); break; } /* end of fastcgi loop */ } + fcgi_destroy_request(request); fcgi_shutdown(); if (cgi_sapi_module.php_ini_path_override) { @@ -2038,7 +2018,7 @@ fastcgi_request_done: out: SG(server_context) = NULL; - php_module_shutdown(TSRMLS_C); + php_module_shutdown(); if (parent) { sapi_shutdown(); diff --git a/sapi/fpm/fpm/fpm_php.c b/sapi/fpm/fpm/fpm_php.c index cd4d3aef3a..e20276974d 100644 --- a/sapi/fpm/fpm/fpm_php.c +++ b/sapi/fpm/fpm/fpm_php.c @@ -23,32 +23,31 @@ static char **limit_extensions = NULL; -static int fpm_php_zend_ini_alter_master(char *name, int name_length, char *new_value, int new_value_length, int mode, int stage TSRMLS_DC) /* {{{ */ +static int fpm_php_zend_ini_alter_master(char *name, int name_length, char *new_value, int new_value_length, int mode, int stage) /* {{{ */ { zend_ini_entry *ini_entry; - char *duplicate; + zend_string *duplicate; - if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry) == FAILURE) { + if ((ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length)) == NULL) { return FAILURE; } - duplicate = strdup(new_value); + duplicate = zend_string_init(new_value, new_value_length, 1); if (!ini_entry->on_modify - || ini_entry->on_modify(ini_entry, duplicate, new_value_length, - ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage TSRMLS_CC) == SUCCESS) { + || ini_entry->on_modify(ini_entry, duplicate, + ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage) == SUCCESS) { ini_entry->value = duplicate; - ini_entry->value_length = new_value_length; ini_entry->modifiable = mode; } else { - free(duplicate); + zend_string_release(duplicate); } return SUCCESS; } /* }}} */ -static void fpm_php_disable(char *value, int (*zend_disable)(char *, uint TSRMLS_DC) TSRMLS_DC) /* {{{ */ +static void fpm_php_disable(char *value, int (*zend_disable)(char *, size_t)) /* {{{ */ { char *s = 0, *e = value; @@ -58,7 +57,7 @@ static void fpm_php_disable(char *value, int (*zend_disable)(char *, uint TSRMLS case ',': if (s) { *e = '\0'; - zend_disable(s, e - s TSRMLS_CC); + zend_disable(s, e - s); s = 0; } break; @@ -72,14 +71,13 @@ static void fpm_php_disable(char *value, int (*zend_disable)(char *, uint TSRMLS } if (s) { - zend_disable(s, e - s TSRMLS_CC); + zend_disable(s, e - s); } } /* }}} */ int fpm_php_apply_defines_ex(struct key_value_s *kv, int mode) /* {{{ */ { - TSRMLS_FETCH(); char *name = kv->key; char *value = kv->value; @@ -88,25 +86,25 @@ int fpm_php_apply_defines_ex(struct key_value_s *kv, int mode) /* {{{ */ if (!strcmp(name, "extension") && *value) { zval zv; - php_dl(value, MODULE_PERSISTENT, &zv, 1 TSRMLS_CC); - return Z_BVAL(zv) ? 1 : -1; + php_dl(value, MODULE_PERSISTENT, &zv, 1); + return Z_TYPE(zv) == IS_TRUE; } - if (fpm_php_zend_ini_alter_master(name, name_len+1, value, value_len, mode, PHP_INI_STAGE_ACTIVATE TSRMLS_CC) == FAILURE) { + if (fpm_php_zend_ini_alter_master(name, name_len, value, value_len, mode, PHP_INI_STAGE_ACTIVATE) == FAILURE) { return -1; } if (!strcmp(name, "disable_functions") && *value) { char *v = strdup(value); PG(disable_functions) = v; - fpm_php_disable(v, zend_disable_function TSRMLS_CC); + fpm_php_disable(v, zend_disable_function); return 1; } if (!strcmp(name, "disable_classes") && *value) { char *v = strdup(value); PG(disable_classes) = v; - fpm_php_disable(v, zend_disable_class TSRMLS_CC); + fpm_php_disable(v, zend_disable_class); return 1; } @@ -132,6 +130,7 @@ static int fpm_php_apply_defines(struct fpm_worker_pool_s *wp) /* {{{ */ return 0; } +/* }}} */ static int fpm_php_set_allowed_clients(struct fpm_worker_pool_s *wp) /* {{{ */ { @@ -157,37 +156,37 @@ static int fpm_php_set_fcgi_mgmt_vars(struct fpm_worker_pool_s *wp) /* {{{ */ /* }}} */ #endif -char *fpm_php_script_filename(TSRMLS_D) /* {{{ */ +char *fpm_php_script_filename(void) /* {{{ */ { return SG(request_info).path_translated; } /* }}} */ -char *fpm_php_request_uri(TSRMLS_D) /* {{{ */ +char *fpm_php_request_uri(void) /* {{{ */ { return (char *) SG(request_info).request_uri; } /* }}} */ -char *fpm_php_request_method(TSRMLS_D) /* {{{ */ +char *fpm_php_request_method(void) /* {{{ */ { return (char *) SG(request_info).request_method; } /* }}} */ -char *fpm_php_query_string(TSRMLS_D) /* {{{ */ +char *fpm_php_query_string(void) /* {{{ */ { return SG(request_info).query_string; } /* }}} */ -char *fpm_php_auth_user(TSRMLS_D) /* {{{ */ +char *fpm_php_auth_user(void) /* {{{ */ { return SG(request_info).auth_user; } /* }}} */ -size_t fpm_php_content_length(TSRMLS_D) /* {{{ */ +size_t fpm_php_content_length(void) /* {{{ */ { return SG(request_info).content_length; } @@ -195,15 +194,14 @@ size_t fpm_php_content_length(TSRMLS_D) /* {{{ */ static void fpm_php_cleanup(int which, void *arg) /* {{{ */ { - TSRMLS_FETCH(); - php_module_shutdown(TSRMLS_C); + php_module_shutdown(); sapi_shutdown(); } /* }}} */ void fpm_php_soft_quit() /* {{{ */ { - fcgi_set_in_shutdown(1); + fcgi_terminate(); } /* }}} */ @@ -258,39 +256,30 @@ int fpm_php_limit_extensions(char *path) /* {{{ */ } /* }}} */ -char* fpm_php_get_string_from_table(char *table, char *key TSRMLS_DC) /* {{{ */ +char* fpm_php_get_string_from_table(zend_string *table, char *key) /* {{{ */ { - zval **data, **tmp; - char *string_key; - uint string_len; - ulong num_key; + zval *data, *tmp; + zend_string *str; if (!table || !key) { return NULL; } /* inspired from ext/standard/info.c */ - zend_is_auto_global(table, strlen(table) TSRMLS_CC); + zend_is_auto_global(table); /* find the table and ensure it's an array */ - if (zend_hash_find(&EG(symbol_table), table, strlen(table) + 1, (void **) &data) == SUCCESS && Z_TYPE_PP(data) == IS_ARRAY) { - - /* reset the internal pointer */ - zend_hash_internal_pointer_reset(Z_ARRVAL_PP(data)); - - /* parse the array to look for our key */ - while (zend_hash_get_current_data(Z_ARRVAL_PP(data), (void **) &tmp) == SUCCESS) { - /* ensure the key is a string */ - if (zend_hash_get_current_key_ex(Z_ARRVAL_PP(data), &string_key, &string_len, &num_key, 0, NULL) == HASH_KEY_IS_STRING) { - /* compare to our key */ - if (!strncmp(string_key, key, string_len)) { - return Z_STRVAL_PP(tmp); - } - } - zend_hash_move_forward(Z_ARRVAL_PP(data)); - } + data = zend_hash_find(&EG(symbol_table), table); + if (!data || Z_TYPE_P(data) != IS_ARRAY) { + return NULL; } + ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(data), str, tmp) { + if (str && !strncmp(ZSTR_VAL(str), key, ZSTR_LEN(str))) { + return Z_STRVAL_P(tmp); + } + } ZEND_HASH_FOREACH_END(); + return NULL; } /* }}} */ diff --git a/sapi/fpm/fpm/fpm_php.h b/sapi/fpm/fpm/fpm_php.h index d6054737d6..a2f2138d23 100644 --- a/sapi/fpm/fpm/fpm_php.h +++ b/sapi/fpm/fpm/fpm_php.h @@ -34,17 +34,17 @@ struct fpm_worker_pool_s; int fpm_php_init_child(struct fpm_worker_pool_s *wp); -char *fpm_php_script_filename(TSRMLS_D); -char *fpm_php_request_uri(TSRMLS_D); -char *fpm_php_request_method(TSRMLS_D); -char *fpm_php_query_string(TSRMLS_D); -char *fpm_php_auth_user(TSRMLS_D); -size_t fpm_php_content_length(TSRMLS_D); +char *fpm_php_script_filename(void); +char *fpm_php_request_uri(void); +char *fpm_php_request_method(void); +char *fpm_php_query_string(void); +char *fpm_php_auth_user(void); +size_t fpm_php_content_length(void); void fpm_php_soft_quit(); int fpm_php_init_main(); int fpm_php_apply_defines_ex(struct key_value_s *kv, int mode); int fpm_php_limit_extensions(char *path); -char* fpm_php_get_string_from_table(char *table, char *key TSRMLS_DC); +char* fpm_php_get_string_from_table(zend_string *table, char *key); #endif diff --git a/sapi/fpm/fpm/fpm_php_trace.c b/sapi/fpm/fpm/fpm_php_trace.c index 925f2de64e..e6482b6380 100644 --- a/sapi/fpm/fpm/fpm_php_trace.c +++ b/sapi/fpm/fpm/fpm_php_trace.c @@ -40,7 +40,7 @@ #endif -static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog TSRMLS_DC) /* {{{ */ +static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog) /* {{{ */ { int callers_limit = 20; pid_t pid = child->pid; @@ -48,6 +48,7 @@ static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog TSRMLS_DC static const int buf_size = 1024; char buf[buf_size]; long execute_data; + long path_translated; long l; gettimeofday(&tv, 0); @@ -56,7 +57,13 @@ static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog TSRMLS_DC fprintf(slowlog, "\n%s [pool %s] pid %d\n", buf, child->wp->config->name, (int) pid); - if (0 > fpm_trace_get_strz(buf, buf_size, (long) &SG(request_info).path_translated)) { + if (0 > fpm_trace_get_long((long) &SG(request_info).path_translated, &l)) { + return -1; + } + + path_translated = l; + + if (0 > fpm_trace_get_strz(buf, buf_size, path_translated)) { return -1; } @@ -70,74 +77,125 @@ static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog TSRMLS_DC while (execute_data) { long function; + long function_name; + long file_name; + long prev; uint lineno = 0; - fprintf(slowlog, "[0x%" PTR_FMT "lx] ", execute_data); - - if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, function_state.function), &l)) { + if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, func), &l)) { return -1; } function = l; if (valid_ptr(function)) { - if (0 > fpm_trace_get_strz(buf, buf_size, function + offsetof(zend_function, common.function_name))) { + if (0 > fpm_trace_get_long(function + offsetof(zend_function, common.function_name), &l)) { return -1; } - fprintf(slowlog, "%s()", buf); + function_name = l; + + if (function_name == 0) { + uint32_t *call_info = (uint32_t *)&l; + if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, This.u1.type_info), &l)) { + return -1; + } + + if (ZEND_CALL_KIND_EX((*call_info) >> 24) == ZEND_CALL_TOP_CODE) { + return 0; + } else if (ZEND_CALL_KIND_EX(*(call_info) >> 24) == ZEND_CALL_NESTED_CODE) { + memcpy(buf, "[INCLUDE_OR_EVAL]", sizeof("[INCLUDE_OR_EVAL]")); + } else { + ZEND_ASSERT(0); + } + } else { + if (0 > fpm_trace_get_strz(buf, buf_size, function_name + offsetof(zend_string, val))) { + return -1; + } + + } } else { - fprintf(slowlog, "???"); + memcpy(buf, "???", sizeof("???")); } + + fprintf(slowlog, "[0x%" PTR_FMT "lx] ", execute_data); + + fprintf(slowlog, "%s()", buf); + + *buf = '\0'; - if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, op_array), &l)) { + if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, prev_execute_data), &l)) { return -1; } - *buf = '\0'; + execute_data = prev = l; - if (valid_ptr(l)) { - long op_array = l; + while (prev) { + zend_uchar *type; - if (0 > fpm_trace_get_strz(buf, buf_size, op_array + offsetof(zend_op_array, filename))) { + if (0 > fpm_trace_get_long(prev + offsetof(zend_execute_data, func), &l)) { return -1; } - } - if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, opline), &l)) { - return -1; - } + function = l; - if (valid_ptr(l)) { - long opline = l; - uint *lu = (uint *) &l; + if (!valid_ptr(function)) { + break; + } - if (0 > fpm_trace_get_long(opline + offsetof(struct _zend_op, lineno), &l)) { + type = (zend_uchar *)&l; + if (0 > fpm_trace_get_long(function + offsetof(zend_function, type), &l)) { return -1; } - lineno = *lu; - } + if (ZEND_USER_CODE(*type)) { + if (0 > fpm_trace_get_long(function + offsetof(zend_op_array, filename), &l)) { + return -1; + } - fprintf(slowlog, " %s:%u\n", *buf ? buf : "unknown", lineno); + file_name = l; - if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, prev_execute_data), &l)) { - return -1; + if (0 > fpm_trace_get_strz(buf, buf_size, file_name + offsetof(zend_string, val))) { + return -1; + } + + if (0 > fpm_trace_get_long(prev + offsetof(zend_execute_data, opline), &l)) { + return -1; + } + + if (valid_ptr(l)) { + long opline = l; + uint32_t *lu = (uint32_t *) &l; + + if (0 > fpm_trace_get_long(opline + offsetof(struct _zend_op, lineno), &l)) { + return -1; + } + + lineno = *lu; + } + break; + } + + if (0 > fpm_trace_get_long(prev + offsetof(zend_execute_data, prev_execute_data), &l)) { + return -1; + } + + prev = l; } - execute_data = l; + fprintf(slowlog, " %s:%u\n", *buf ? buf : "unknown", lineno); if (0 == --callers_limit) { break; } } + return 0; } /* }}} */ void fpm_php_trace(struct fpm_child_s *child) /* {{{ */ { - TSRMLS_FETCH(); fpm_scoreboard_update(0, 0, 0, 0, 0, 0, 1, FPM_SCOREBOARD_ACTION_INC, child->wp->scoreboard); FILE *slowlog; @@ -154,7 +212,7 @@ void fpm_php_trace(struct fpm_child_s *child) /* {{{ */ goto done1; } - if (0 > fpm_php_trace_dump(child, slowlog TSRMLS_CC)) { + if (0 > fpm_php_trace_dump(child, slowlog)) { fprintf(slowlog, "+++ dump failed\n"); } diff --git a/sapi/fpm/fpm/fpm_process_ctl.c b/sapi/fpm/fpm/fpm_process_ctl.c index 76ea4d358e..ca5a6f2e40 100644 --- a/sapi/fpm/fpm/fpm_process_ctl.c +++ b/sapi/fpm/fpm/fpm_process_ctl.c @@ -425,7 +425,7 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{ return; } - zlog(ZLOG_DEBUG, "[pool %s] %d child(ren) have been created dynamically", wp->config->name, children_to_fork); + zlog(ZLOG_DEBUG, "[pool %s] %d child(ren) have been created dynamically", wp->config->name, children_to_fork); /* Double the spawn rate for the next iteration */ if (wp->idle_spawn_rate < FPM_MAX_SPAWN_RATE) { diff --git a/sapi/fpm/fpm/fpm_request.c b/sapi/fpm/fpm/fpm_request.c index ed7e7a8890..ec8601b478 100644 --- a/sapi/fpm/fpm/fpm_request.c +++ b/sapi/fpm/fpm/fpm_request.c @@ -92,7 +92,6 @@ void fpm_request_reading_headers() /* {{{ */ proc->request_method[0] = '\0'; proc->script_filename[0] = '\0'; proc->query_string[0] = '\0'; - proc->query_string[0] = '\0'; proc->auth_user[0] = '\0'; proc->content_length = 0; fpm_scoreboard_proc_release(proc); @@ -104,14 +103,13 @@ void fpm_request_reading_headers() /* {{{ */ void fpm_request_info() /* {{{ */ { - TSRMLS_FETCH(); struct fpm_scoreboard_proc_s *proc; - char *request_uri = fpm_php_request_uri(TSRMLS_C); - char *request_method = fpm_php_request_method(TSRMLS_C); - char *script_filename = fpm_php_script_filename(TSRMLS_C); - char *query_string = fpm_php_query_string(TSRMLS_C); - char *auth_user = fpm_php_auth_user(TSRMLS_C); - size_t content_length = fpm_php_content_length(TSRMLS_C); + char *request_uri = fpm_php_request_uri(); + char *request_method = fpm_php_request_method(); + char *script_filename = fpm_php_script_filename(); + char *query_string = fpm_php_query_string(); + char *auth_user = fpm_php_auth_user(); + size_t content_length = fpm_php_content_length(); struct timeval now; fpm_clock_get(&now); @@ -172,14 +170,14 @@ void fpm_request_executing() /* {{{ */ } /* }}} */ -void fpm_request_end(TSRMLS_D) /* {{{ */ +void fpm_request_end(void) /* {{{ */ { struct fpm_scoreboard_proc_s *proc; struct timeval now; #ifdef HAVE_TIMES struct tms cpu; #endif - size_t memory = zend_memory_peak_usage(1 TSRMLS_CC); + size_t memory = zend_memory_peak_usage(1); fpm_clock_get(&now); #ifdef HAVE_TIMES @@ -256,7 +254,7 @@ void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *now, #if HAVE_FPM_TRACE if (child->slow_logged.tv_sec == 0 && slowlog_timeout && proc.request_stage == FPM_REQUEST_EXECUTING && tv.tv_sec >= slowlog_timeout) { - + str_purify_filename(purified_script_filename, proc.script_filename, sizeof(proc.script_filename)); child->slow_logged = proc.accepted; diff --git a/sapi/fpm/fpm/fpm_request.h b/sapi/fpm/fpm/fpm_request.h index aebd36cff4..d9e831d100 100644 --- a/sapi/fpm/fpm/fpm_request.h +++ b/sapi/fpm/fpm/fpm_request.h @@ -9,7 +9,7 @@ void fpm_request_accepting(); /* hanging in accept() */ void fpm_request_reading_headers(); /* start reading fastcgi request from very first byte */ void fpm_request_info(); /* not a stage really but a point in the php code, where all request params have become known to sapi */ void fpm_request_executing(); /* the script is executing */ -void fpm_request_end(TSRMLS_D); /* request ended: script response have been sent to web server */ +void fpm_request_end(void); /* request ended: script response have been sent to web server */ void fpm_request_finished(); /* request processed: cleaning current request */ struct fpm_child_s; diff --git a/sapi/fpm/fpm/fpm_scoreboard.c b/sapi/fpm/fpm/fpm_scoreboard.c index 8d0868182d..eabab8f8e6 100644 --- a/sapi/fpm/fpm/fpm_scoreboard.c +++ b/sapi/fpm/fpm/fpm_scoreboard.c @@ -69,7 +69,7 @@ int fpm_scoreboard_init_main() /* {{{ */ wp->scoreboard->start_epoch = time(NULL); strlcpy(wp->scoreboard->pool, wp->config->name, sizeof(wp->scoreboard->pool)); } - return 0; + return 0; } /* }}} */ diff --git a/sapi/fpm/fpm/fpm_signals.c b/sapi/fpm/fpm/fpm_signals.c index c5d0692f18..a637e69e71 100644 --- a/sapi/fpm/fpm/fpm_signals.c +++ b/sapi/fpm/fpm/fpm_signals.c @@ -241,6 +241,10 @@ int fpm_signals_init_child() /* {{{ */ zlog(ZLOG_SYSERROR, "failed to init child signals: sigaction()"); return -1; } + +#ifdef ZEND_SIGNALS + zend_signal_init(); +#endif return 0; } /* }}} */ diff --git a/sapi/fpm/fpm/fpm_sockets.c b/sapi/fpm/fpm/fpm_sockets.c index 46ce161844..f27bb4afe3 100644 --- a/sapi/fpm/fpm/fpm_sockets.c +++ b/sapi/fpm/fpm/fpm_sockets.c @@ -265,6 +265,8 @@ static int fpm_socket_af_inet_listening_socket(struct fpm_worker_pool_s *wp) /* } else if (strlen(dup_address) == strspn(dup_address, "0123456789")) { /* this is port */ port = atoi(dup_address); port_str = dup_address; + /* IPv6 catch-all + IPv4-mapped */ + addr = "::"; } if (port == 0) { @@ -272,18 +274,6 @@ static int fpm_socket_af_inet_listening_socket(struct fpm_worker_pool_s *wp) /* return -1; } - if (!addr) { - /* no address: default documented behavior, all IPv4 addresses */ - struct sockaddr_in sa_in; - - memset(&sa_in, 0, sizeof(sa_in)); - sa_in.sin_family = AF_INET; - sa_in.sin_port = htons(port); - sa_in.sin_addr.s_addr = htonl(INADDR_ANY); - free(dup_address); - return fpm_sockets_get_listening_socket(wp, (struct sockaddr *) &sa_in, sizeof(struct sockaddr_in)); - } - /* strip brackets from address for getaddrinfo */ addr_len = strlen(addr); if (addr[0] == '[' && addr[addr_len - 1] == ']') { @@ -305,10 +295,10 @@ static int fpm_socket_af_inet_listening_socket(struct fpm_worker_pool_s *wp) /* inet_ntop(p->ai_family, fpm_get_in_addr(p->ai_addr), tmpbuf, INET6_ADDRSTRLEN); if (sock < 0) { if ((sock = fpm_sockets_get_listening_socket(wp, p->ai_addr, p->ai_addrlen)) != -1) { - zlog(ZLOG_DEBUG, "Found address for %s, socket opened on %s", dup_address, tmpbuf); + zlog(ZLOG_DEBUG, "Found address for %s, socket opened on %s", addr, tmpbuf); } } else { - zlog(ZLOG_WARNING, "Found multiple addresses for %s, %s ignored", dup_address, tmpbuf); + zlog(ZLOG_WARNING, "Found multiple addresses for %s, %s ignored", addr, tmpbuf); } } @@ -430,7 +420,7 @@ int fpm_socket_get_listening_queue(int sock, unsigned *cur_lq, unsigned *max_lq) zlog(ZLOG_SYSERROR, "failed to retrieve TCP_INFO for socket"); return -1; } -#if defined(__FreeBSD__) +#if defined(__FreeBSD__) || defined(__NetBSD__) if (info.__tcpi_sacked == 0) { return -1; } diff --git a/sapi/fpm/fpm/fpm_sockets.h b/sapi/fpm/fpm/fpm_sockets.h index 446c78e410..2bd3d58249 100644 --- a/sapi/fpm/fpm/fpm_sockets.h +++ b/sapi/fpm/fpm/fpm_sockets.h @@ -19,7 +19,7 @@ #if (__FreeBSD__) || (__OpenBSD__) #define FPM_BACKLOG_DEFAULT -1 #else -#define FPM_BACKLOG_DEFAULT 65535 +#define FPM_BACKLOG_DEFAULT 511 #endif enum fpm_address_domain fpm_sockets_domain_from_address(char *addr); diff --git a/sapi/fpm/fpm/fpm_status.c b/sapi/fpm/fpm/fpm_status.c index 2363b57f80..3e82face3c 100644 --- a/sapi/fpm/fpm/fpm_status.c +++ b/sapi/fpm/fpm/fpm_status.c @@ -46,7 +46,7 @@ int fpm_status_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ } /* }}} */ -int fpm_status_handle_request(TSRMLS_D) /* {{{ */ +int fpm_status_handle_request(void) /* {{{ */ { struct fpm_scoreboard_s scoreboard, *scoreboard_p; struct fpm_scoreboard_proc_s proc; @@ -55,6 +55,7 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */ int full, encode; char *short_syntax, *short_post; char *full_pre, *full_syntax, *full_post, *full_separator; + zend_string *_GET_str; if (!SG(request_info).request_uri) { return 0; @@ -63,9 +64,9 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */ /* PING */ if (fpm_status_ping_uri && fpm_status_ping_response && !strcmp(fpm_status_ping_uri, SG(request_info).request_uri)) { fpm_request_executing(); - sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC); - sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1 TSRMLS_CC); - sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1 TSRMLS_CC); + sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1); + sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1); + sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1); SG(sapi_headers).http_response_code = 200; /* handle HEAD */ @@ -85,9 +86,9 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */ if (!scoreboard_p) { zlog(ZLOG_ERROR, "status: unable to find or access status shared memory"); SG(sapi_headers).http_response_code = 500; - sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC); - sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1 TSRMLS_CC); - sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1 TSRMLS_CC); + sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1); + sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1); + sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1); PUTS("Internal error. Please review log file for errors."); return 1; } @@ -95,9 +96,9 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */ if (!fpm_spinlock(&scoreboard_p->lock, 1)) { zlog(ZLOG_NOTICE, "[pool %s] status: scoreboard already in used.", scoreboard_p->pool); SG(sapi_headers).http_response_code = 503; - sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC); - sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1 TSRMLS_CC); - sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1 TSRMLS_CC); + sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1); + sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1); + sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1); PUTS("Server busy. Please try again later."); return 1; } @@ -108,16 +109,16 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */ if (scoreboard.idle < 0 || scoreboard.active < 0) { zlog(ZLOG_ERROR, "[pool %s] invalid status values", scoreboard.pool); SG(sapi_headers).http_response_code = 500; - sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC); - sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1 TSRMLS_CC); - sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1 TSRMLS_CC); + sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1); + sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1); + sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1); PUTS("Internal error. Please review log file for errors."); return 1; } /* send common headers */ - sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1 TSRMLS_CC); - sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1 TSRMLS_CC); + sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1); + sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1); SG(sapi_headers).http_response_code = 200; /* handle HEAD */ @@ -126,14 +127,15 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */ } /* full status ? */ - full = (fpm_php_get_string_from_table("_GET", "full" TSRMLS_CC) != NULL); + _GET_str = zend_string_init("_GET", sizeof("_GET")-1, 0); + full = (fpm_php_get_string_from_table(_GET_str, "full") != NULL); short_syntax = short_post = NULL; full_separator = full_pre = full_syntax = full_post = NULL; encode = 0; /* HTML */ - if (fpm_php_get_string_from_table("_GET", "html" TSRMLS_CC)) { - sapi_add_header_ex(ZEND_STRL("Content-Type: text/html"), 1, 1 TSRMLS_CC); + if (fpm_php_get_string_from_table(_GET_str, "html")) { + sapi_add_header_ex(ZEND_STRL("Content-Type: text/html"), 1, 1); time_format = "%d/%b/%Y:%H:%M:%S %z"; encode = 1; @@ -207,8 +209,8 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */ } /* XML */ - } else if (fpm_php_get_string_from_table("_GET", "xml" TSRMLS_CC)) { - sapi_add_header_ex(ZEND_STRL("Content-Type: text/xml"), 1, 1 TSRMLS_CC); + } else if (fpm_php_get_string_from_table(_GET_str, "xml")) { + sapi_add_header_ex(ZEND_STRL("Content-Type: text/xml"), 1, 1); time_format = "%s"; encode = 1; @@ -236,7 +238,7 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */ short_post = "</status>"; } else { full_pre = "<processes>\n"; - full_syntax = + full_syntax = "<process>" "<pid>%d</pid>" "<state>%s</state>" @@ -259,8 +261,8 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */ } /* JSON */ - } else if (fpm_php_get_string_from_table("_GET", "json" TSRMLS_CC)) { - sapi_add_header_ex(ZEND_STRL("Content-Type: application/json"), 1, 1 TSRMLS_CC); + } else if (fpm_php_get_string_from_table(_GET_str, "json")) { + sapi_add_header_ex(ZEND_STRL("Content-Type: application/json"), 1, 1); time_format = "%s"; short_syntax = @@ -311,7 +313,7 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */ /* TEXT */ } else { - sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC); + sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1); time_format = "%d/%b/%Y:%H:%M:%S %z"; short_syntax = @@ -376,6 +378,7 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */ PUTS(buffer); efree(buffer); + zend_string_release(_GET_str); if (short_post) { PUTS(short_post); @@ -384,7 +387,7 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */ /* no need to test the var 'full' */ if (full_syntax) { int i, first; - size_t len; + zend_string *tmp_query_string; char *query_string; struct timeval duration, now; #ifdef HAVE_FPM_LQ @@ -413,12 +416,13 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */ } query_string = NULL; - len = 0; + tmp_query_string = NULL; if (proc.query_string[0] != '\0') { if (!encode) { query_string = proc.query_string; } else { - query_string = php_escape_html_entities_ex((unsigned char *)proc.query_string, strlen(proc.query_string), &len, 1, ENT_HTML_IGNORE_ERRORS & ENT_COMPAT, NULL, 1 TSRMLS_CC); + tmp_query_string = php_escape_html_entities_ex((unsigned char *)proc.query_string, strlen(proc.query_string), 1, ENT_HTML_IGNORE_ERRORS & ENT_COMPAT, NULL, 1); + query_string = ZSTR_VAL(tmp_query_string); } } @@ -458,8 +462,8 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */ PUTS(buffer); efree(buffer); - if (len > 0 && query_string) { - efree(query_string); + if (tmp_query_string) { + zend_string_free(tmp_query_string); } } diff --git a/sapi/fpm/fpm/fpm_status.h b/sapi/fpm/fpm/fpm_status.h index 8f3daf9c72..c6c27cd031 100644 --- a/sapi/fpm/fpm/fpm_status.h +++ b/sapi/fpm/fpm/fpm_status.h @@ -28,7 +28,7 @@ void fpm_status_increment_accepted_conn(struct fpm_shm_s *shm); void fpm_status_set_pm(struct fpm_shm_s *shm, int pm); void fpm_status_update_max_children_reached(struct fpm_shm_s *shm, unsigned int max_children_reached); void fpm_status_increment_max_children_reached(struct fpm_shm_s *shm); -int fpm_status_handle_request(TSRMLS_D); +int fpm_status_handle_request(void); extern struct fpm_shm_s *fpm_status_shm; diff --git a/sapi/fpm/fpm/fpm_systemd.c b/sapi/fpm/fpm/fpm_systemd.c index c4d7ec15a4..95d12c97f2 100644 --- a/sapi/fpm/fpm/fpm_systemd.c +++ b/sapi/fpm/fpm/fpm_systemd.c @@ -29,7 +29,7 @@ static void fpm_systemd() /* {{{ */ } /* - zlog(ZLOG_DEBUG, "systemd %s (Processes active:%d, idle:%d, Requests:%lu, slow:%lu, Traffic:%.3greq/sec)", + zlog(ZLOG_DEBUG, "systemd %s (Processes active:%d, idle:%d, Requests:%lu, slow:%lu, Traffic:%.3greq/sec)", fpm_global_config.systemd_watchdog ? "watchdog" : "heartbeat", active, idle, requests, slow_req, ((float)requests - last) * 1000.0 / fpm_global_config.systemd_interval); */ diff --git a/sapi/fpm/fpm/fpm_trace.c b/sapi/fpm/fpm/fpm_trace.c index 366af5a3fe..eae7fe9bbf 100644 --- a/sapi/fpm/fpm/fpm_trace.c +++ b/sapi/fpm/fpm/fpm_trace.c @@ -11,13 +11,9 @@ int fpm_trace_get_strz(char *buf, size_t sz, long addr) /* {{{ */ { int i; - long l; + long l = addr; char *lc = (char *) &l; - if (0 > fpm_trace_get_long(addr, &l)) { - return -1; - } - i = l % SIZEOF_LONG; l -= i; for (addr = l; ; addr += SIZEOF_LONG) { diff --git a/sapi/fpm/fpm/fpm_unix.c b/sapi/fpm/fpm/fpm_unix.c index f0d4573483..6089e3109e 100644 --- a/sapi/fpm/fpm/fpm_unix.c +++ b/sapi/fpm/fpm/fpm_unix.c @@ -477,7 +477,7 @@ int fpm_unix_init_main() /* {{{ */ * The parent process has then to wait for the master * process to initialize to return a consistent exit * value. For this pupose, the master process will - * send \"1\" into the pipe if everything went well + * send \"1\" into the pipe if everything went well * and \"0\" otherwise. */ diff --git a/sapi/fpm/fpm/zlog.c b/sapi/fpm/fpm/zlog.c index 80db9d8374..1659c77efc 100644 --- a/sapi/fpm/fpm/zlog.c +++ b/sapi/fpm/fpm/zlog.c @@ -98,20 +98,20 @@ int zlog_set_level(int new_value) /* {{{ */ } /* }}} */ -void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /* {{{ */ +void vzlog(const char *function, int line, int flags, const char *fmt, va_list args) /* {{{ */ { struct timeval tv; char buf[MAX_LINE_LENGTH]; const size_t buf_size = MAX_LINE_LENGTH; - va_list args; size_t len = 0; int truncated = 0; int saved_errno; if (external_logger) { - va_start(args, fmt); - len = vsnprintf(buf, buf_size, fmt, args); - va_end(args); + va_list ap; + va_copy(ap, args); + len = vsnprintf(buf, buf_size, fmt, ap); + va_end(ap); if (len >= buf_size) { memcpy(buf + buf_size - sizeof("..."), "...", sizeof("...") - 1); len = buf_size - 1; @@ -157,9 +157,7 @@ void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /* } if (!truncated) { - va_start(args, fmt); len += vsnprintf(buf + len, buf_size - len, fmt, args); - va_end(args); if (len >= buf_size) { truncated = 1; } @@ -184,7 +182,7 @@ void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /* buf[len] = '\0'; php_syslog(syslog_priorities[zlog_level], "%s", buf); buf[len++] = '\n'; - } else + } else #endif { buf[len++] = '\n'; @@ -197,3 +195,10 @@ void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /* } /* }}} */ +void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /* {{{ */ { + va_list args; + va_start(args, fmt); + vzlog(function, line, flags, fmt, args); + va_end(args); +} +/* }}} */ diff --git a/sapi/fpm/fpm/zlog.h b/sapi/fpm/fpm/zlog.h index 1945922da5..c2bf752b93 100644 --- a/sapi/fpm/fpm/zlog.h +++ b/sapi/fpm/fpm/zlog.h @@ -5,6 +5,8 @@ #ifndef ZLOG_H #define ZLOG_H 1 +#include <stdarg.h> + #define zlog(flags,...) zlog_ex(__func__, __LINE__, flags, __VA_ARGS__) struct timeval; @@ -17,6 +19,7 @@ void zlog_set_launched(void); size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len); +void vzlog(const char *function, int line, int flags, const char *fmt, va_list args); void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) __attribute__ ((format(printf,4,5))); @@ -24,6 +27,7 @@ void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) extern const int syslog_priorities[]; #endif +/* keep this same as FCGI_ERROR */ enum { ZLOG_DEBUG = 1, ZLOG_NOTICE = 2, diff --git a/sapi/fpm/init.d.php-fpm.in b/sapi/fpm/init.d.php-fpm.in index 020b942f14..42f94a8a26 100644 --- a/sapi/fpm/init.d.php-fpm.in +++ b/sapi/fpm/init.d.php-fpm.in @@ -144,8 +144,12 @@ case "$1" in echo " done" ;; + configtest) + $php_fpm_BIN -t + ;; + *) - echo "Usage: $0 {start|stop|force-quit|restart|reload|status}" + echo "Usage: $0 {start|stop|force-quit|restart|reload|status|configtest}" exit 1 ;; diff --git a/sapi/fpm/php-fpm.conf.in b/sapi/fpm/php-fpm.conf.in index dd037db768..9e5b593f83 100644 --- a/sapi/fpm/php-fpm.conf.in +++ b/sapi/fpm/php-fpm.conf.in @@ -6,14 +6,6 @@ ; prefix (@prefix@). This prefix can be dynamically changed by using the ; '-p' argument from the command line. -; Include one or more files. If glob(3) exists, it is used to include a bunch of -; files from a glob(3) pattern. This directive can be used everywhere in the -; file. -; Relative path can also be used. They will be prefixed by: -; - the global prefix if it's been set (-p argument) -; - @prefix@ otherwise -;include=etc/fpm.d/*.conf - ;;;;;;;;;;;;;;;;;; ; Global Options ; ;;;;;;;;;;;;;;;;;; @@ -55,7 +47,7 @@ ; Default Value: 0 ;emergency_restart_threshold = 0 -; Interval of time used by emergency_restart_interval to determine when +; Interval of time used by emergency_restart_interval to determine when ; a graceful restart will be initiated. This can be useful to work around ; accidental corruptions in an accelerator's shared memory. ; Available Units: s(econds), m(inutes), h(ours), or d(ays) @@ -87,11 +79,11 @@ ; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging. ; Default Value: yes ;daemonize = yes - + ; Set open file descriptor rlimit for the master process. ; Default Value: system defined value ;rlimit_files = 1024 - + ; Set max core size rlimit for the master process. ; Possible Values: 'unlimited' or an integer greater or equal to 0 ; Default Value: system defined value @@ -116,7 +108,7 @@ ;systemd_interval = 10 ;;;;;;;;;;;;;;;;;;;; -; Pool Definitions ; +; Pool Definitions ; ;;;;;;;;;;;;;;;;;;;; ; Multiple pools of child processes may be started with different listening @@ -124,414 +116,10 @@ ; used in logs and stats. There is no limitation on the number of pools which ; FPM can handle. Your system will tell you anyway :) -; Start a new pool named 'www'. -; the variable $pool can we used in any directive and will be replaced by the -; pool name ('www' here) -[www] - -; Per pool prefix -; It only applies on the following directives: -; - 'access.log' -; - 'slowlog' -; - 'listen' (unixsocket) -; - 'chroot' -; - 'chdir' -; - 'php_values' -; - 'php_admin_values' -; When not set, the global prefix (or @php_fpm_prefix@) applies instead. -; Note: This directive can also be relative to the global prefix. -; Default Value: none -;prefix = /path/to/pools/$pool - -; Unix user/group of processes -; Note: The user is mandatory. If the group is not set, the default user's group -; will be used. -user = @php_fpm_user@ -group = @php_fpm_group@ - -; The address on which to accept FastCGI requests. -; Valid syntaxes are: -; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on -; a specific port; -; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on -; a specific port; -; 'port' - to listen on a TCP socket to all IPv4 addresses on a -; specific port; -; '[::]:port' - to listen on a TCP socket to all addresses -; (IPv6 and IPv4-mapped) on a specific port; -; '/path/to/unix/socket' - to listen on a unix socket. -; Note: This value is mandatory. -listen = 127.0.0.1:9000 - -; Set listen(2) backlog. -; Default Value: 65535 (-1 on FreeBSD and OpenBSD) -;listen.backlog = 65535 - -; Set permissions for unix socket, if one is used. In Linux, read/write -; permissions must be set in order to allow connections from a web server. Many -; BSD-derived systems allow connections regardless of permissions. -; Default Values: user and group are set as the running user -; mode is set to 0660 -;listen.owner = @php_fpm_user@ -;listen.group = @php_fpm_group@ -;listen.mode = 0660 -; When POSIX Access Control Lists are supported you can set them using -; these options, value is a comma separated list of user/group names. -; When set, listen.owner and listen.group are ignored -;listen.acl_users = -;listen.acl_groups = - -; List of addresses (IPv4/IPv6) of FastCGI clients which are allowed to connect. -; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original -; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address -; must be separated by a comma. If this value is left blank, connections will be -; accepted from any ip address. -; Default Value: any -;listen.allowed_clients = 127.0.0.1 - -; Specify the nice(2) priority to apply to the pool processes (only if set) -; The value can vary from -19 (highest priority) to 20 (lower priority) -; Note: - It will only work if the FPM master process is launched as root -; - The pool processes will inherit the master process priority -; unless it specified otherwise -; Default Value: no set -; process.priority = -19 - -; Choose how the process manager will control the number of child processes. -; Possible Values: -; static - a fixed number (pm.max_children) of child processes; -; dynamic - the number of child processes are set dynamically based on the -; following directives. With this process management, there will be -; always at least 1 children. -; pm.max_children - the maximum number of children that can -; be alive at the same time. -; pm.start_servers - the number of children created on startup. -; pm.min_spare_servers - the minimum number of children in 'idle' -; state (waiting to process). If the number -; of 'idle' processes is less than this -; number then some children will be created. -; pm.max_spare_servers - the maximum number of children in 'idle' -; state (waiting to process). If the number -; of 'idle' processes is greater than this -; number then some children will be killed. -; ondemand - no children are created at startup. Children will be forked when -; new requests will connect. The following parameter are used: -; pm.max_children - the maximum number of children that -; can be alive at the same time. -; pm.process_idle_timeout - The number of seconds after which -; an idle process will be killed. -; Note: This value is mandatory. -pm = dynamic - -; The number of child processes to be created when pm is set to 'static' and the -; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'. -; This value sets the limit on the number of simultaneous requests that will be -; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. -; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP -; CGI. The below defaults are based on a server without much resources. Don't -; forget to tweak pm.* to fit your needs. -; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand' -; Note: This value is mandatory. -pm.max_children = 5 - -; The number of child processes created on startup. -; Note: Used only when pm is set to 'dynamic' -; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 -pm.start_servers = 2 - -; The desired minimum number of idle server processes. -; Note: Used only when pm is set to 'dynamic' -; Note: Mandatory when pm is set to 'dynamic' -pm.min_spare_servers = 1 - -; The desired maximum number of idle server processes. -; Note: Used only when pm is set to 'dynamic' -; Note: Mandatory when pm is set to 'dynamic' -pm.max_spare_servers = 3 - -; The number of seconds after which an idle process will be killed. -; Note: Used only when pm is set to 'ondemand' -; Default Value: 10s -;pm.process_idle_timeout = 10s; - -; The number of requests each child process should execute before respawning. -; This can be useful to work around memory leaks in 3rd party libraries. For -; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS. -; Default Value: 0 -;pm.max_requests = 500 - -; The URI to view the FPM status page. If this value is not set, no URI will be -; recognized as a status page. It shows the following informations: -; pool - the name of the pool; -; process manager - static, dynamic or ondemand; -; start time - the date and time FPM has started; -; start since - number of seconds since FPM has started; -; accepted conn - the number of request accepted by the pool; -; listen queue - the number of request in the queue of pending -; connections (see backlog in listen(2)); -; max listen queue - the maximum number of requests in the queue -; of pending connections since FPM has started; -; listen queue len - the size of the socket queue of pending connections; -; idle processes - the number of idle processes; -; active processes - the number of active processes; -; total processes - the number of idle + active processes; -; max active processes - the maximum number of active processes since FPM -; has started; -; max children reached - number of times, the process limit has been reached, -; when pm tries to start more children (works only for -; pm 'dynamic' and 'ondemand'); -; Value are updated in real time. -; Example output: -; pool: www -; process manager: static -; start time: 01/Jul/2011:17:53:49 +0200 -; start since: 62636 -; accepted conn: 190460 -; listen queue: 0 -; max listen queue: 1 -; listen queue len: 42 -; idle processes: 4 -; active processes: 11 -; total processes: 15 -; max active processes: 12 -; max children reached: 0 -; -; By default the status page output is formatted as text/plain. Passing either -; 'html', 'xml' or 'json' in the query string will return the corresponding -; output syntax. Example: -; http://www.foo.bar/status -; http://www.foo.bar/status?json -; http://www.foo.bar/status?html -; http://www.foo.bar/status?xml -; -; By default the status page only outputs short status. Passing 'full' in the -; query string will also return status for each pool process. -; Example: -; http://www.foo.bar/status?full -; http://www.foo.bar/status?json&full -; http://www.foo.bar/status?html&full -; http://www.foo.bar/status?xml&full -; The Full status returns for each process: -; pid - the PID of the process; -; state - the state of the process (Idle, Running, ...); -; start time - the date and time the process has started; -; start since - the number of seconds since the process has started; -; requests - the number of requests the process has served; -; request duration - the duration in µs of the requests; -; request method - the request method (GET, POST, ...); -; request URI - the request URI with the query string; -; content length - the content length of the request (only with POST); -; user - the user (PHP_AUTH_USER) (or '-' if not set); -; script - the main script called (or '-' if not set); -; last request cpu - the %cpu the last request consumed -; it's always 0 if the process is not in Idle state -; because CPU calculation is done when the request -; processing has terminated; -; last request memory - the max amount of memory the last request consumed -; it's always 0 if the process is not in Idle state -; because memory calculation is done when the request -; processing has terminated; -; If the process is in Idle state, then informations are related to the -; last request the process has served. Otherwise informations are related to -; the current request being served. -; Example output: -; ************************ -; pid: 31330 -; state: Running -; start time: 01/Jul/2011:17:53:49 +0200 -; start since: 63087 -; requests: 12808 -; request duration: 1250261 -; request method: GET -; request URI: /test_mem.php?N=10000 -; content length: 0 -; user: - -; script: /home/fat/web/docs/php/test_mem.php -; last request cpu: 0.00 -; last request memory: 0 -; -; Note: There is a real-time FPM status monitoring sample web page available -; It's available in: @EXPANDED_DATADIR@/fpm/status.html -; -; Note: The value must start with a leading slash (/). The value can be -; anything, but it may not be a good idea to use the .php extension or it -; may conflict with a real PHP file. -; Default Value: not set -;pm.status_path = /status - -; The ping URI to call the monitoring page of FPM. If this value is not set, no -; URI will be recognized as a ping page. This could be used to test from outside -; that FPM is alive and responding, or to -; - create a graph of FPM availability (rrd or such); -; - remove a server from a group if it is not responding (load balancing); -; - trigger alerts for the operating team (24/7). -; Note: The value must start with a leading slash (/). The value can be -; anything, but it may not be a good idea to use the .php extension or it -; may conflict with a real PHP file. -; Default Value: not set -;ping.path = /ping - -; This directive may be used to customize the response of a ping request. The -; response is formatted as text/plain with a 200 response code. -; Default Value: pong -;ping.response = pong - -; The access log file -; Default: not set -;access.log = log/$pool.access.log - -; The access log format. -; The following syntax is allowed -; %%: the '%' character -; %C: %CPU used by the request -; it can accept the following format: -; - %{user}C for user CPU only -; - %{system}C for system CPU only -; - %{total}C for user + system CPU (default) -; %d: time taken to serve the request -; it can accept the following format: -; - %{seconds}d (default) -; - %{miliseconds}d -; - %{mili}d -; - %{microseconds}d -; - %{micro}d -; %e: an environment variable (same as $_ENV or $_SERVER) -; it must be associated with embraces to specify the name of the env -; variable. Some exemples: -; - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e -; - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e -; %f: script filename -; %l: content-length of the request (for POST request only) -; %m: request method -; %M: peak of memory allocated by PHP -; it can accept the following format: -; - %{bytes}M (default) -; - %{kilobytes}M -; - %{kilo}M -; - %{megabytes}M -; - %{mega}M -; %n: pool name -; %o: output header -; it must be associated with embraces to specify the name of the header: -; - %{Content-Type}o -; - %{X-Powered-By}o -; - %{Transfert-Encoding}o -; - .... -; %p: PID of the child that serviced the request -; %P: PID of the parent of the child that serviced the request -; %q: the query string -; %Q: the '?' character if query string exists -; %r: the request URI (without the query string, see %q and %Q) -; %R: remote IP address -; %s: status (response code) -; %t: server time the request was received -; it can accept a strftime(3) format: -; %d/%b/%Y:%H:%M:%S %z (default) -; %T: time the log has been written (the request has finished) -; it can accept a strftime(3) format: -; %d/%b/%Y:%H:%M:%S %z (default) -; %u: remote user -; -; Default: "%R - %u %t \"%m %r\" %s" -;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%" - -; The log file for slow requests -; Default Value: not set -; Note: slowlog is mandatory if request_slowlog_timeout is set -;slowlog = log/$pool.log.slow - -; The timeout for serving a single request after which a PHP backtrace will be -; dumped to the 'slowlog' file. A value of '0s' means 'off'. -; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) -; Default Value: 0 -;request_slowlog_timeout = 0 - -; The timeout for serving a single request after which the worker process will -; be killed. This option should be used when the 'max_execution_time' ini option -; does not stop script execution for some reason. A value of '0' means 'off'. -; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) -; Default Value: 0 -;request_terminate_timeout = 0 - -; Set open file descriptor rlimit. -; Default Value: system defined value -;rlimit_files = 1024 - -; Set max core size rlimit. -; Possible Values: 'unlimited' or an integer greater or equal to 0 -; Default Value: system defined value -;rlimit_core = 0 - -; Chroot to this directory at the start. This value must be defined as an -; absolute path. When this value is not set, chroot is not used. -; Note: you can prefix with '$prefix' to chroot to the pool prefix or one -; of its subdirectories. If the pool prefix is not set, the global prefix -; will be used instead. -; Note: chrooting is a great security feature and should be used whenever -; possible. However, all PHP paths will be relative to the chroot -; (error_log, sessions.save_path, ...). -; Default Value: not set -;chroot = - -; Chdir to this directory at the start. -; Note: relative path can be used. -; Default Value: current directory or / when chroot -;chdir = /var/www - -; Redirect worker stdout and stderr into main error log. If not set, stdout and -; stderr will be redirected to /dev/null according to FastCGI specs. -; Note: on highloaded environement, this can cause some delay in the page -; process time (several ms). -; Default Value: no -;catch_workers_output = yes - -; Clear environment in FPM workers -; Prevents arbitrary environment variables from reaching FPM worker processes -; by clearing the environment in workers before env vars specified in this -; pool configuration are added. -; Setting to "no" will make all environment variables available to PHP code -; via getenv(), $_ENV and $_SERVER. -; Default Value: yes -;clear_env = no - -; Limits the extensions of the main script FPM will allow to parse. This can -; prevent configuration mistakes on the web server side. You should only limit -; FPM to .php extensions to prevent malicious users to use other extensions to -; exectute php code. -; Note: set an empty value to allow all extensions. -; Default Value: .php -;security.limit_extensions = .php .php3 .php4 .php5 - -; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from -; the current environment. -; Default Value: clean env -;env[HOSTNAME] = $HOSTNAME -;env[PATH] = /usr/local/bin:/usr/bin:/bin -;env[TMP] = /tmp -;env[TMPDIR] = /tmp -;env[TEMP] = /tmp - -; Additional php.ini defines, specific to this pool of workers. These settings -; overwrite the values previously defined in the php.ini. The directives are the -; same as the PHP SAPI: -; php_value/php_flag - you can set classic ini defines which can -; be overwritten from PHP call 'ini_set'. -; php_admin_value/php_admin_flag - these directives won't be overwritten by -; PHP call 'ini_set' -; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no. - -; Defining 'extension' will load the corresponding shared extension from -; extension_dir. Defining 'disable_functions' or 'disable_classes' will not -; overwrite previously defined php.ini values, but will append the new value -; instead. - -; Note: path INI options can be relative and will be expanded with the prefix -; (pool, global or @prefix@) - -; Default Value: nothing is defined by default except the values in php.ini and -; specified at startup with the -d argument -;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com -;php_flag[display_errors] = off -;php_admin_value[error_log] = /var/log/fpm-php.www.log -;php_admin_flag[log_errors] = on -;php_admin_value[memory_limit] = 32M +; Include one or more files. If glob(3) exists, it is used to include a bunch of +; files from a glob(3) pattern. This directive can be used everywhere in the +; file. +; Relative path can also be used. They will be prefixed by: +; - the global prefix if it's been set (-p argument) +; - @prefix@ otherwise +include=@php_fpm_sysconfdir@/php-fpm.d/*.conf diff --git a/sapi/fpm/tests/003.phpt b/sapi/fpm/tests/003.phpt index f928626ecc..a4c04ae9ce 100644 --- a/sapi/fpm/tests/003.phpt +++ b/sapi/fpm/tests/003.phpt @@ -1,7 +1,10 @@ --TEST-- FPM: Test IPv6 support --SKIPIF-- -<?php include "skipif.inc"; ?> +<?php include "skipif.inc"; + @stream_socket_client('tcp://[::1]:0', $errno); + if ($errno != 111) die('skip IPv6 not supported.'); +?> --FILE-- <?php diff --git a/sapi/fpm/tests/004.phpt b/sapi/fpm/tests/004.phpt index 2a4d666c64..565819aed4 100644 --- a/sapi/fpm/tests/004.phpt +++ b/sapi/fpm/tests/004.phpt @@ -1,7 +1,10 @@ --TEST-- FPM: Test IPv4/IPv6 support --SKIPIF-- -<?php include "skipif.inc"; ?> +<?php include "skipif.inc"; + @stream_socket_client('tcp://[::1]:0', $errno); + if ($errno != 111) die('skip IPv6 not supported.'); +?> --FILE-- <?php diff --git a/sapi/fpm/tests/005.phpt b/sapi/fpm/tests/005.phpt index c565c2a9eb..6c8210ec8e 100644 --- a/sapi/fpm/tests/005.phpt +++ b/sapi/fpm/tests/005.phpt @@ -1,7 +1,10 @@ --TEST-- FPM: Test IPv4 allowed clients --SKIPIF-- -<?php include "skipif.inc"; ?> +<?php include "skipif.inc"; + @stream_socket_client('tcp://[::1]:0', $errno); + if ($errno != 111) die('skip IPv6 not supported.'); +?> --FILE-- <?php diff --git a/sapi/fpm/tests/006.phpt b/sapi/fpm/tests/006.phpt index a12ca253d2..e552087335 100644 --- a/sapi/fpm/tests/006.phpt +++ b/sapi/fpm/tests/006.phpt @@ -1,7 +1,10 @@ --TEST-- FPM: Test IPv6 allowed clients (bug #68428) --SKIPIF-- -<?php include "skipif.inc"; ?> +<?php include "skipif.inc"; + @stream_socket_client('tcp://[::1]:0', $errno); + if ($errno != 111) die('skip IPv6 not supported.'); +?> --FILE-- <?php diff --git a/sapi/fpm/tests/007.phpt b/sapi/fpm/tests/007.phpt index 0d817907cf..6329af209a 100644 --- a/sapi/fpm/tests/007.phpt +++ b/sapi/fpm/tests/007.phpt @@ -1,7 +1,10 @@ --TEST-- FPM: Test IPv6 all addresses and access_log (bug #68421) --SKIPIF-- -<?php include "skipif.inc"; ?> +<?php include "skipif.inc"; + @stream_socket_client('tcp://[::1]:0', $errno); + if ($errno != 111) die('skip IPv6 not supported.'); +?> --FILE-- <?php diff --git a/sapi/fpm/tests/008.phpt b/sapi/fpm/tests/008.phpt index 60f1ea6ebd..732a717aad 100644 --- a/sapi/fpm/tests/008.phpt +++ b/sapi/fpm/tests/008.phpt @@ -1,7 +1,22 @@ --TEST-- FPM: Test multi pool (dynamic + ondemand + static) (bug #68423) --SKIPIF-- -<?php include "skipif.inc"; ?> +<?php +include "skipif.inc"; + +$cfg = <<<EOT +[global] +[poold_ondemand] +listen=127.0.0.1:9000 +pm = ondemand +pm.max_children = 2 +pm.process_idle_timeout = 10 +EOT; + +if (test_fpm_conf($cfg, $msg) == false) { + die("skip " . $msg); +} +?> --FILE-- <?php diff --git a/sapi/fpm/tests/010.phpt b/sapi/fpm/tests/010.phpt index 5146e3c84f..49e1a07923 100644 --- a/sapi/fpm/tests/010.phpt +++ b/sapi/fpm/tests/010.phpt @@ -22,11 +22,8 @@ error_log = $logfile [unconfined] listen = 127.0.0.1:$port pm.status_path = /status -pm = dynamic -pm.max_children = 5 -pm.start_servers = 2 -pm.min_spare_servers = 1 -pm.max_spare_servers = 3 +pm = static +pm.max_children = 1 EOT; $fpm = run_fpm($cfg, $tail); @@ -65,16 +62,16 @@ Cache-Control: %s Content-type: text/plain%s pool: unconfined -process manager: dynamic +process manager: static start time: %s start since: %d accepted conn: 1 listen queue: 0 max listen queue: 0 listen queue len: %d -idle processes: 1 +idle processes: 0 active processes: 1 -total processes: 2 +total processes: 1 max active processes: 1 max children reached: 0 slow requests: 0 diff --git a/sapi/fpm/tests/016.phpt b/sapi/fpm/tests/016.phpt index 1a9e8e7577..a5084f18f3 100644 --- a/sapi/fpm/tests/016.phpt +++ b/sapi/fpm/tests/016.phpt @@ -1,7 +1,22 @@ --TEST-- FPM: Test splited configuration and load order #68391 --SKIPIF-- -<?php include "skipif.inc"; ?> +<?php +include "skipif.inc"; + +$cfg = <<<EOT +[global] +[poold_ondemand] +listen=127.0.0.1:9000 +pm = ondemand +pm.max_children = 2 +pm.process_idle_timeout = 10 +EOT; + +if (test_fpm_conf($cfg, $msg) == false) { + die("skip " . $msg); +} +?> --FILE-- <?php @@ -84,4 +99,4 @@ Done unlink($name); } @rmdir($logdir); -?>
\ No newline at end of file +?> diff --git a/sapi/fpm/tests/021-uds-acl.phpt b/sapi/fpm/tests/021-uds-acl.phpt index f39c526418..f5da086702 100644 --- a/sapi/fpm/tests/021-uds-acl.phpt +++ b/sapi/fpm/tests/021-uds-acl.phpt @@ -4,9 +4,16 @@ FPM: Test Unix Domain Socket with Posix ACL <?php include "skipif.inc"; if (!(file_exists('/usr/bin/getfacl') && file_exists('/etc/passwd') && file_exists('/etc/group'))) die ("skip missing getfacl command"); +$cfg = <<<EOT +[global] +[unconfined] +listen = 127.0.0.1:9999 +listen.acl_users = nobody +listen.acl_groups = nobody +listen.mode = 0600 +EOT; +if (test_fpm_conf($cfg, $msg) == false) { die("skip " . $msg); } ?> ---XFAIL-- -Mark as XFAIL because --with-fpm-acl is not enabled in default build --FILE-- <?php diff --git a/sapi/fpm/tests/include.inc b/sapi/fpm/tests/include.inc index b195fad507..5cbb08b478 100644 --- a/sapi/fpm/tests/include.inc +++ b/sapi/fpm/tests/include.inc @@ -52,6 +52,18 @@ function run_fpm($config, &$out = false, $extra_args = '') /* {{{ */ } /* }}} */ +function test_fpm_conf($config, &$msg = NULL) { /* {{{ */ + $cfg = dirname(__FILE__).'/test-fpm-config.tmp'; + file_put_contents($cfg, $config); + exec(get_fpm_path() . ' -t -y ' . $cfg . ' 2>&1', $output, $code); + if ($code) { + $msg = preg_replace("/\[.+?\]/", "", $output[0]); + return false; + } + return true; +} +/* }}} */ + function run_fpm_till($needle, $config, $max = 10) /* {{{ */ { $i = 0; @@ -76,7 +88,7 @@ function run_fpm_till($needle, $config, $max = 10) /* {{{ */ } /* }}} */ -function fpm_display_log($tail, $n=1, $ignore='systemd') { +function fpm_display_log($tail, $n=1, $ignore='systemd') { /* {{{ */ while ($n) { $a = fgets($tail); if (empty($ignore) || !strpos($a, $ignore)) { @@ -84,9 +96,9 @@ function fpm_display_log($tail, $n=1, $ignore='systemd') { $n--; } } -} +} /* }}} */ -function run_request($host, $port, $uri='/ping', $query='') { +function run_request($host, $port, $uri='/ping', $query='') { /* {{{ */ require_once 'fcgi.inc'; $client = new Adoy\FastCGI\Client($host, $port); $params = array( @@ -109,3 +121,4 @@ function run_request($host, $port, $uri='/ping', $query='') { ); return $client->request($params, false)."\n"; } +/* }}} */ diff --git a/sapi/fpm/www.conf.in b/sapi/fpm/www.conf.in new file mode 100644 index 0000000000..394e27819d --- /dev/null +++ b/sapi/fpm/www.conf.in @@ -0,0 +1,413 @@ +; Start a new pool named 'www'. +; the variable $pool can we used in any directive and will be replaced by the +; pool name ('www' here) +[www] + +; Per pool prefix +; It only applies on the following directives: +; - 'access.log' +; - 'slowlog' +; - 'listen' (unixsocket) +; - 'chroot' +; - 'chdir' +; - 'php_values' +; - 'php_admin_values' +; When not set, the global prefix (or @php_fpm_prefix@) applies instead. +; Note: This directive can also be relative to the global prefix. +; Default Value: none +;prefix = /path/to/pools/$pool + +; Unix user/group of processes +; Note: The user is mandatory. If the group is not set, the default user's group +; will be used. +user = @php_fpm_user@ +group = @php_fpm_group@ + +; The address on which to accept FastCGI requests. +; Valid syntaxes are: +; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on +; a specific port; +; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on +; a specific port; +; 'port' - to listen on a TCP socket to all addresses +; (IPv6 and IPv4-mapped) on a specific port; +; '/path/to/unix/socket' - to listen on a unix socket. +; Note: This value is mandatory. +listen = 127.0.0.1:9000 + +; Set listen(2) backlog. +; Default Value: 511 (-1 on FreeBSD and OpenBSD) +;listen.backlog = 511 + +; Set permissions for unix socket, if one is used. In Linux, read/write +; permissions must be set in order to allow connections from a web server. Many +; BSD-derived systems allow connections regardless of permissions. +; Default Values: user and group are set as the running user +; mode is set to 0660 +;listen.owner = @php_fpm_user@ +;listen.group = @php_fpm_group@ +;listen.mode = 0660 +; When POSIX Access Control Lists are supported you can set them using +; these options, value is a comma separated list of user/group names. +; When set, listen.owner and listen.group are ignored +;listen.acl_users = +;listen.acl_groups = + +; List of addresses (IPv4/IPv6) of FastCGI clients which are allowed to connect. +; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original +; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address +; must be separated by a comma. If this value is left blank, connections will be +; accepted from any ip address. +; Default Value: any +;listen.allowed_clients = 127.0.0.1 + +; Specify the nice(2) priority to apply to the pool processes (only if set) +; The value can vary from -19 (highest priority) to 20 (lower priority) +; Note: - It will only work if the FPM master process is launched as root +; - The pool processes will inherit the master process priority +; unless it specified otherwise +; Default Value: no set +; process.priority = -19 + +; Choose how the process manager will control the number of child processes. +; Possible Values: +; static - a fixed number (pm.max_children) of child processes; +; dynamic - the number of child processes are set dynamically based on the +; following directives. With this process management, there will be +; always at least 1 children. +; pm.max_children - the maximum number of children that can +; be alive at the same time. +; pm.start_servers - the number of children created on startup. +; pm.min_spare_servers - the minimum number of children in 'idle' +; state (waiting to process). If the number +; of 'idle' processes is less than this +; number then some children will be created. +; pm.max_spare_servers - the maximum number of children in 'idle' +; state (waiting to process). If the number +; of 'idle' processes is greater than this +; number then some children will be killed. +; ondemand - no children are created at startup. Children will be forked when +; new requests will connect. The following parameter are used: +; pm.max_children - the maximum number of children that +; can be alive at the same time. +; pm.process_idle_timeout - The number of seconds after which +; an idle process will be killed. +; Note: This value is mandatory. +pm = dynamic + +; The number of child processes to be created when pm is set to 'static' and the +; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'. +; This value sets the limit on the number of simultaneous requests that will be +; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. +; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP +; CGI. The below defaults are based on a server without much resources. Don't +; forget to tweak pm.* to fit your needs. +; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand' +; Note: This value is mandatory. +pm.max_children = 5 + +; The number of child processes created on startup. +; Note: Used only when pm is set to 'dynamic' +; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 +pm.start_servers = 2 + +; The desired minimum number of idle server processes. +; Note: Used only when pm is set to 'dynamic' +; Note: Mandatory when pm is set to 'dynamic' +pm.min_spare_servers = 1 + +; The desired maximum number of idle server processes. +; Note: Used only when pm is set to 'dynamic' +; Note: Mandatory when pm is set to 'dynamic' +pm.max_spare_servers = 3 + +; The number of seconds after which an idle process will be killed. +; Note: Used only when pm is set to 'ondemand' +; Default Value: 10s +;pm.process_idle_timeout = 10s; + +; The number of requests each child process should execute before respawning. +; This can be useful to work around memory leaks in 3rd party libraries. For +; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS. +; Default Value: 0 +;pm.max_requests = 500 + +; The URI to view the FPM status page. If this value is not set, no URI will be +; recognized as a status page. It shows the following informations: +; pool - the name of the pool; +; process manager - static, dynamic or ondemand; +; start time - the date and time FPM has started; +; start since - number of seconds since FPM has started; +; accepted conn - the number of request accepted by the pool; +; listen queue - the number of request in the queue of pending +; connections (see backlog in listen(2)); +; max listen queue - the maximum number of requests in the queue +; of pending connections since FPM has started; +; listen queue len - the size of the socket queue of pending connections; +; idle processes - the number of idle processes; +; active processes - the number of active processes; +; total processes - the number of idle + active processes; +; max active processes - the maximum number of active processes since FPM +; has started; +; max children reached - number of times, the process limit has been reached, +; when pm tries to start more children (works only for +; pm 'dynamic' and 'ondemand'); +; Value are updated in real time. +; Example output: +; pool: www +; process manager: static +; start time: 01/Jul/2011:17:53:49 +0200 +; start since: 62636 +; accepted conn: 190460 +; listen queue: 0 +; max listen queue: 1 +; listen queue len: 42 +; idle processes: 4 +; active processes: 11 +; total processes: 15 +; max active processes: 12 +; max children reached: 0 +; +; By default the status page output is formatted as text/plain. Passing either +; 'html', 'xml' or 'json' in the query string will return the corresponding +; output syntax. Example: +; http://www.foo.bar/status +; http://www.foo.bar/status?json +; http://www.foo.bar/status?html +; http://www.foo.bar/status?xml +; +; By default the status page only outputs short status. Passing 'full' in the +; query string will also return status for each pool process. +; Example: +; http://www.foo.bar/status?full +; http://www.foo.bar/status?json&full +; http://www.foo.bar/status?html&full +; http://www.foo.bar/status?xml&full +; The Full status returns for each process: +; pid - the PID of the process; +; state - the state of the process (Idle, Running, ...); +; start time - the date and time the process has started; +; start since - the number of seconds since the process has started; +; requests - the number of requests the process has served; +; request duration - the duration in µs of the requests; +; request method - the request method (GET, POST, ...); +; request URI - the request URI with the query string; +; content length - the content length of the request (only with POST); +; user - the user (PHP_AUTH_USER) (or '-' if not set); +; script - the main script called (or '-' if not set); +; last request cpu - the %cpu the last request consumed +; it's always 0 if the process is not in Idle state +; because CPU calculation is done when the request +; processing has terminated; +; last request memory - the max amount of memory the last request consumed +; it's always 0 if the process is not in Idle state +; because memory calculation is done when the request +; processing has terminated; +; If the process is in Idle state, then informations are related to the +; last request the process has served. Otherwise informations are related to +; the current request being served. +; Example output: +; ************************ +; pid: 31330 +; state: Running +; start time: 01/Jul/2011:17:53:49 +0200 +; start since: 63087 +; requests: 12808 +; request duration: 1250261 +; request method: GET +; request URI: /test_mem.php?N=10000 +; content length: 0 +; user: - +; script: /home/fat/web/docs/php/test_mem.php +; last request cpu: 0.00 +; last request memory: 0 +; +; Note: There is a real-time FPM status monitoring sample web page available +; It's available in: @EXPANDED_DATADIR@/fpm/status.html +; +; Note: The value must start with a leading slash (/). The value can be +; anything, but it may not be a good idea to use the .php extension or it +; may conflict with a real PHP file. +; Default Value: not set +;pm.status_path = /status + +; The ping URI to call the monitoring page of FPM. If this value is not set, no +; URI will be recognized as a ping page. This could be used to test from outside +; that FPM is alive and responding, or to +; - create a graph of FPM availability (rrd or such); +; - remove a server from a group if it is not responding (load balancing); +; - trigger alerts for the operating team (24/7). +; Note: The value must start with a leading slash (/). The value can be +; anything, but it may not be a good idea to use the .php extension or it +; may conflict with a real PHP file. +; Default Value: not set +;ping.path = /ping + +; This directive may be used to customize the response of a ping request. The +; response is formatted as text/plain with a 200 response code. +; Default Value: pong +;ping.response = pong + +; The access log file +; Default: not set +;access.log = log/$pool.access.log + +; The access log format. +; The following syntax is allowed +; %%: the '%' character +; %C: %CPU used by the request +; it can accept the following format: +; - %{user}C for user CPU only +; - %{system}C for system CPU only +; - %{total}C for user + system CPU (default) +; %d: time taken to serve the request +; it can accept the following format: +; - %{seconds}d (default) +; - %{miliseconds}d +; - %{mili}d +; - %{microseconds}d +; - %{micro}d +; %e: an environment variable (same as $_ENV or $_SERVER) +; it must be associated with embraces to specify the name of the env +; variable. Some exemples: +; - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e +; - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e +; %f: script filename +; %l: content-length of the request (for POST request only) +; %m: request method +; %M: peak of memory allocated by PHP +; it can accept the following format: +; - %{bytes}M (default) +; - %{kilobytes}M +; - %{kilo}M +; - %{megabytes}M +; - %{mega}M +; %n: pool name +; %o: output header +; it must be associated with embraces to specify the name of the header: +; - %{Content-Type}o +; - %{X-Powered-By}o +; - %{Transfert-Encoding}o +; - .... +; %p: PID of the child that serviced the request +; %P: PID of the parent of the child that serviced the request +; %q: the query string +; %Q: the '?' character if query string exists +; %r: the request URI (without the query string, see %q and %Q) +; %R: remote IP address +; %s: status (response code) +; %t: server time the request was received +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; The strftime(3) format must be encapsuled in a %{<strftime_format>}t tag +; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t +; %T: time the log has been written (the request has finished) +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; The strftime(3) format must be encapsuled in a %{<strftime_format>}t tag +; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t +; %u: remote user +; +; Default: "%R - %u %t \"%m %r\" %s" +;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%" + +; The log file for slow requests +; Default Value: not set +; Note: slowlog is mandatory if request_slowlog_timeout is set +;slowlog = log/$pool.log.slow + +; The timeout for serving a single request after which a PHP backtrace will be +; dumped to the 'slowlog' file. A value of '0s' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 +;request_slowlog_timeout = 0 + +; The timeout for serving a single request after which the worker process will +; be killed. This option should be used when the 'max_execution_time' ini option +; does not stop script execution for some reason. A value of '0' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 +;request_terminate_timeout = 0 + +; Set open file descriptor rlimit. +; Default Value: system defined value +;rlimit_files = 1024 + +; Set max core size rlimit. +; Possible Values: 'unlimited' or an integer greater or equal to 0 +; Default Value: system defined value +;rlimit_core = 0 + +; Chroot to this directory at the start. This value must be defined as an +; absolute path. When this value is not set, chroot is not used. +; Note: you can prefix with '$prefix' to chroot to the pool prefix or one +; of its subdirectories. If the pool prefix is not set, the global prefix +; will be used instead. +; Note: chrooting is a great security feature and should be used whenever +; possible. However, all PHP paths will be relative to the chroot +; (error_log, sessions.save_path, ...). +; Default Value: not set +;chroot = + +; Chdir to this directory at the start. +; Note: relative path can be used. +; Default Value: current directory or / when chroot +;chdir = /var/www + +; Redirect worker stdout and stderr into main error log. If not set, stdout and +; stderr will be redirected to /dev/null according to FastCGI specs. +; Note: on highloaded environement, this can cause some delay in the page +; process time (several ms). +; Default Value: no +;catch_workers_output = yes + +; Clear environment in FPM workers +; Prevents arbitrary environment variables from reaching FPM worker processes +; by clearing the environment in workers before env vars specified in this +; pool configuration are added. +; Setting to "no" will make all environment variables available to PHP code +; via getenv(), $_ENV and $_SERVER. +; Default Value: yes +;clear_env = no + +; Limits the extensions of the main script FPM will allow to parse. This can +; prevent configuration mistakes on the web server side. You should only limit +; FPM to .php extensions to prevent malicious users to use other extensions to +; exectute php code. +; Note: set an empty value to allow all extensions. +; Default Value: .php +;security.limit_extensions = .php .php3 .php4 .php5 .php7 + +; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from +; the current environment. +; Default Value: clean env +;env[HOSTNAME] = $HOSTNAME +;env[PATH] = /usr/local/bin:/usr/bin:/bin +;env[TMP] = /tmp +;env[TMPDIR] = /tmp +;env[TEMP] = /tmp + +; Additional php.ini defines, specific to this pool of workers. These settings +; overwrite the values previously defined in the php.ini. The directives are the +; same as the PHP SAPI: +; php_value/php_flag - you can set classic ini defines which can +; be overwritten from PHP call 'ini_set'. +; php_admin_value/php_admin_flag - these directives won't be overwritten by +; PHP call 'ini_set' +; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no. + +; Defining 'extension' will load the corresponding shared extension from +; extension_dir. Defining 'disable_functions' or 'disable_classes' will not +; overwrite previously defined php.ini values, but will append the new value +; instead. + +; Note: path INI options can be relative and will be expanded with the prefix +; (pool, global or @prefix@) + +; Default Value: nothing is defined by default except the values in php.ini and +; specified at startup with the -d argument +;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com +;php_flag[display_errors] = off +;php_admin_value[error_log] = /var/log/fpm-php.www.log +;php_admin_flag[log_errors] = on +;php_admin_value[memory_limit] = 32M diff --git a/sapi/isapi/CREDITS b/sapi/isapi/CREDITS deleted file mode 100644 index 11c6fdc73c..0000000000 --- a/sapi/isapi/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -ISAPI -Andi Gutmans, Zeev Suraski diff --git a/sapi/isapi/config.m4 b/sapi/isapi/config.m4 deleted file mode 100644 index 6014bab09f..0000000000 --- a/sapi/isapi/config.m4 +++ /dev/null @@ -1,24 +0,0 @@ -dnl -dnl $Id$ -dnl - -PHP_ARG_WITH(isapi, for Zeus ISAPI support, -[ --with-isapi[=DIR] Build PHP as an ISAPI module for use with Zeus], no, no) - -if test "$PHP_ISAPI" != "no"; then - if test "$PHP_ISAPI" = "yes"; then - ZEUSPATH=/usr/local/zeus # the default - else - ZEUSPATH=$PHP_ISAPI - fi - test -f "$ZEUSPATH/web/include/httpext.h" || AC_MSG_ERROR(Unable to find httpext.h in $ZEUSPATH/web/include) - PHP_BUILD_THREAD_SAFE - AC_DEFINE(WITH_ZEUS, 1, [ ]) - PHP_ADD_INCLUDE($ZEUSPATH/web/include) - PHP_SELECT_SAPI(isapi, shared, php5isapi.c) - INSTALL_IT="\$(SHELL) \$(srcdir)/install-sh -m 0755 $SAPI_SHARED \$(INSTALL_ROOT)$ZEUSPATH/web/bin/" -fi - -dnl ## Local Variables: -dnl ## tab-width: 4 -dnl ## End: diff --git a/sapi/isapi/config.w32 b/sapi/isapi/config.w32 deleted file mode 100644 index 8012352744..0000000000 --- a/sapi/isapi/config.w32 +++ /dev/null @@ -1,13 +0,0 @@ -// vim:ft=javascript -// $Id$ - -ARG_ENABLE('isapi', 'Build ISAPI version of PHP', 'no'); - -if (PHP_ISAPI == "yes") { - if (PHP_ZTS == "no") { - WARNING("ISAPI module requires an --enable-zts build of PHP"); - } else { - SAPI('isapi', 'php5isapi.c', 'php' + PHP_VERSION + 'isapi.dll', '/D PHP5ISAPI_EXPORTS'); - ADD_FLAG('LDFLAGS_ISAPI', '/DEF:sapi\\isapi\\php5isapi.def'); - } -} diff --git a/sapi/isapi/php.sym b/sapi/isapi/php.sym deleted file mode 100644 index 34b50b851c..0000000000 --- a/sapi/isapi/php.sym +++ /dev/null @@ -1,5 +0,0 @@ -GetFilterVersion -HttpFilterProc -GetExtensionVersion -HttpExtensionProc -ZSLMain diff --git a/sapi/isapi/php5isapi.c b/sapi/isapi/php5isapi.c deleted file mode 100644 index dd1ef9ac1d..0000000000 --- a/sapi/isapi/php5isapi.c +++ /dev/null @@ -1,973 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 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: Zeev Suraski <zeev@zend.com> | - | Ben Mansell <ben@zeus.com> (Zeus Support) | - +----------------------------------------------------------------------+ - */ -/* $Id$ */ - -#include "php.h" -#include <httpext.h> -#include <httpfilt.h> -#include <httpext.h> -#include "php_main.h" -#include "SAPI.h" -#include "php_globals.h" -#include "ext/standard/info.h" -#include "php_variables.h" -#include "php_ini.h" - -#ifdef PHP_WIN32 -# include <process.h> -#else -# define __try -# define __except(val) -# define __declspec(foo) -#endif - - -#ifdef WITH_ZEUS -# include "httpext.h" -# include <errno.h> -# define GetLastError() errno -#endif - -#ifdef PHP_WIN32 -#define PHP_ENABLE_SEH -#endif - -/* -uncomment the following lines to turn off -exception trapping when running under a debugger - -#ifdef _DEBUG -#undef PHP_ENABLE_SEH -#endif -*/ - -#define MAX_STATUS_LENGTH sizeof("xxxx LONGEST POSSIBLE STATUS DESCRIPTION") -#define ISAPI_SERVER_VAR_BUF_SIZE 1024 -#define ISAPI_POST_DATA_BUF 1024 - -static zend_bool bFilterLoaded=0; -static zend_bool bTerminateThreadsOnError=0; - -static char *isapi_special_server_variable_names[] = { - "ALL_HTTP", - "HTTPS", -#ifndef WITH_ZEUS - "SCRIPT_NAME", -#endif - NULL -}; - -#define NUM_SPECIAL_VARS (sizeof(isapi_special_server_variable_names)/sizeof(char *)) -#define SPECIAL_VAR_ALL_HTTP 0 -#define SPECIAL_VAR_HTTPS 1 -#define SPECIAL_VAR_PHP_SELF 2 - -static char *isapi_server_variable_names[] = { - "AUTH_PASSWORD", - "AUTH_TYPE", - "AUTH_USER", - "CONTENT_LENGTH", - "CONTENT_TYPE", - "PATH_TRANSLATED", - "QUERY_STRING", - "REMOTE_ADDR", - "REMOTE_HOST", - "REMOTE_USER", - "REQUEST_METHOD", - "SERVER_NAME", - "SERVER_PORT", - "SERVER_PROTOCOL", - "SERVER_SOFTWARE", -#ifndef WITH_ZEUS - "APPL_MD_PATH", - "APPL_PHYSICAL_PATH", - "INSTANCE_ID", - "INSTANCE_META_PATH", - "LOGON_USER", - "REQUEST_URI", - "URL", -#else - "DOCUMENT_ROOT", -#endif - NULL -}; - - -static char *isapi_secure_server_variable_names[] = { - "CERT_COOKIE", - "CERT_FLAGS", - "CERT_ISSUER", - "CERT_KEYSIZE", - "CERT_SECRETKEYSIZE", - "CERT_SERIALNUMBER", - "CERT_SERVER_ISSUER", - "CERT_SERVER_SUBJECT", - "CERT_SUBJECT", - "HTTPS_KEYSIZE", - "HTTPS_SECRETKEYSIZE", - "HTTPS_SERVER_ISSUER", - "HTTPS_SERVER_SUBJECT", - "SERVER_PORT_SECURE", -#ifdef WITH_ZEUS - "SSL_CLIENT_CN", - "SSL_CLIENT_EMAIL", - "SSL_CLIENT_OU", - "SSL_CLIENT_O", - "SSL_CLIENT_L", - "SSL_CLIENT_ST", - "SSL_CLIENT_C", - "SSL_CLIENT_I_CN", - "SSL_CLIENT_I_EMAIL", - "SSL_CLIENT_I_OU", - "SSL_CLIENT_I_O", - "SSL_CLIENT_I_L", - "SSL_CLIENT_I_ST", - "SSL_CLIENT_I_C", -#endif - NULL -}; - - -static void php_info_isapi(ZEND_MODULE_INFO_FUNC_ARGS) -{ - char **p; - char variable_buf[ISAPI_SERVER_VAR_BUF_SIZE]; - DWORD variable_len; - char **all_variables[] = { - isapi_server_variable_names, - isapi_special_server_variable_names, - isapi_secure_server_variable_names, - NULL - }; - char ***server_variable_names; - LPEXTENSION_CONTROL_BLOCK lpECB; - - lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context); - - php_info_print_table_start(); - php_info_print_table_header(2, "Server Variable", "Value"); - server_variable_names = all_variables; - while (*server_variable_names) { - p = *server_variable_names; - while (*p) { - variable_len = ISAPI_SERVER_VAR_BUF_SIZE; - if (lpECB->GetServerVariable(lpECB->ConnID, *p, variable_buf, &variable_len) - && variable_buf[0]) { - php_info_print_table_row(2, *p, variable_buf); - } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - char *tmp_variable_buf; - - tmp_variable_buf = (char *) emalloc(variable_len); - if (lpECB->GetServerVariable(lpECB->ConnID, *p, tmp_variable_buf, &variable_len) - && variable_buf[0]) { - php_info_print_table_row(2, *p, tmp_variable_buf); - } - efree(tmp_variable_buf); - } - p++; - } - server_variable_names++; - } - php_info_print_table_end(); -} - - -static zend_module_entry php_isapi_module = { - STANDARD_MODULE_HEADER, - "ISAPI", - NULL, - NULL, - NULL, - NULL, - NULL, - php_info_isapi, - NULL, - STANDARD_MODULE_PROPERTIES -}; - - -static int sapi_isapi_ub_write(const char *str, uint str_length TSRMLS_DC) -{ - DWORD num_bytes = str_length; - LPEXTENSION_CONTROL_BLOCK ecb; - - ecb = (LPEXTENSION_CONTROL_BLOCK) SG(server_context); - if (ecb->WriteClient(ecb->ConnID, (char *) str, &num_bytes, HSE_IO_SYNC) == FALSE) { - php_handle_aborted_connection(); - } - return num_bytes; -} - - -static int sapi_isapi_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - return SAPI_HEADER_ADD; -} - - - -static void accumulate_header_length(sapi_header_struct *sapi_header, uint *total_length TSRMLS_DC) -{ - *total_length += sapi_header->header_len+2; -} - - -static void concat_header(sapi_header_struct *sapi_header, char **combined_headers_ptr TSRMLS_DC) -{ - memcpy(*combined_headers_ptr, sapi_header->header, sapi_header->header_len); - *combined_headers_ptr += sapi_header->header_len; - **combined_headers_ptr = '\r'; - (*combined_headers_ptr)++; - **combined_headers_ptr = '\n'; - (*combined_headers_ptr)++; -} - - -static int sapi_isapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - uint total_length = 2; /* account for the trailing \r\n */ - char *combined_headers, *combined_headers_ptr; - LPEXTENSION_CONTROL_BLOCK lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context); - HSE_SEND_HEADER_EX_INFO header_info; - sapi_header_struct default_content_type; - char *status_buf = NULL; - - /* Obtain headers length */ - if (SG(sapi_headers).send_default_content_type) { - sapi_get_default_content_type_header(&default_content_type TSRMLS_CC); - accumulate_header_length(&default_content_type, (void *) &total_length TSRMLS_CC); - } - zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) accumulate_header_length, (void *) &total_length TSRMLS_CC); - - /* Generate headers */ - combined_headers = (char *) emalloc(total_length+1); - combined_headers_ptr = combined_headers; - if (SG(sapi_headers).send_default_content_type) { - concat_header(&default_content_type, (void *) &combined_headers_ptr TSRMLS_CC); - sapi_free_header(&default_content_type); /* we no longer need it */ - } - zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) concat_header, (void *) &combined_headers_ptr TSRMLS_CC); - *combined_headers_ptr++ = '\r'; - *combined_headers_ptr++ = '\n'; - *combined_headers_ptr = 0; - - switch (SG(sapi_headers).http_response_code) { - case 200: - header_info.pszStatus = "200 OK"; - break; - case 302: - header_info.pszStatus = "302 Moved Temporarily"; - break; - case 401: - header_info.pszStatus = "401 Authorization Required"; - break; - default: { - const char *sline = SG(sapi_headers).http_status_line; - int sline_len; - - /* httpd requires that r->status_line is set to the first digit of - * the status-code: */ - if (sline && ((sline_len = strlen(sline)) > 12) && strncmp(sline, "HTTP/1.", 7) == 0 && sline[8] == ' ') { - if ((sline_len - 9) > MAX_STATUS_LENGTH) { - status_buf = estrndup(sline + 9, MAX_STATUS_LENGTH); - } else { - status_buf = estrndup(sline + 9, sline_len - 9); - } - } else { - status_buf = emalloc(MAX_STATUS_LENGTH + 1); - snprintf(status_buf, MAX_STATUS_LENGTH, "%d Undescribed", SG(sapi_headers).http_response_code); - } - header_info.pszStatus = status_buf; - break; - } - } - header_info.cchStatus = strlen(header_info.pszStatus); - header_info.pszHeader = combined_headers; - header_info.cchHeader = total_length; - header_info.fKeepConn = FALSE; - lpECB->dwHttpStatusCode = SG(sapi_headers).http_response_code; - - lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER_EX, &header_info, NULL, NULL); - - efree(combined_headers); - if (status_buf) { - efree(status_buf); - } - return SAPI_HEADER_SENT_SUCCESSFULLY; -} - - -static int php_isapi_startup(sapi_module_struct *sapi_module) -{ - if (php_module_startup(sapi_module, &php_isapi_module, 1)==FAILURE) { - return FAILURE; - } else { - bTerminateThreadsOnError = (zend_bool) INI_INT("isapi.terminate_threads_on_error"); - return SUCCESS; - } -} - - -static int sapi_isapi_read_post(char *buffer, uint count_bytes TSRMLS_DC) -{ - LPEXTENSION_CONTROL_BLOCK lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context); - DWORD read_from_buf=0; - DWORD read_from_input=0; - DWORD total_read=0; - - if ((DWORD) SG(read_post_bytes) < lpECB->cbAvailable) { - read_from_buf = MIN(lpECB->cbAvailable-SG(read_post_bytes), count_bytes); - memcpy(buffer, lpECB->lpbData+SG(read_post_bytes), read_from_buf); - total_read += read_from_buf; - } - if (read_from_buf<count_bytes - && (SG(read_post_bytes)+read_from_buf) < lpECB->cbTotalBytes) { - DWORD cbRead=0, cbSize; - - read_from_input = MIN(count_bytes-read_from_buf, lpECB->cbTotalBytes-SG(read_post_bytes)-read_from_buf); - while (cbRead < read_from_input) { - cbSize = read_from_input - cbRead; - if (!lpECB->ReadClient(lpECB->ConnID, buffer+read_from_buf+cbRead, &cbSize) || cbSize==0) { - break; - } - cbRead += cbSize; - } - total_read += cbRead; - } - return total_read; -} - - -static char *sapi_isapi_read_cookies(TSRMLS_D) -{ - LPEXTENSION_CONTROL_BLOCK lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context); - char variable_buf[ISAPI_SERVER_VAR_BUF_SIZE]; - DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE; - - if (lpECB->GetServerVariable(lpECB->ConnID, "HTTP_COOKIE", variable_buf, &variable_len)) { - return estrndup(variable_buf, variable_len); - } else if (GetLastError()==ERROR_INSUFFICIENT_BUFFER) { - char *tmp_variable_buf = (char *) emalloc(variable_len+1); - - if (lpECB->GetServerVariable(lpECB->ConnID, "HTTP_COOKIE", tmp_variable_buf, &variable_len)) { - tmp_variable_buf[variable_len] = 0; - return tmp_variable_buf; - } else { - efree(tmp_variable_buf); - } - } - return STR_EMPTY_ALLOC(); -} - - -#ifdef WITH_ZEUS - -static void sapi_isapi_register_zeus_ssl_variables(LPEXTENSION_CONTROL_BLOCK lpECB, zval *track_vars_array TSRMLS_DC) -{ - char static_variable_buf[ISAPI_SERVER_VAR_BUF_SIZE]; - DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE; - char static_cons_buf[ISAPI_SERVER_VAR_BUF_SIZE]; - /* - * We need to construct the /C=.../ST=... - * DN's for SSL_CLIENT_DN and SSL_CLIENT_I_DN - */ - strcpy( static_cons_buf, "/C=" ); - if( lpECB->GetServerVariable( lpECB->ConnID, "SSL_CLIENT_C", static_variable_buf, &variable_len ) && static_variable_buf[0] ) { - strlcat( static_cons_buf, static_variable_buf, ISAPI_SERVER_VAR_BUF_SIZE); - } - strlcat( static_cons_buf, "/ST=", ISAPI_SERVER_VAR_BUF_SIZE); - variable_len = ISAPI_SERVER_VAR_BUF_SIZE; - if( lpECB->GetServerVariable( lpECB->ConnID, "SSL_CLIENT_ST", static_variable_buf, &variable_len ) && static_variable_buf[0] ) { - strlcat( static_cons_buf, static_variable_buf, ISAPI_SERVER_VAR_BUF_SIZE ); - } - php_register_variable( "SSL_CLIENT_DN", static_cons_buf, track_vars_array TSRMLS_CC ); - - strcpy( static_cons_buf, "/C=" ); - variable_len = ISAPI_SERVER_VAR_BUF_SIZE; - if( lpECB->GetServerVariable( lpECB->ConnID, "SSL_CLIENT_I_C", static_variable_buf, &variable_len ) && static_variable_buf[0] ) { - strlcat( static_cons_buf, static_variable_buf, ISAPI_SERVER_VAR_BUF_SIZE ); - } - strlcat( static_cons_buf, "/ST=", ISAPI_SERVER_VAR_BUF_SIZE); - variable_len = ISAPI_SERVER_VAR_BUF_SIZE; - if( lpECB->GetServerVariable( lpECB->ConnID, "SSL_CLIENT_I_ST", static_variable_buf, &variable_len ) && static_variable_buf[0] ) { - strlcat( static_cons_buf, static_variable_buf, ISAPI_SERVER_VAR_BUF_SIZE ); - } - php_register_variable( "SSL_CLIENT_I_DN", static_cons_buf, track_vars_array TSRMLS_CC ); -} - -static void sapi_isapi_register_zeus_variables(LPEXTENSION_CONTROL_BLOCK lpECB, zval *track_vars_array TSRMLS_DC) -{ - char static_variable_buf[ISAPI_SERVER_VAR_BUF_SIZE]; - DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE; - DWORD scriptname_len = ISAPI_SERVER_VAR_BUF_SIZE; - DWORD pathinfo_len = 0; - char *strtok_buf = NULL; - - /* Get SCRIPT_NAME, we use this to work out which bit of the URL - * belongs in PHP's version of PATH_INFO - */ - lpECB->GetServerVariable(lpECB->ConnID, "SCRIPT_NAME", static_variable_buf, &scriptname_len); - - /* Adjust Zeus' version of PATH_INFO, set PHP_SELF, - * and generate REQUEST_URI - */ - if ( lpECB->GetServerVariable(lpECB->ConnID, "PATH_INFO", static_variable_buf, &variable_len) && static_variable_buf[0] ) { - - /* PHP_SELF is just PATH_INFO */ - php_register_variable( "PHP_SELF", static_variable_buf, track_vars_array TSRMLS_CC ); - - /* Chop off filename to get just the 'real' PATH_INFO' */ - pathinfo_len = variable_len - scriptname_len; - php_register_variable( "PATH_INFO", static_variable_buf + scriptname_len - 1, track_vars_array TSRMLS_CC ); - /* append query string to give url... extra byte for '?' */ - if ( strlen(lpECB->lpszQueryString) + variable_len + 1 < ISAPI_SERVER_VAR_BUF_SIZE ) { - /* append query string only if it is present... */ - if ( strlen(lpECB->lpszQueryString) ) { - static_variable_buf[ variable_len - 1 ] = '?'; - strcpy( static_variable_buf + variable_len, lpECB->lpszQueryString ); - } - php_register_variable( "URL", static_variable_buf, track_vars_array TSRMLS_CC ); - php_register_variable( "REQUEST_URI", static_variable_buf, track_vars_array TSRMLS_CC ); - } - } - - /* Get and adjust PATH_TRANSLATED to what PHP wants */ - variable_len = ISAPI_SERVER_VAR_BUF_SIZE; - if ( lpECB->GetServerVariable(lpECB->ConnID, "PATH_TRANSLATED", static_variable_buf, &variable_len) && static_variable_buf[0] ) { - static_variable_buf[ variable_len - pathinfo_len - 1 ] = '\0'; - php_register_variable( "PATH_TRANSLATED", static_variable_buf, track_vars_array TSRMLS_CC ); - } - - /* Bring in the AUTHENTICATION stuff as needed */ - variable_len = ISAPI_SERVER_VAR_BUF_SIZE; - if ( lpECB->GetServerVariable(lpECB->ConnID, "AUTH_USER", static_variable_buf, &variable_len) && static_variable_buf[0] ) { - php_register_variable( "PHP_AUTH_USER", static_variable_buf, track_vars_array TSRMLS_CC ); - } - variable_len = ISAPI_SERVER_VAR_BUF_SIZE; - if ( lpECB->GetServerVariable(lpECB->ConnID, "AUTH_PASSWORD", static_variable_buf, &variable_len) && static_variable_buf[0] ) { - php_register_variable( "PHP_AUTH_PW", static_variable_buf, track_vars_array TSRMLS_CC ); - } - variable_len = ISAPI_SERVER_VAR_BUF_SIZE; - if ( lpECB->GetServerVariable(lpECB->ConnID, "AUTH_TYPE", static_variable_buf, &variable_len) && static_variable_buf[0] ) { - php_register_variable( "AUTH_TYPE", static_variable_buf, track_vars_array TSRMLS_CC ); - } - - /* And now, for the SSL variables (if applicable) */ - variable_len = ISAPI_SERVER_VAR_BUF_SIZE; - if ( lpECB->GetServerVariable(lpECB->ConnID, "CERT_COOKIE", static_variable_buf, &variable_len) && static_variable_buf[0] ) { - sapi_isapi_register_zeus_ssl_variables( lpECB, track_vars_array TSRMLS_CC ); - } - /* Copy some of the variables we need to meet Apache specs */ - variable_len = ISAPI_SERVER_VAR_BUF_SIZE; - if ( lpECB->GetServerVariable(lpECB->ConnID, "SERVER_SOFTWARE", static_variable_buf, &variable_len) && static_variable_buf[0] ) { - php_register_variable( "SERVER_SIGNATURE", static_variable_buf, track_vars_array TSRMLS_CC ); - } -} -#else - -static void sapi_isapi_register_iis_variables(LPEXTENSION_CONTROL_BLOCK lpECB, zval *track_vars_array TSRMLS_DC) -{ - char static_variable_buf[ISAPI_SERVER_VAR_BUF_SIZE]; - char path_info_buf[ISAPI_SERVER_VAR_BUF_SIZE]; - DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE; - DWORD scriptname_len = ISAPI_SERVER_VAR_BUF_SIZE; - DWORD pathinfo_len = 0; - HSE_URL_MAPEX_INFO humi; - - /* Get SCRIPT_NAME, we use this to work out which bit of the URL - * belongs in PHP's version of PATH_INFO. SCRIPT_NAME also becomes PHP_SELF. - */ - lpECB->GetServerVariable(lpECB->ConnID, "SCRIPT_NAME", static_variable_buf, &scriptname_len); - php_register_variable("SCRIPT_FILENAME", SG(request_info).path_translated, track_vars_array TSRMLS_CC); - - /* Adjust IIS' version of PATH_INFO, set PHP_SELF, - * and generate REQUEST_URI - * Get and adjust PATH_TRANSLATED to what PHP wants - */ - if ( lpECB->GetServerVariable(lpECB->ConnID, "PATH_INFO", static_variable_buf, &variable_len) && static_variable_buf[0] ) { - - /* Chop off filename to get just the 'real' PATH_INFO' */ - php_register_variable( "ORIG_PATH_INFO", static_variable_buf, track_vars_array TSRMLS_CC ); - pathinfo_len = variable_len - scriptname_len; - strncpy(path_info_buf, static_variable_buf + scriptname_len - 1, sizeof(path_info_buf)-1); - php_register_variable( "PATH_INFO", path_info_buf, track_vars_array TSRMLS_CC ); - /* append query string to give url... extra byte for '?' */ - if ( strlen(lpECB->lpszQueryString) + variable_len + 1 < ISAPI_SERVER_VAR_BUF_SIZE ) { - /* append query string only if it is present... */ - if ( strlen(lpECB->lpszQueryString) ) { - static_variable_buf[ variable_len - 1 ] = '?'; - strcpy( static_variable_buf + variable_len, lpECB->lpszQueryString ); - } - php_register_variable( "URL", static_variable_buf, track_vars_array TSRMLS_CC ); - php_register_variable( "REQUEST_URI", static_variable_buf, track_vars_array TSRMLS_CC ); - } - variable_len = ISAPI_SERVER_VAR_BUF_SIZE; - if ( lpECB->GetServerVariable(lpECB->ConnID, "PATH_TRANSLATED", static_variable_buf, &variable_len) && static_variable_buf[0] ) { - php_register_variable( "ORIG_PATH_TRANSLATED", static_variable_buf, track_vars_array TSRMLS_CC ); - } - if (lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_MAP_URL_TO_PATH_EX, path_info_buf, &pathinfo_len, (LPDWORD) &humi)) { - /* Remove trailing \ */ - if (humi.lpszPath[variable_len-2] == '\\') { - humi.lpszPath[variable_len-2] = 0; - } - php_register_variable("PATH_TRANSLATED", humi.lpszPath, track_vars_array TSRMLS_CC); - } - } - - static_variable_buf[0] = '/'; - static_variable_buf[1] = 0; - variable_len = 2; - if (lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_MAP_URL_TO_PATH_EX, static_variable_buf, &variable_len, (LPDWORD) &humi)) { - /* Remove trailing \ */ - if (humi.lpszPath[variable_len-2] == '\\') { - humi.lpszPath[variable_len-2] = 0; - } - php_register_variable("DOCUMENT_ROOT", humi.lpszPath, track_vars_array TSRMLS_CC); - } - - if (!SG(request_info).auth_user || !SG(request_info).auth_password || - !SG(request_info).auth_user[0] || !SG(request_info).auth_password[0]) { - variable_len = ISAPI_SERVER_VAR_BUF_SIZE; - if (lpECB->GetServerVariable(lpECB->ConnID, "HTTP_AUTHORIZATION", static_variable_buf, &variable_len) - && static_variable_buf[0]) { - php_handle_auth_data(static_variable_buf TSRMLS_CC); - } - } - - if (SG(request_info).auth_user) { - php_register_variable("PHP_AUTH_USER", SG(request_info).auth_user, track_vars_array TSRMLS_CC ); - } - if (SG(request_info).auth_password) { - php_register_variable("PHP_AUTH_PW", SG(request_info).auth_password, track_vars_array TSRMLS_CC ); - } -} -#endif - -static void sapi_isapi_register_server_variables2(char **server_variables, LPEXTENSION_CONTROL_BLOCK lpECB, zval *track_vars_array, char **recorded_values TSRMLS_DC) -{ - char **p=server_variables; - DWORD variable_len; - char static_variable_buf[ISAPI_SERVER_VAR_BUF_SIZE]; - char *variable_buf; - - while (*p) { - variable_len = ISAPI_SERVER_VAR_BUF_SIZE; - if (lpECB->GetServerVariable(lpECB->ConnID, *p, static_variable_buf, &variable_len) - && static_variable_buf[0]) { - php_register_variable(*p, static_variable_buf, track_vars_array TSRMLS_CC); - if (recorded_values) { - recorded_values[p-server_variables] = estrndup(static_variable_buf, variable_len); - } - } else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - variable_buf = (char *) emalloc(variable_len+1); - if (lpECB->GetServerVariable(lpECB->ConnID, *p, variable_buf, &variable_len) - && variable_buf[0]) { - php_register_variable(*p, variable_buf, track_vars_array TSRMLS_CC); - } - if (recorded_values) { - recorded_values[p-server_variables] = variable_buf; - } else { - efree(variable_buf); - } - } else { /* for compatibility with Apache SAPIs */ - php_register_variable(*p, "", track_vars_array TSRMLS_CC); - } - p++; - } -} - - -static void sapi_isapi_register_server_variables(zval *track_vars_array TSRMLS_DC) -{ - DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE; - char *variable; - char *strtok_buf = NULL; - char *isapi_special_server_variables[NUM_SPECIAL_VARS]; - LPEXTENSION_CONTROL_BLOCK lpECB; - - lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context); - - /* Register the special ISAPI variables */ - memset(isapi_special_server_variables, 0, sizeof(isapi_special_server_variables)); - sapi_isapi_register_server_variables2(isapi_special_server_variable_names, lpECB, track_vars_array, isapi_special_server_variables TSRMLS_CC); - if (SG(request_info).cookie_data) { - php_register_variable("HTTP_COOKIE", SG(request_info).cookie_data, track_vars_array TSRMLS_CC); - } - - /* Register the standard ISAPI variables */ - sapi_isapi_register_server_variables2(isapi_server_variable_names, lpECB, track_vars_array, NULL TSRMLS_CC); - - if (isapi_special_server_variables[SPECIAL_VAR_HTTPS] - && (atoi(isapi_special_server_variables[SPECIAL_VAR_HTTPS]) - || !strcasecmp(isapi_special_server_variables[SPECIAL_VAR_HTTPS], "on")) - ) { - /* Register SSL ISAPI variables */ - sapi_isapi_register_server_variables2(isapi_secure_server_variable_names, lpECB, track_vars_array, NULL TSRMLS_CC); - } - - if (isapi_special_server_variables[SPECIAL_VAR_HTTPS]) { - efree(isapi_special_server_variables[SPECIAL_VAR_HTTPS]); - } - - -#ifdef WITH_ZEUS - sapi_isapi_register_zeus_variables(lpECB, track_vars_array TSRMLS_CC); -#else - sapi_isapi_register_iis_variables(lpECB, track_vars_array TSRMLS_CC); -#endif - - /* PHP_SELF support */ - if (isapi_special_server_variables[SPECIAL_VAR_PHP_SELF]) { - php_register_variable("PHP_SELF", isapi_special_server_variables[SPECIAL_VAR_PHP_SELF], track_vars_array TSRMLS_CC); - efree(isapi_special_server_variables[SPECIAL_VAR_PHP_SELF]); - } - - if (isapi_special_server_variables[SPECIAL_VAR_ALL_HTTP]) { - /* Register the internal bits of ALL_HTTP */ - variable = php_strtok_r(isapi_special_server_variables[SPECIAL_VAR_ALL_HTTP], "\r\n", &strtok_buf); - while (variable) { - char *colon = strchr(variable, ':'); - - if (colon) { - char *value = colon+1; - - while (*value==' ') { - value++; - } - *colon = 0; - php_register_variable(variable, value, track_vars_array TSRMLS_CC); - *colon = ':'; - } - variable = php_strtok_r(NULL, "\r\n", &strtok_buf); - } - efree(isapi_special_server_variables[SPECIAL_VAR_ALL_HTTP]); - } -} - - -static sapi_module_struct isapi_sapi_module = { - "isapi", /* name */ - "ISAPI", /* pretty name */ - - php_isapi_startup, /* startup */ - php_module_shutdown_wrapper, /* shutdown */ - - NULL, /* activate */ - NULL, /* deactivate */ - - sapi_isapi_ub_write, /* unbuffered write */ - NULL, /* flush */ - NULL, /* get uid */ - NULL, /* getenv */ - - php_error, /* error handler */ - - sapi_isapi_header_handler, /* header handler */ - sapi_isapi_send_headers, /* send headers handler */ - NULL, /* send header handler */ - - sapi_isapi_read_post, /* read POST data */ - sapi_isapi_read_cookies, /* read Cookies */ - - sapi_isapi_register_server_variables, /* register server variables */ - NULL, /* Log message */ - NULL, /* Get request time */ - NULL, /* Child terminate */ - - STANDARD_SAPI_MODULE_PROPERTIES -}; - - -BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pFilterVersion) -{ - bFilterLoaded = 1; - pFilterVersion->dwFilterVersion = HTTP_FILTER_REVISION; - strcpy(pFilterVersion->lpszFilterDesc, isapi_sapi_module.pretty_name); - pFilterVersion->dwFlags= (SF_NOTIFY_AUTHENTICATION | SF_NOTIFY_PREPROC_HEADERS); - return TRUE; -} - - -DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificationType, LPVOID pvNotification) -{ - TSRMLS_FETCH(); - - switch (notificationType) { - case SF_NOTIFY_PREPROC_HEADERS: - SG(request_info).auth_user = NULL; - SG(request_info).auth_password = NULL; - SG(request_info).auth_digest = NULL; - break; - case SF_NOTIFY_AUTHENTICATION: { - char *auth_user = ((HTTP_FILTER_AUTHENT *) pvNotification)->pszUser; - char *auth_password = ((HTTP_FILTER_AUTHENT *) pvNotification)->pszPassword; - - if (auth_user && auth_user[0]) { - SG(request_info).auth_user = estrdup(auth_user); - } - if (auth_password && auth_password[0]) { - SG(request_info).auth_password = estrdup(auth_password); - } - return SF_STATUS_REQ_HANDLED_NOTIFICATION; - } - break; - } - return SF_STATUS_REQ_NEXT_NOTIFICATION; -} - - -static void init_request_info(LPEXTENSION_CONTROL_BLOCK lpECB TSRMLS_DC) -{ - DWORD variable_len = ISAPI_SERVER_VAR_BUF_SIZE; - char static_variable_buf[ISAPI_SERVER_VAR_BUF_SIZE]; -#ifndef WITH_ZEUS - HSE_URL_MAPEX_INFO humi; -#endif - - SG(request_info).request_method = lpECB->lpszMethod; - SG(request_info).query_string = lpECB->lpszQueryString; - SG(request_info).request_uri = lpECB->lpszPathInfo; - SG(request_info).content_type = lpECB->lpszContentType; - SG(request_info).content_length = lpECB->cbTotalBytes; - SG(sapi_headers).http_response_code = 200; /* I think dwHttpStatusCode is invalid at this stage -RL */ - if (!bFilterLoaded) { /* we don't have valid ISAPI Filter information */ - SG(request_info).auth_user = SG(request_info).auth_password = SG(request_info).auth_digest = NULL; - } - -#ifdef WITH_ZEUS - /* PATH_TRANSLATED can contain extra PATH_INFO stuff after the - * file being loaded, so we must use SCRIPT_FILENAME instead - */ - if(lpECB->GetServerVariable(lpECB->ConnID, "SCRIPT_FILENAME", static_variable_buf, &variable_len)) { - SG(request_info).path_translated = estrdup(static_variable_buf); - } else -#else - /* happily, IIS gives us SCRIPT_NAME which is correct (without PATH_INFO stuff) - so we can just map that to the physical path and we have our filename */ - - lpECB->GetServerVariable(lpECB->ConnID, "SCRIPT_NAME", static_variable_buf, &variable_len); - if (lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_MAP_URL_TO_PATH_EX, static_variable_buf, &variable_len, (LPDWORD) &humi)) { - SG(request_info).path_translated = estrdup(humi.lpszPath); - } else -#endif - /* if mapping fails, default to what the server tells us */ - SG(request_info).path_translated = estrdup(lpECB->lpszPathTranslated); - - /* some server configurations allow '..' to slip through in the - translated path. We'll just refuse to handle such a path. */ - if (strstr(SG(request_info).path_translated,"..")) { - SG(sapi_headers).http_response_code = 404; - efree(SG(request_info).path_translated); - SG(request_info).path_translated = NULL; - } -} - - -static void php_isapi_report_exception(char *message, int message_len TSRMLS_DC) -{ - if (!SG(headers_sent)) { - HSE_SEND_HEADER_EX_INFO header_info; - LPEXTENSION_CONTROL_BLOCK lpECB = (LPEXTENSION_CONTROL_BLOCK) SG(server_context); - - header_info.pszStatus = "500 Internal Server Error"; - header_info.cchStatus = strlen(header_info.pszStatus); - header_info.pszHeader = "Content-Type: text/html\r\n\r\n"; - header_info.cchHeader = strlen(header_info.pszHeader); - - lpECB->dwHttpStatusCode = 500; - lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER_EX, &header_info, NULL, NULL); - SG(headers_sent)=1; - } - sapi_isapi_ub_write(message, message_len TSRMLS_CC); -} - - -BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer) -{ - pVer->dwExtensionVersion = HSE_VERSION; -#ifdef WITH_ZEUS - strncpy( pVer->lpszExtensionDesc, isapi_sapi_module.name, HSE_MAX_EXT_DLL_NAME_LEN); -#else - lstrcpyn(pVer->lpszExtensionDesc, isapi_sapi_module.name, HSE_MAX_EXT_DLL_NAME_LEN); -#endif - return TRUE; -} - - -static void my_endthread() -{ -#ifdef PHP_WIN32 - if (bTerminateThreadsOnError) { - _endthread(); - } -#endif -} - -#ifdef PHP_WIN32 -/* ep is accessible only in the context of the __except expression, - * so we have to call this function to obtain it. - */ -BOOL exceptionhandler(LPEXCEPTION_POINTERS *e, LPEXCEPTION_POINTERS ep) -{ - *e=ep; - return TRUE; -} -#endif - -DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB) -{ - zend_file_handle file_handle; - zend_bool stack_overflown=0; - int retval = FAILURE; -#ifdef PHP_ENABLE_SEH - LPEXCEPTION_POINTERS e; -#endif - TSRMLS_FETCH(); - - zend_first_try { -#ifdef PHP_ENABLE_SEH - __try { -#endif - init_request_info(lpECB TSRMLS_CC); - SG(server_context) = lpECB; - - php_request_startup(TSRMLS_C); - - file_handle.filename = SG(request_info).path_translated; - file_handle.free_filename = 0; - file_handle.type = ZEND_HANDLE_FILENAME; - file_handle.opened_path = NULL; - - /* open the script here so we can 404 if it fails */ - if (file_handle.filename) - retval = php_fopen_primary_script(&file_handle TSRMLS_CC); - - if (!file_handle.filename || retval == FAILURE) { - SG(sapi_headers).http_response_code = 404; - PUTS("No input file specified.\n"); - } else { - php_execute_script(&file_handle TSRMLS_CC); - } - - if (SG(request_info).cookie_data) { - efree(SG(request_info).cookie_data); - } - if (SG(request_info).path_translated) - efree(SG(request_info).path_translated); -#ifdef PHP_ENABLE_SEH - } __except(exceptionhandler(&e, GetExceptionInformation())) { - char buf[1024]; - if (_exception_code()==EXCEPTION_STACK_OVERFLOW) { - LPBYTE lpPage; - static SYSTEM_INFO si; - static MEMORY_BASIC_INFORMATION mi; - static DWORD dwOldProtect; - - GetSystemInfo(&si); - - /* Get page ESP is pointing to */ - _asm mov lpPage, esp; - - /* Get stack allocation base */ - VirtualQuery(lpPage, &mi, sizeof(mi)); - - /* Go to the page below the current page */ - lpPage = (LPBYTE) (mi.BaseAddress) - si.dwPageSize; - - /* Free pages below current page */ - if (!VirtualFree(mi.AllocationBase, (LPBYTE)lpPage - (LPBYTE) mi.AllocationBase, MEM_DECOMMIT)) { - _endthread(); - } - - /* Restore the guard page */ - if (!VirtualProtect(lpPage, si.dwPageSize, PAGE_GUARD | PAGE_READWRITE, &dwOldProtect)) { - _endthread(); - } - - CG(unclean_shutdown)=1; - _snprintf(buf, sizeof(buf)-1,"PHP has encountered a Stack overflow"); - php_isapi_report_exception(buf, strlen(buf) TSRMLS_CC); - } else if (_exception_code()==EXCEPTION_ACCESS_VIOLATION) { - _snprintf(buf, sizeof(buf)-1,"PHP has encountered an Access Violation at %p", e->ExceptionRecord->ExceptionAddress); - php_isapi_report_exception(buf, strlen(buf) TSRMLS_CC); - my_endthread(); - } else { - _snprintf(buf, sizeof(buf)-1,"PHP has encountered an Unhandled Exception Code %d at %p", e->ExceptionRecord->ExceptionCode , e->ExceptionRecord->ExceptionAddress); - php_isapi_report_exception(buf, strlen(buf) TSRMLS_CC); - my_endthread(); - } - } -#endif -#ifdef PHP_ENABLE_SEH - __try { - php_request_shutdown(NULL); - } __except(EXCEPTION_EXECUTE_HANDLER) { - my_endthread(); - } -#else - php_request_shutdown(NULL); -#endif - } zend_catch { - zend_try { - php_request_shutdown(NULL); - } zend_end_try(); - return HSE_STATUS_ERROR; - } zend_end_try(); - - return HSE_STATUS_SUCCESS; -} - - - -__declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - switch (fdwReason) { - case DLL_PROCESS_ATTACH: -#ifdef WITH_ZEUS - tsrm_startup(128, 1, TSRM_ERROR_LEVEL_CORE, "TSRM.log"); -#else - tsrm_startup(128, 1, TSRM_ERROR_LEVEL_CORE, "C:\\TSRM.log"); -#endif - sapi_startup(&isapi_sapi_module); - if (isapi_sapi_module.startup) { - isapi_sapi_module.startup(&sapi_module); - } - break; - case DLL_THREAD_ATTACH: - break; - case DLL_THREAD_DETACH: - ts_free_thread(); - break; - case DLL_PROCESS_DETACH: - if (isapi_sapi_module.shutdown) { - isapi_sapi_module.shutdown(&sapi_module); - } - sapi_shutdown(); - tsrm_shutdown(); - break; - } - return TRUE; -} - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - */ diff --git a/sapi/isapi/php5isapi.def b/sapi/isapi/php5isapi.def deleted file mode 100644 index 596023ef55..0000000000 --- a/sapi/isapi/php5isapi.def +++ /dev/null @@ -1,5 +0,0 @@ -EXPORTS -HttpFilterProc -GetFilterVersion -HttpExtensionProc -GetExtensionVersion diff --git a/sapi/isapi/php5isapi.dsp b/sapi/isapi/php5isapi.dsp deleted file mode 100644 index 3dbab11eff..0000000000 --- a/sapi/isapi/php5isapi.dsp +++ /dev/null @@ -1,165 +0,0 @@ -# Microsoft Developer Studio Project File - Name="php5isapi" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=php5isapi - 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 "php5isapi.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 "php5isapi.mak" CFG="php5isapi - Win32 Debug_TS"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "php5isapi - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "php5isapi - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "php5isapi - Win32 Release_TS_inline" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "php5isapi - Win32 Release_TSDbg" (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)" == "php5isapi - 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 Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PHP5ISAPI_EXPORTS" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\..\win32" /I "..\..\Zend" /I "..\.." /I "..\..\main" /I "..\..\TSRM" /D "_DEBUG" /D "COMPILE_LIBZEND" /D ZEND_DEBUG=1 /D "_WINDOWS" /D "_USRDLL" /D "PHP5ISAPI_EXPORTS" /D "MSVC5" /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "_MBCS" /FR /YX /FD /GZ /c
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x40d /d "_DEBUG"
-# ADD RSC /l 0x40d /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 wsock32.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 php5ts_debug.lib /nologo /version:4.0 /dll /debug /machine:I386 /nodefaultlib:"libcmt" /pdbtype:sept /libpath:"..\..\Debug_TS"
-
-!ELSEIF "$(CFG)" == "php5isapi - 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 "PHP5ISAPI_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "...\..\include" /I "..\..\win32" /I "..\..\Zend" /I "..\.." /I "..\..\main" /I "..\..\TSRM" /D "NDEBUG" /D ZEND_DEBUG=0 /D "_WINDOWS" /D "_USRDLL" /D "PHP5ISAPI_EXPORTS" /D "MSVC5" /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "_MBCS" /FR /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x40d /d "NDEBUG"
-# ADD RSC /l 0x40d /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 kernel32.lib user32.lib gdi32.lib wsock32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php5ts.lib /nologo /version:4.0 /dll /machine:I386 /libpath:"..\..\Release_TS"
-
-!ELSEIF "$(CFG)" == "php5isapi - Win32 Release_TS_inline"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "php5isapi___Win32_Release_TS_inline"
-# PROP BASE Intermediate_Dir "php5isapi___Win32_Release_TS_inline"
-# PROP BASE Ignore_Export_Lib 0
-# 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 /MD /W3 /GX /O2 /I "...\..\include" /I "..\..\win32" /I "..\..\Zend" /I "..\.." /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "PHP5ISAPI_EXPORTS" /D "MSVC5" /D "ZTS" /D "WIN32" /D "_MBCS" /D ZEND_DEBUG=0 /FR /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "...\..\include" /I "..\..\win32" /I "..\..\Zend" /I "..\.." /I "..\..\main" /I "..\..\TSRM" /D "NDEBUG" /D ZEND_DEBUG=0 /D "ZEND_WIN32_FORCE_INLINE" /D "_WINDOWS" /D "_USRDLL" /D "PHP5ISAPI_EXPORTS" /D "MSVC5" /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "_MBCS" /FR /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x40d /d "NDEBUG"
-# ADD RSC /l 0x40d /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib wsock32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php5ts.lib /nologo /dll /machine:I386 /libpath:"..\..\Release_TS"
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib wsock32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php5ts.lib /nologo /version:4.0 /dll /machine:I386 /libpath:"..\..\Release_TS_inline"
-
-!ELSEIF "$(CFG)" == "php5isapi - Win32 Release_TSDbg"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "php5isapi___Win32_Release_TSDbg"
-# PROP BASE Intermediate_Dir "php5isapi___Win32_Release_TSDbg"
-# PROP BASE Ignore_Export_Lib 0
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "..\..\Release_TSDbg"
-# PROP Intermediate_Dir "Release_TSDbg"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "...\..\include" /I "..\..\win32" /I "..\..\Zend" /I "..\.." /I "..\..\main" /I "..\..\TSRM" /D "NDEBUG" /D ZEND_DEBUG=0 /D "_WINDOWS" /D "_USRDLL" /D "PHP5ISAPI_EXPORTS" /D "MSVC5" /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "_MBCS" /FR /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /Zi /Od /I "...\..\include" /I "..\..\win32" /I "..\..\Zend" /I "..\.." /I "..\..\main" /I "..\..\TSRM" /D "NDEBUG" /D ZEND_DEBUG=0 /D "_WINDOWS" /D "_USRDLL" /D "PHP5ISAPI_EXPORTS" /D "MSVC5" /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "_MBCS" /FR /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x40d /d "NDEBUG"
-# ADD RSC /l 0x40d /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib wsock32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php5ts.lib /nologo /version:4.0 /dll /machine:I386 /libpath:"..\..\Release_TS"
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib wsock32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php5ts.lib /nologo /version:4.0 /dll /debug /machine:I386 /libpath:"..\..\Release_TSDbg"
-
-!ENDIF
-
-# Begin Target
-
-# Name "php5isapi - Win32 Debug_TS"
-# Name "php5isapi - Win32 Release_TS"
-# Name "php5isapi - Win32 Release_TS_inline"
-# Name "php5isapi - Win32 Release_TSDbg"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\php5isapi.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\php5isapi.def
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# End Target
-# End Project
diff --git a/sapi/isapi/stresstest/getopt.c b/sapi/isapi/stresstest/getopt.c deleted file mode 100644 index 57faa0f890..0000000000 --- a/sapi/isapi/stresstest/getopt.c +++ /dev/null @@ -1,175 +0,0 @@ -/* Borrowed from Apache NT Port */ - -#include <stdio.h> -#include <string.h> -#include <assert.h> -#include <stdlib.h> -#include "getopt.h" -#define OPTERRCOLON (1) -#define OPTERRNF (2) -#define OPTERRARG (3) - - -char *ap_optarg; -int ap_optind = 1; -static int ap_opterr = 1; -static int ap_optopt; - -static int -ap_optiserr(int argc, char * const *argv, int oint, const char *optstr, - int optchr, int err) -{ - if (ap_opterr) - { - fprintf(stderr, "Error in argument %d, char %d: ", oint, optchr+1); - switch(err) - { - case OPTERRCOLON: - fprintf(stderr, ": in flags\n"); - break; - case OPTERRNF: - fprintf(stderr, "option not found %c\n", argv[oint][optchr]); - break; - case OPTERRARG: - fprintf(stderr, "no argument for option %c\n", argv[oint][optchr]); - break; - default: - fprintf(stderr, "unknown\n"); - break; - } - } - ap_optopt = argv[oint][optchr]; - return('?'); -} - -int ap_getopt(int argc, char* const *argv, const char *optstr) -{ - static int optchr = 0; - static int dash = 0; /* have already seen the - */ - - char *cp; - - if (ap_optind >= argc) - return(EOF); - if (!dash && (argv[ap_optind][0] != '-')) - return(EOF); - if (!dash && (argv[ap_optind][0] == '-') && !argv[ap_optind][1]) - { - /* - * use to specify stdin. Need to let pgm process this and - * the following args - */ - return(EOF); - } - if ((argv[ap_optind][0] == '-') && (argv[ap_optind][1] == '-')) - { - /* -- indicates end of args */ - ap_optind++; - return(EOF); - } - if (!dash) - { - assert((argv[ap_optind][0] == '-') && argv[ap_optind][1]); - dash = 1; - optchr = 1; - } - - /* Check if the guy tries to do a -: kind of flag */ - assert(dash); - if (argv[ap_optind][optchr] == ':') - { - dash = 0; - ap_optind++; - return(ap_optiserr(argc, argv, ap_optind-1, optstr, optchr, OPTERRCOLON)); - } - if (!(cp = strchr(optstr, argv[ap_optind][optchr]))) - { - int errind = ap_optind; - int errchr = optchr; - - if (!argv[ap_optind][optchr+1]) - { - dash = 0; - ap_optind++; - } - else - optchr++; - return(ap_optiserr(argc, argv, errind, optstr, errchr, OPTERRNF)); - } - if (cp[1] == ':') - { - /* Check for cases where the value of the argument - is in the form -<arg> <val> or in the form -<arg><val> */ - dash = 0; - if(!argv[ap_optind][2]) { - ap_optind++; - if (ap_optind == argc) - return(ap_optiserr(argc, argv, ap_optind-1, optstr, optchr, OPTERRARG)); - ap_optarg = argv[ap_optind++]; - } - else - { - ap_optarg = &argv[ap_optind][2]; - ap_optind++; - } - return(*cp); - } - else - { - if (!argv[ap_optind][optchr+1]) - { - dash = 0; - ap_optind++; - } - else - optchr++; - return(*cp); - } - assert(0); - return(0); -} - -#ifdef TESTGETOPT -int - main (int argc, char **argv) - { - int c; - extern char *ap_optarg; - extern int ap_optind; - int aflg = 0; - int bflg = 0; - int errflg = 0; - char *ofile = NULL; - - while ((c = ap_getopt(argc, argv, "abo:")) != EOF) - switch (c) { - case 'a': - if (bflg) - errflg++; - else - aflg++; - break; - case 'b': - if (aflg) - errflg++; - else - bflg++; - break; - case 'o': - ofile = ap_optarg; - (void)printf("ofile = %s\n", ofile); - break; - case '?': - errflg++; - } - if (errflg) { - (void)fprintf(stderr, - "usage: cmd [-a|-b] [-o <filename>] files...\n"); - exit (2); - } - for ( ; ap_optind < argc; ap_optind++) - (void)printf("%s\n", argv[ap_optind]); - return 0; - } - -#endif /* TESTGETOPT */ diff --git a/sapi/isapi/stresstest/getopt.h b/sapi/isapi/stresstest/getopt.h deleted file mode 100644 index a3e278e3a6..0000000000 --- a/sapi/isapi/stresstest/getopt.h +++ /dev/null @@ -1,12 +0,0 @@ -/* Borrowed from Apache NT Port */ -#ifdef __cplusplus -extern "C" { -#endif -extern char *ap_optarg; -extern int ap_optind; - -int ap_getopt(int argc, char* const *argv, const char *optstr); - -#ifdef __cplusplus -} -#endif
\ No newline at end of file diff --git a/sapi/isapi/stresstest/notes.txt b/sapi/isapi/stresstest/notes.txt deleted file mode 100644 index f58ab3c0e9..0000000000 --- a/sapi/isapi/stresstest/notes.txt +++ /dev/null @@ -1,56 +0,0 @@ -This stress test program is for debugging threading issues with the ISAPI -module. - -2 ways to use it: - -1: test any php script file on multiple threads -2: run the php test scripts bundled with the source code - - - -GLOBAL SETTINGS -=============== - -If you need to set special environement variables, in addition to your -regular environment, create a file that contains them, one setting per line: - -MY_ENV_VAR=XXXXXXXX - -This can be used to simulate ISAPI environment variables if need be. - -By default, stress test uses 10 threads. To change this, change the define -NUM_THREADS in stresstest.cpp. - - - -1: Test any php script file on multiple threads -=============================================== - -Create a file that contains a list of php script files, one per line. If -you need to provide input, place the GET data, or Query String, after the -filename. File contents would look like: - -e:\inetpub\pages\index.php -e:\inetpub\pages\info.php -e:\inetpub\pages\test.php a=1&b=2 - -Run: stresstest L files.txt - - - -2: Run the php test scripts bundled with the source code -======================================================== - -supply the path to the parent of the "tests" directory (expect a couple -long pauses for a couple of the larger tests) - -Run: stresstest T c:\php5-source - - - -TODO: - -* Make more options configurable: number of threads, iterations, etc. -* Improve stdout output to make it more useful -* Implement support for SKIPIF -* Improve speed of CompareFile function (too slow on big files). diff --git a/sapi/isapi/stresstest/stresstest.cpp b/sapi/isapi/stresstest/stresstest.cpp deleted file mode 100644 index 9a5964a6ba..0000000000 --- a/sapi/isapi/stresstest/stresstest.cpp +++ /dev/null @@ -1,936 +0,0 @@ -/* - * ======================================================================= * - * File: stress .c * - * stress tester for isapi dll's * - * based on cgiwrap * - * ======================================================================= * - * -*/ -#define WIN32_LEAN_AND_MEAN -#include <afx.h> -#include <afxtempl.h> -#include <winbase.h> -#include <winerror.h> -#include <httpext.h> -#include <stdio.h> -#include <stdlib.h> -#include "getopt.h" - -// These are things that go out in the Response Header -// -#define HTTP_VER "HTTP/1.0" -#define SERVER_VERSION "Http-Srv-Beta2/1.0" - -// -// Simple wrappers for the heap APIS -// -#define xmalloc(s) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (s)) -#define xfree(s) HeapFree(GetProcessHeap(), 0, (s)) - -// -// The mandatory exports from the ISAPI DLL -// -DWORD numThreads = 1; -DWORD iterations = 1; - -HANDLE StartNow; -// quick and dirty environment -typedef CMapStringToString TEnvironment; -TEnvironment IsapiEnvironment; - -typedef struct _TResults { - LONG ok; - LONG bad; -} TResults; - -CStringArray IsapiFileList; // list of filenames -CStringArray TestNames; // --TEST-- -CStringArray IsapiGetData; // --GET-- -CStringArray IsapiPostData; // --POST-- -CStringArray IsapiMatchData; // --EXPECT-- -CArray<TResults, TResults> Results; - -typedef struct _TIsapiContext { - HANDLE in; - HANDLE out; - DWORD tid; - TEnvironment env; - HANDLE waitEvent; -} TIsapiContext; - -// -// Prototypes of the functions this sample implements -// -extern "C" { -HINSTANCE hDll; -typedef BOOL (WINAPI *VersionProc)(HSE_VERSION_INFO *) ; -typedef DWORD (WINAPI *HttpExtProc)(EXTENSION_CONTROL_BLOCK *); -typedef BOOL (WINAPI *TerminateProc) (DWORD); -BOOL WINAPI FillExtensionControlBlock(EXTENSION_CONTROL_BLOCK *, TIsapiContext *) ; -BOOL WINAPI GetServerVariable(HCONN, LPSTR, LPVOID, LPDWORD ); -BOOL WINAPI ReadClient(HCONN, LPVOID, LPDWORD); -BOOL WINAPI WriteClient(HCONN, LPVOID, LPDWORD, DWORD); -BOOL WINAPI ServerSupportFunction(HCONN, DWORD, LPVOID, LPDWORD, LPDWORD); -VersionProc IsapiGetExtensionVersion; -HttpExtProc IsapiHttpExtensionProc; -TerminateProc TerminateExtensionProc; -HSE_VERSION_INFO version_info; -} - -char * MakeDateStr(VOID); -char * GetEnv(char *); - - - - -DWORD CALLBACK IsapiThread(void *); -int stress_main(const char *filename, - const char *arg, - const char *postfile, - const char *matchdata); - - - -BOOL bUseTestFiles = FALSE; -char temppath[MAX_PATH]; - -void stripcrlf(char *line) -{ - DWORD l = strlen(line)-1; - if (line[l]==10 || line[l]==13) line[l]=0; - l = strlen(line)-1; - if (line[l]==10 || line[l]==13) line[l]=0; -} - -#define COMPARE_BUF_SIZE 1024 - -BOOL CompareFiles(const char*f1, const char*f2) -{ - FILE *fp1, *fp2; - bool retval; - char buf1[COMPARE_BUF_SIZE], buf2[COMPARE_BUF_SIZE]; - int length1, length2; - - if ((fp1=fopen(f1, "r"))==NULL) { - return FALSE; - } - - if ((fp2=fopen(f2, "r"))==NULL) { - fclose(fp1); - return FALSE; - } - - retval = TRUE; // success oriented - while (true) { - length1 = fread(buf1, 1, sizeof(buf1), fp1); - length2 = fread(buf2, 1, sizeof(buf2), fp2); - - // check for end of file - if (feof(fp1)) { - if (!feof(fp2)) { - retval = FALSE; - } - break; - } else if (feof(fp2)) { - if (!feof(fp1)) { - retval = FALSE; - } - break; - } - - // compare data - if (length1!=length2 - || memcmp(buf1, buf2, length1)!=0) { - retval = FALSE; - break; - } - } - fclose(fp1); - fclose(fp2); - - return retval; -} - - -BOOL CompareStringWithFile(const char *filename, const char *str, unsigned int str_length) -{ - FILE *fp; - bool retval; - char buf[COMPARE_BUF_SIZE]; - unsigned int offset=0, readbytes; - fprintf(stderr, "test %s\n",filename); - if ((fp=fopen(filename, "rb"))==NULL) { - fprintf(stderr, "Error opening %s\n",filename); - return FALSE; - } - - retval = TRUE; // success oriented - while (true) { - readbytes = fread(buf, 1, sizeof(buf), fp); - - // check for end of file - - if (offset+readbytes > str_length - || memcmp(buf, str+offset, readbytes)!=NULL) { - fprintf(stderr, "File missmatch %s\n",filename); - retval = FALSE; - break; - } - if (feof(fp)) { - if (!retval) fprintf(stderr, "File zero length %s\n",filename); - break; - } - } - fclose(fp); - - return retval; -} - - -BOOL ReadGlobalEnvironment(const char *environment) -{ - if (environment) { - FILE *fp = fopen(environment, "r"); - DWORD i=0; - if (fp) { - char line[2048]; - while (fgets(line, sizeof(line)-1, fp)) { - // file.php arg1 arg2 etc. - char *p = strchr(line, '='); - if (p) { - *p=0; - IsapiEnvironment[line]=p+1; - } - } - fclose(fp); - return IsapiEnvironment.GetCount() > 0; - } - } - return FALSE; -} - -BOOL ReadFileList(const char *filelist) -{ - FILE *fp = fopen(filelist, "r"); - if (!fp) { - printf("Unable to open %s\r\n", filelist); - } - char line[2048]; - int i=0; - while (fgets(line, sizeof(line)-1, fp)) { - // file.php arg1 arg2 etc. - stripcrlf(line); - if (strlen(line)>3) { - char *p = strchr(line, ' '); - if (p) { - *p = 0; - // get file - - IsapiFileList.Add(line); - IsapiGetData.Add(p+1); - } else { - // just a filename is all - IsapiFileList.Add(line); - IsapiGetData.Add(""); - } - } - - // future use - IsapiPostData.Add(""); - IsapiMatchData.Add(""); - TestNames.Add(""); - - i++; - } - Results.SetSize(TestNames.GetSize()); - - fclose(fp); - return IsapiFileList.GetSize() > 0; -} - -void DoThreads() { - - if (IsapiFileList.GetSize() == 0) { - printf("No Files to test\n"); - return; - } - - printf("Starting Threads...\n"); - // loop creating threads - DWORD tid; - HANDLE *threads = new HANDLE[numThreads]; - DWORD i; - for (i=0; i< numThreads; i++) { - threads[i]=CreateThread(NULL, 0, IsapiThread, NULL, CREATE_SUSPENDED, &tid); - } - for (i=0; i< numThreads; i++) { - if (threads[i]) ResumeThread(threads[i]); - } - // wait for threads to finish - WaitForMultipleObjects(numThreads, threads, TRUE, INFINITE); - for (i=0; i< numThreads; i++) { - CloseHandle(threads[i]); - } - delete [] threads; -} - -void DoFileList(const char *filelist, const char *environment) -{ - // read config files - - if (!ReadFileList(filelist)) { - printf("No Files to test!\r\n"); - return; - } - - ReadGlobalEnvironment(environment); - - DoThreads(); -} - - -/** - * ParseTestFile - * parse a single phpt file and add it to the arrays - */ -BOOL ParseTestFile(const char *path, const char *fn) -{ - // parse the test file - char filename[MAX_PATH]; - _snprintf(filename, sizeof(filename)-1, "%s\\%s", path, fn); - char line[1024]; - memset(line, 0, sizeof(line)); - CString cTest, cSkipIf, cPost, cGet, cFile, cExpect; - printf("Reading %s\r\n", filename); - - enum state {none, test, skipif, post, get, file, expect} parsestate = none; - - FILE *fp = fopen(filename, "rb"); - char *tn = _tempnam(temppath,"pht."); - char *en = _tempnam(temppath,"exp."); - FILE *ft = fopen(tn, "wb+"); - FILE *fe = fopen(en, "wb+"); - if (fp && ft && fe) { - while (fgets(line, sizeof(line)-1, fp)) { - if (line[0]=='-') { - if (_strnicmp(line, "--TEST--", 8)==0) { - parsestate = test; - continue; - } else if (_strnicmp(line, "--SKIPIF--", 10)==0) { - parsestate = skipif; - continue; - } else if (_strnicmp(line, "--POST--", 8)==0) { - parsestate = post; - continue; - } else if (_strnicmp(line, "--GET--", 7)==0) { - parsestate = get; - continue; - } else if (_strnicmp(line, "--FILE--", 8)==0) { - parsestate = file; - continue; - } else if (_strnicmp(line, "--EXPECT--", 10)==0) { - parsestate = expect; - continue; - } - } - switch (parsestate) { - case test: - stripcrlf(line); - cTest = line; - break; - case skipif: - cSkipIf += line; - break; - case post: - cPost += line; - break; - case get: - cGet += line; - break; - case file: - fputs(line, ft); - break; - case expect: - fputs(line, fe); - break; - } - } - - fclose(fp); - fclose(ft); - fclose(fe); - - if (!cTest.IsEmpty()) { - IsapiFileList.Add(tn); - TestNames.Add(cTest); - IsapiGetData.Add(cGet); - IsapiPostData.Add(cPost); - IsapiMatchData.Add(en); - free(tn); - free(en); - return TRUE; - } - } - free(tn); - free(en); - return FALSE; -} - - -/** - * GetTestFiles - * Recurse through the path and subdirectories, parse each phpt file - */ -BOOL GetTestFiles(const char *path) -{ - // find all files .phpt under testpath\tests - char FindPath[MAX_PATH]; - WIN32_FIND_DATA fd; - memset(&fd, 0, sizeof(WIN32_FIND_DATA)); - - _snprintf(FindPath, sizeof(FindPath)-1, "%s\\*.*", path); - HANDLE fh = FindFirstFile(FindPath, &fd); - if (fh != INVALID_HANDLE_VALUE) { - do { - if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && - !strchr(fd.cFileName, '.')) { - // subdirectory, recurse into it - char NewFindPath[MAX_PATH]; - _snprintf(NewFindPath, sizeof(NewFindPath)-1, "%s\\%s", path, fd.cFileName); - GetTestFiles(NewFindPath); - } else if (strstr(fd.cFileName, ".phpt")) { - // got test file, parse it now - if (ParseTestFile(path, fd.cFileName)) { - printf("Test File Added: %s\\%s\r\n", path, fd.cFileName); - } - } - memset(&fd, 0, sizeof(WIN32_FIND_DATA)); - } while (FindNextFile(fh, &fd) != 0); - FindClose(fh); - } - return IsapiFileList.GetSize() > 0; -} - -void DeleteTempFiles(const char *mask) -{ - char FindPath[MAX_PATH]; - WIN32_FIND_DATA fd; - memset(&fd, 0, sizeof(WIN32_FIND_DATA)); - - _snprintf(FindPath, sizeof(FindPath)-1, "%s\\%s", temppath, mask); - HANDLE fh = FindFirstFile(FindPath, &fd); - if (fh != INVALID_HANDLE_VALUE) { - do { - char NewFindPath[MAX_PATH]; - _snprintf(NewFindPath, sizeof(NewFindPath)-1, "%s\\%s", temppath, fd.cFileName); - DeleteFile(NewFindPath); - memset(&fd, 0, sizeof(WIN32_FIND_DATA)); - } while (FindNextFile(fh, &fd) != 0); - FindClose(fh); - } -} - -void DoTestFiles(const char *filelist, const char *environment) -{ - if (!GetTestFiles(filelist)) { - printf("No Files to test!\r\n"); - return; - } - - Results.SetSize(IsapiFileList.GetSize()); - - ReadGlobalEnvironment(environment); - - DoThreads(); - - printf("\r\nRESULTS:\r\n"); - // show results: - DWORD r = Results.GetSize(); - for (DWORD i=0; i< r; i++) { - TResults result = Results.GetAt(i); - printf("%s\r\nOK: %d FAILED: %d\r\n", TestNames.GetAt(i), result.ok, result.bad); - } - - // delete temp files - printf("Deleting Temp Files\r\n"); - DeleteTempFiles("exp.*"); - DeleteTempFiles("pht.*"); - printf("Done\r\n"); -} - -#define OPTSTRING "m:f:d:h:t:i:" -static void _usage(char *argv0) -{ - char *prog; - - prog = strrchr(argv0, '/'); - if (prog) { - prog++; - } else { - prog = "stresstest"; - } - - printf("Usage: %s -m <isapi.dll> -d|-l <file> [-t <numthreads>] [-i <numiterations>]\n" - " -m path to isapi dll\n" - " -d <directory> php directory (to run php test files).\n" - " -f <file> file containing list of files to run\n" - " -t number of threads to use (default=1)\n" - " -i number of iterations per thread (default=1)\n" - " -h This help\n", prog); -} -int main(int argc, char* argv[]) -{ - LPVOID lpMsgBuf; - char *filelist=NULL, *environment=NULL, *module=NULL; - int c = NULL; - while ((c=ap_getopt(argc, argv, OPTSTRING))!=-1) { - switch (c) { - case 'd': - bUseTestFiles = TRUE; - filelist = strdup(ap_optarg); - break; - case 'f': - bUseTestFiles = FALSE; - filelist = strdup(ap_optarg); - break; - case 'e': - environment = strdup(ap_optarg); - break; - case 't': - numThreads = atoi(ap_optarg); - break; - case 'i': - iterations = atoi(ap_optarg); - break; - case 'm': - module = strdup(ap_optarg); - break; - case 'h': - _usage(argv[0]); - exit(0); - break; - } - } - if (!module || !filelist) { - _usage(argv[0]); - exit(0); - } - - GetTempPath(sizeof(temppath), temppath); - hDll = LoadLibrary(module); // Load our DLL - - if (!hDll) { - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR) &lpMsgBuf, - 0, - NULL - ); - fprintf(stderr,"Error: Dll 'php5isapi.dll' not found -%d\n%s\n", GetLastError(), lpMsgBuf); - free (module); - free(filelist); - LocalFree( lpMsgBuf ); - return -1; - } - - // - // Find the exported functions - - IsapiGetExtensionVersion = (VersionProc)GetProcAddress(hDll,"GetExtensionVersion"); - if (!IsapiGetExtensionVersion) { - fprintf(stderr,"Can't Get Extension Version %d\n", GetLastError()); - free (module); - free(filelist); - return -1; - } - IsapiHttpExtensionProc = (HttpExtProc)GetProcAddress(hDll,"HttpExtensionProc"); - if (!IsapiHttpExtensionProc) { - fprintf(stderr,"Can't Get Extension proc %d\n", GetLastError()); - free (module); - free(filelist); - return -1; - } - TerminateExtensionProc = (TerminateProc) GetProcAddress(hDll, - "TerminateExtension"); - - // This should really check if the version information matches what we - // expect. - // - if (!IsapiGetExtensionVersion(&version_info) ) { - fprintf(stderr,"Fatal: GetExtensionVersion failed\n"); - free (module); - free(filelist); - return -1; - } - - if (bUseTestFiles) { - char TestPath[MAX_PATH]; - if (filelist != NULL) - _snprintf(TestPath, sizeof(TestPath)-1, "%s\\tests", filelist); - else strcpy(TestPath, "tests"); - DoTestFiles(TestPath, environment); - } else { - DoFileList(filelist, environment); - } - - // cleanup - if (TerminateExtensionProc) TerminateExtensionProc(0); - - // We should really free memory (e.g., from GetEnv), but we'll be dead - // soon enough - - FreeLibrary(hDll); - free (module); - free(filelist); - return 0; -} - - -DWORD CALLBACK IsapiThread(void *p) -{ - DWORD filecount = IsapiFileList.GetSize(); - - for (DWORD j=0; j<iterations; j++) { - for (DWORD i=0; i<filecount; i++) { - // execute each file - CString testname = TestNames.GetAt(i); - BOOL ok = FALSE; - if (stress_main(IsapiFileList.GetAt(i), - IsapiGetData.GetAt(i), - IsapiPostData.GetAt(i), - IsapiMatchData.GetAt(i))) { - InterlockedIncrement(&Results[i].ok); - ok = TRUE; - } else { - InterlockedIncrement(&Results[i].bad); - ok = FALSE; - } - - if (testname.IsEmpty()) { - printf("Thread %d File %s\n", GetCurrentThreadId(), IsapiFileList.GetAt(i)); - } else { - printf("tid %d: %s %s\n", GetCurrentThreadId(), testname, ok?"OK":"FAIL"); - } - Sleep(10); - } - } - printf("Thread ending...\n"); - return 0; -} - -/* - * ======================================================================= * - * In the startup of this program, we look at our executable name and * - * replace the ".EXE" with ".DLL" to find the ISAPI DLL we need to load. * - * This means that the executable need only be given the same "name" as * - * the DLL to load. There is no recompilation required. * - * ======================================================================= * -*/ -BOOL stress_main(const char *filename, - const char *arg, - const char *postdata, - const char *matchdata) -{ - - EXTENSION_CONTROL_BLOCK ECB; - DWORD rc; - TIsapiContext context; - - // open output and input files - context.tid = GetCurrentThreadId(); - CString fname; - fname.Format("%08X.out", context.tid); - - context.out = CreateFile(fname, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL); - if (context.out==INVALID_HANDLE_VALUE) { - printf("failed to open output file %s\n", fname); - return 0; - } - - // not using post files - context.in = INVALID_HANDLE_VALUE; - - // - // Fill the ECB with the necessary information - // - if (!FillExtensionControlBlock(&ECB, &context) ) { - fprintf(stderr,"Fill Ext Block Failed\n"); - return -1; - } - - // check for command line argument, - // first arg = filename - // this is added for testing php from command line - - context.env.RemoveAll(); - context.env["PATH_TRANSLATED"]= filename; - context.env["SCRIPT_MAP"]= filename; - context.env["CONTENT_TYPE"]= ""; - context.env["CONTENT_LENGTH"]= ""; - context.env["QUERY_STRING"]= arg; - context.env["METHOD"]="GET"; - context.env["PATH_INFO"] = ""; - context.waitEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - char buf[MAX_PATH]; - if (postdata && *postdata !=0) { - ECB.cbAvailable = strlen(postdata); - ECB.cbTotalBytes = ECB.cbAvailable; - ECB.lpbData = (unsigned char *)postdata; - context.env["METHOD"]="POST"; - - _snprintf(buf, sizeof(buf)-1, "%d", ECB.cbTotalBytes); - context.env["CONTENT_LENGTH"]=buf; - - context.env["CONTENT_TYPE"]="application/x-www-form-urlencoded"; - } - ECB.lpszMethod = strdup(context.env["METHOD"]); - ECB.lpszPathTranslated = strdup(filename); - ECB.lpszQueryString = strdup(arg); - ECB.lpszPathInfo = strdup(context.env["PATH_INFO"]); - - - // Call the DLL - // - rc = IsapiHttpExtensionProc(&ECB); - if (rc == HSE_STATUS_PENDING) { - // We will exit in ServerSupportFunction - WaitForSingleObject(context.waitEvent, INFINITE); - } - CloseHandle(context.waitEvent); - //Sleep(75); - free(ECB.lpszPathTranslated); - free(ECB.lpszQueryString); - free(ECB.lpszMethod); - free(ECB.lpszPathInfo); - - BOOL ok = TRUE; - - if (context.out != INVALID_HANDLE_VALUE) CloseHandle(context.out); - - // compare the output with the EXPECT section - if (matchdata && *matchdata != 0) { - ok = CompareFiles(fname, matchdata); - } - - DeleteFile(fname); - - return ok; - -} -// -// GetServerVariable() is how the DLL calls the main program to figure out -// the environment variables it needs. This is a required function. -// -BOOL WINAPI GetServerVariable(HCONN hConn, LPSTR lpszVariableName, - LPVOID lpBuffer, LPDWORD lpdwSize){ - - DWORD rc; - CString value; - TIsapiContext *c = (TIsapiContext *)hConn; - if (!c) return FALSE; - - if (IsapiEnvironment.Lookup(lpszVariableName, value)) { - rc = value.GetLength(); - strncpy((char *)lpBuffer, value, *lpdwSize-1); - } else if (c->env.Lookup(lpszVariableName, value)) { - rc = value.GetLength(); - strncpy((char *)lpBuffer, value, *lpdwSize-1); - } else - rc = GetEnvironmentVariable(lpszVariableName, (char *)lpBuffer, *lpdwSize) ; - - if (!rc) { // return of 0 indicates the variable was not found - SetLastError(ERROR_NO_DATA); - return FALSE; - } - - if (rc > *lpdwSize) { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return FALSE; - } - - *lpdwSize =rc + 1 ; // GetEnvironmentVariable does not count the NULL - - return TRUE; - -} -// -// Again, we don't have an HCONN, so we simply wrap ReadClient() to -// ReadFile on stdin. The semantics of the two functions are the same -// -BOOL WINAPI ReadClient(HCONN hConn, LPVOID lpBuffer, LPDWORD lpdwSize) { - TIsapiContext *c = (TIsapiContext *)hConn; - if (!c) return FALSE; - - if (c->in != INVALID_HANDLE_VALUE) - return ReadFile(c->in, lpBuffer, (*lpdwSize), lpdwSize, NULL); - - return FALSE; -} -// -// ditto for WriteClient() -// -BOOL WINAPI WriteClient(HCONN hConn, LPVOID lpBuffer, LPDWORD lpdwSize, - DWORD dwReserved) { - TIsapiContext *c = (TIsapiContext *)hConn; - if (!c) return FALSE; - - if (c->out != INVALID_HANDLE_VALUE) - return WriteFile(c->out, lpBuffer, *lpdwSize, lpdwSize, NULL); - return FALSE; -} -// -// This is a special callback function used by the DLL for certain extra -// functionality. Look at the API help for details. -// -BOOL WINAPI ServerSupportFunction(HCONN hConn, DWORD dwHSERequest, - LPVOID lpvBuffer, LPDWORD lpdwSize, LPDWORD lpdwDataType){ - - TIsapiContext *c = (TIsapiContext *)hConn; - char *lpszRespBuf; - char * temp = NULL; - DWORD dwBytes; - BOOL bRet = TRUE; - - switch(dwHSERequest) { - case (HSE_REQ_SEND_RESPONSE_HEADER) : - lpszRespBuf = (char *)xmalloc(*lpdwSize);//+ 80);//accommodate our header - if (!lpszRespBuf) - return FALSE; - wsprintf(lpszRespBuf,"%s", - //HTTP_VER, - - /* Default response is 200 Ok */ - - //lpvBuffer?lpvBuffer:"200 Ok", - - /* Create a string for the time. */ - //temp=MakeDateStr(), - - //SERVER_VERSION, - - /* If this exists, it is a pointer to a data buffer to - be sent. */ - lpdwDataType?(char *)lpdwDataType:NULL); - - if (temp) xfree(temp); - - dwBytes = strlen(lpszRespBuf); - bRet = WriteClient(0, lpszRespBuf, &dwBytes, 0); - xfree(lpszRespBuf); - - break; - // - // A real server would do cleanup here - case (HSE_REQ_DONE_WITH_SESSION): - SetEvent(c->waitEvent); - //ExitThread(0); - break; - - // - // This sends a redirect (temporary) to the client. - // The header construction is similar to RESPONSE_HEADER above. - // - case (HSE_REQ_SEND_URL_REDIRECT_RESP): - lpszRespBuf = (char *)xmalloc(*lpdwSize +80) ; - if (!lpszRespBuf) - return FALSE; - wsprintf(lpszRespBuf,"%s %s %s\r\n", - HTTP_VER, - "302 Moved Temporarily", - (lpdwSize > 0)?lpvBuffer:0); - xfree(temp); - dwBytes = strlen(lpszRespBuf); - bRet = WriteClient(0, lpszRespBuf, &dwBytes, 0); - xfree(lpszRespBuf); - break; - default: - return FALSE; - break; - } - return bRet; - -} -// -// Makes a string of the date and time from GetSystemTime(). -// This is in UTC, as required by the HTTP spec.` -// -char * MakeDateStr(void){ - SYSTEMTIME systime; - char *szDate= (char *)xmalloc(64); - - char * DaysofWeek[] = {"Sun","Mon","Tue","Wed","Thurs","Fri","Sat"}; - char * Months[] = {"NULL","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug", - "Sep","Oct","Nov","Dec"}; - - GetSystemTime(&systime); - - wsprintf(szDate,"%s, %d %s %d %d:%d.%d", DaysofWeek[systime.wDayOfWeek], - systime.wDay, - Months[systime.wMonth], - systime.wYear, - systime.wHour, systime.wMinute, - systime.wSecond ); - - return szDate; -} -// -// Fill the ECB up -// -BOOL WINAPI FillExtensionControlBlock(EXTENSION_CONTROL_BLOCK *ECB, TIsapiContext *context) { - - char * temp; - ECB->cbSize = sizeof(EXTENSION_CONTROL_BLOCK); - ECB->dwVersion = MAKELONG(HSE_VERSION_MINOR, HSE_VERSION_MAJOR); - ECB->ConnID = (void *)context; - // - // Pointers to the functions the DLL will call. - // - ECB->GetServerVariable = GetServerVariable; - ECB->ReadClient = ReadClient; - ECB->WriteClient = WriteClient; - ECB->ServerSupportFunction = ServerSupportFunction; - - // - // Fill in the standard CGI environment variables - // - ECB->lpszMethod = GetEnv("REQUEST_METHOD"); - if (!ECB->lpszMethod) ECB->lpszMethod = "GET"; - - ECB->lpszQueryString = GetEnv("QUERY_STRING"); - ECB->lpszPathInfo = GetEnv("PATH_INFO"); - ECB->lpszPathTranslated = GetEnv("PATH_TRANSLATED"); - ECB->cbTotalBytes=( (temp=GetEnv("CONTENT_LENGTH")) ? (atoi(temp)): 0); - ECB->cbAvailable = 0; - ECB->lpbData = (unsigned char *)""; - ECB->lpszContentType = GetEnv("CONTENT_TYPE"); - return TRUE; - -} - -// -// Works like _getenv(), but uses win32 functions instead. -// -char *GetEnv(LPSTR lpszEnvVar) -{ - - char *var, dummy; - DWORD dwLen; - - if (!lpszEnvVar) - return ""; - - dwLen =GetEnvironmentVariable(lpszEnvVar, &dummy, 1); - - if (dwLen == 0) - return ""; - - var = (char *)xmalloc(dwLen); - if (!var) - return ""; - (void)GetEnvironmentVariable(lpszEnvVar, var, dwLen); - - return var; -} diff --git a/sapi/isapi/stresstest/stresstest.dsp b/sapi/isapi/stresstest/stresstest.dsp deleted file mode 100644 index fb82303e3d..0000000000 --- a/sapi/isapi/stresstest/stresstest.dsp +++ /dev/null @@ -1,108 +0,0 @@ -# Microsoft Developer Studio Project File - Name="stresstest" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=stresstest - Win32 Debug
-!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 "stresstest.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 "stresstest.mak" CFG="stresstest - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "stresstest - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE "stresstest - Win32 Debug" (based on "Win32 (x86) Console Application")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "stresstest - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 2
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "_AFXDLL" /FD /c
-# SUBTRACT CPP /YX /Yc /Yu
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
-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 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 /subsystem:console /machine:I386
-# ADD LINK32 /nologo /subsystem:console /machine:I386
-
-!ELSEIF "$(CFG)" == "stresstest - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 2
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "c:\php-fcgi"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "_AFXDLL" /FD /GZ /c
-# SUBTRACT CPP /YX /Yc /Yu
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
-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 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 /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-
-!ENDIF
-
-# Begin Target
-
-# Name "stresstest - Win32 Release"
-# Name "stresstest - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\getopt.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\getopt.h
-# End Source File
-# Begin Source File
-
-SOURCE=.\stresstest.cpp
-# End Source File
-# End Group
-# Begin Source File
-
-SOURCE=.\notes.txt
-# End Source File
-# End Target
-# End Project
diff --git a/sapi/litespeed/lsapi_main.c b/sapi/litespeed/lsapi_main.c index f08a2c268f..b0ea105a88 100644 --- a/sapi/litespeed/lsapi_main.c +++ b/sapi/litespeed/lsapi_main.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -126,7 +126,7 @@ static void sapi_lsapi_ini_defaults(HashTable *configuration_hash) /* {{{ sapi_lsapi_ub_write */ -static int sapi_lsapi_ub_write(const char *str, uint str_length TSRMLS_DC) +static size_t sapi_lsapi_ub_write(const char *str, size_t str_length) { int ret; int remain; @@ -155,7 +155,7 @@ static int sapi_lsapi_ub_write(const char *str, uint str_length TSRMLS_DC) /* {{{ sapi_lsapi_flush */ -static void sapi_lsapi_flush( void * server_context TSRMLS_DC ) +static void sapi_lsapi_flush( void * server_context ) { if ( lsapi_mode ) { if ( LSAPI_Flush() == -1) { @@ -168,11 +168,12 @@ static void sapi_lsapi_flush( void * server_context TSRMLS_DC ) /* {{{ sapi_lsapi_deactivate */ -static int sapi_lsapi_deactivate(TSRMLS_D) +static int sapi_lsapi_deactivate(void) { if ( SG(request_info).path_translated ) { efree( SG(request_info).path_translated ); + SG(request_info).path_translated = NULL; } return SUCCESS; @@ -184,7 +185,7 @@ static int sapi_lsapi_deactivate(TSRMLS_D) /* {{{ sapi_lsapi_getenv */ -static char *sapi_lsapi_getenv( char * name, size_t name_len TSRMLS_DC ) +static char *sapi_lsapi_getenv( char * name, size_t name_len ) { if ( lsapi_mode ) { return LSAPI_GetEnv( name ); @@ -206,10 +207,10 @@ static int add_variable( const char * pKey, int keyLen, const char * pValue, int #else int filter_arg = (arg == PG(http_globals)[TRACK_VARS_ENV])?PARSE_ENV:PARSE_SERVER; #endif - char * new_val = (char *) pValue; - unsigned int new_val_len; + char * new_val = (char *) pValue; + size_t new_val_len; - if (sapi_module.input_filter(filter_arg, (char *)pKey, &new_val, valLen, &new_val_len TSRMLS_CC)) { + if (sapi_module.input_filter(filter_arg, (char *)pKey, &new_val, valLen, &new_val_len)) { php_register_variable_safe((char *)pKey, new_val, new_val_len, (zval *)arg ); } return 1; @@ -236,7 +237,7 @@ static int add_variable( const char * pKey, int keyLen, const char * pValue, int } */ -static void litespeed_php_import_environment_variables(zval *array_ptr TSRMLS_DC) +static void litespeed_php_import_environment_variables(zval *array_ptr) { char buf[128]; char **env, *p, *t = buf; @@ -295,68 +296,35 @@ static void litespeed_php_import_environment_variables(zval *array_ptr TSRMLS_DC } memcpy(t, *env, nlen); t[nlen] = '\0'; - add_variable(t, nlen, p + 1, strlen( p + 1 ), array_ptr TSRMLS_CC); + add_variable(t, nlen, p + 1, strlen( p + 1 ), array_ptr); } if (t != buf && t != NULL) { efree(t); } } - -#if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || PHP_MAJOR_VERSION < 5) -static int add_variable_magic_quote( const char * pKey, int keyLen, const char * pValue, int valLen, - void * arg ) -{ - zval * gpc_element, **gpc_element_p; - HashTable * symtable1 = Z_ARRVAL_P((zval * )arg); - register char * pKey1 = (char *)pKey; - - MAKE_STD_ZVAL(gpc_element); - Z_STRLEN_P( gpc_element ) = valLen; - Z_STRVAL_P( gpc_element ) = php_addslashes((char *)pValue, valLen, &Z_STRLEN_P( gpc_element ), 0 ); - Z_TYPE_P( gpc_element ) = IS_STRING; -#if PHP_MAJOR_VERSION > 4 - zend_symtable_update( symtable1, pKey1, keyLen + 1, &gpc_element, sizeof( zval *), (void **) &gpc_element_p ); -#else - zend_hash_update( symtable1, pKey1, keyLen + 1, &gpc_element, sizeof( zval *), (void **) &gpc_element_p ); -#endif - return 1; -} - -#endif - /* {{{ sapi_lsapi_register_variables */ -static void sapi_lsapi_register_variables(zval *track_vars_array TSRMLS_DC) +static void sapi_lsapi_register_variables(zval *track_vars_array) { char * php_self = ""; if ( lsapi_mode ) { if ( (SG(request_info).request_uri ) ) php_self = (SG(request_info).request_uri ); - litespeed_php_import_environment_variables(track_vars_array TSRMLS_CC); + litespeed_php_import_environment_variables(track_vars_array); -#if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || PHP_MAJOR_VERSION < 5) - if (!PG(magic_quotes_gpc)) { -#endif - LSAPI_ForeachHeader( add_variable, track_vars_array ); - LSAPI_ForeachEnv( add_variable, track_vars_array ); - add_variable("PHP_SELF", 8, php_self, strlen( php_self ), track_vars_array ); -#if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || PHP_MAJOR_VERSION < 5) - } else { - LSAPI_ForeachHeader( add_variable_magic_quote, track_vars_array ); - LSAPI_ForeachEnv( add_variable_magic_quote, track_vars_array ); - add_variable_magic_quote("PHP_SELF", 8, php_self, strlen( php_self ), track_vars_array ); - } -#endif + LSAPI_ForeachHeader( add_variable, track_vars_array ); + LSAPI_ForeachEnv( add_variable, track_vars_array ); + add_variable("PHP_SELF", 8, php_self, strlen( php_self ), track_vars_array ); } else { - php_import_environment_variables(track_vars_array TSRMLS_CC); + php_import_environment_variables(track_vars_array); - php_register_variable("PHP_SELF", php_self, track_vars_array TSRMLS_CC); - php_register_variable("SCRIPT_NAME", php_self, track_vars_array TSRMLS_CC); - php_register_variable("SCRIPT_FILENAME", script_filename, track_vars_array TSRMLS_CC); - php_register_variable("PATH_TRANSLATED", script_filename, track_vars_array TSRMLS_CC); - php_register_variable("DOCUMENT_ROOT", "", track_vars_array TSRMLS_CC); + php_register_variable("PHP_SELF", php_self, track_vars_array); + php_register_variable("SCRIPT_NAME", php_self, track_vars_array); + php_register_variable("SCRIPT_FILENAME", script_filename, track_vars_array); + php_register_variable("PATH_TRANSLATED", script_filename, track_vars_array); + php_register_variable("DOCUMENT_ROOT", "", track_vars_array); } } @@ -365,7 +333,7 @@ static void sapi_lsapi_register_variables(zval *track_vars_array TSRMLS_DC) /* {{{ sapi_lsapi_read_post */ -static int sapi_lsapi_read_post(char *buffer, uint count_bytes TSRMLS_DC) +static size_t sapi_lsapi_read_post(char *buffer, size_t count_bytes) { if ( lsapi_mode ) { return LSAPI_ReadReqBody( buffer, (unsigned long long)count_bytes ); @@ -380,7 +348,7 @@ static int sapi_lsapi_read_post(char *buffer, uint count_bytes TSRMLS_DC) /* {{{ sapi_lsapi_read_cookies */ -static char *sapi_lsapi_read_cookies(TSRMLS_D) +static char *sapi_lsapi_read_cookies(void) { if ( lsapi_mode ) { return LSAPI_GetHeader( H_COOKIE ); @@ -393,7 +361,7 @@ static char *sapi_lsapi_read_cookies(TSRMLS_D) /* {{{ sapi_lsapi_send_headers */ -static int sapi_lsapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) +static int sapi_lsapi_send_headers(sapi_headers_struct *sapi_headers) { sapi_header_struct *h; zend_llist_position pos; @@ -412,7 +380,7 @@ static int sapi_lsapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) int len; char headerBuf[SAPI_LSAPI_MAX_HEADER_LENGTH]; - hd = sapi_get_default_content_type(TSRMLS_C); + hd = sapi_get_default_content_type(); len = snprintf( headerBuf, SAPI_LSAPI_MAX_HEADER_LENGTH - 1, "Content-type: %s", hd ); efree(hd); @@ -430,7 +398,7 @@ static int sapi_lsapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) /* {{{ sapi_lsapi_send_headers */ -static void sapi_lsapi_log_message(char *message TSRMLS_DC) +static void sapi_lsapi_log_message(char *message) { char buf[8192]; int len = strlen( message ); @@ -489,11 +457,11 @@ static sapi_module_struct lsapi_sapi_module = }; /* }}} */ -static void init_request_info( TSRMLS_D ) +static void init_request_info( void ) { char * pContentType = LSAPI_GetHeader( H_CONTENT_TYPE ); char * pAuth; - + SG(request_info).content_type = pContentType ? pContentType : ""; SG(request_info).request_method = LSAPI_GetRequestMethod(); SG(request_info).query_string = LSAPI_GetQueryString(); @@ -503,9 +471,9 @@ static void init_request_info( TSRMLS_D ) /* It is not reset by zend engine, set it to 200. */ SG(sapi_headers).http_response_code = 200; - + pAuth = LSAPI_GetHeader( H_AUTHORIZATION ); - php_handle_auth_data(pAuth TSRMLS_CC); + php_handle_auth_data(pAuth); } static char s_cur_chdir[4096] = ""; @@ -532,7 +500,7 @@ static int lsapi_chdir_primary_script( zend_file_handle * file_handle ) if ( !CWDG(cwd).cwd || ( strcmp( file_handle->filename, CWDG(cwd).cwd ) != 0 ) ) { CWDG(cwd).cwd_length = p - file_handle->filename; - CWDG(cwd).cwd = (char *) realloc(CWDG(cwd).cwd, CWDG(cwd).cwd_length+1); + CWDG(cwd).cwd = (char *) realloc(CWDG(cwd).cwd, CWDG(cwd).cwd_length+1); memmove( CWDG(cwd).cwd, file_handle->filename, CWDG(cwd).cwd_length+1 ); } *p = ch; @@ -564,7 +532,7 @@ static int lsapi_fopen_primary_script( zend_file_handle * file_handle ) return 0; } -static int lsapi_execute_script( zend_file_handle * file_handle TSRMLS_DC) +static int lsapi_execute_script( zend_file_handle * file_handle) { char *p; int len; @@ -583,26 +551,26 @@ static int lsapi_execute_script( zend_file_handle * file_handle TSRMLS_DC) len = 0; memccpy( p, SG(request_info).path_translated + len, 0, 46 ); - php_execute_script(file_handle TSRMLS_CC); + php_execute_script(file_handle); return 0; } -static int lsapi_module_main(int show_source TSRMLS_DC) +static int lsapi_module_main(int show_source) { zend_file_handle file_handle = {0}; - if (php_request_startup(TSRMLS_C) == FAILURE ) { + if (php_request_startup() == FAILURE ) { return -1; } if (show_source) { zend_syntax_highlighter_ini syntax_highlighter_ini; php_get_highlight_struct(&syntax_highlighter_ini); - highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini TSRMLS_CC); + highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini); } else { - lsapi_execute_script( &file_handle TSRMLS_CC); + lsapi_execute_script( &file_handle); } zend_try { php_request_shutdown(NULL); @@ -616,7 +584,7 @@ static int alter_ini( const char * pKey, int keyLen, const char * pValue, int va void * arg ) { #if PHP_MAJOR_VERSION >= 7 - zend_string * psKey; + zend_string * psKey; #endif int type = ZEND_INI_PERDIR; if ( '\001' == *pKey ) { @@ -634,15 +602,16 @@ static int alter_ini( const char * pKey, int keyLen, const char * pValue, int va else { #if PHP_MAJOR_VERSION >= 7 - psKey = STR_INIT( pKey, keyLen, 1 ); - zend_alter_ini_entry(psKey, + --keyLen; + psKey = zend_string_init(pKey, keyLen, 1); + zend_alter_ini_entry_chars(psKey, (char *)pValue, valLen, type, PHP_INI_STAGE_ACTIVATE); - STR_RELEASE( psKey ); + zend_string_release(psKey); #else zend_alter_ini_entry((char *)pKey, keyLen, (char *)pValue, valLen, - type, PHP_INI_STAGE_ACTIVATE); + type, PHP_INI_STAGE_ACTIVATE); #endif } } @@ -658,7 +627,7 @@ static void override_ini() } -static int processReq( TSRMLS_D ) +static int processReq( void ) { int ret = 0; zend_first_try { @@ -670,9 +639,9 @@ static int processReq( TSRMLS_D ) override_ini(); if ( engine ) { - init_request_info( TSRMLS_C ); + init_request_info( ); - if ( lsapi_module_main( source_highlight TSRMLS_CC ) == -1 ) { + if ( lsapi_module_main( source_highlight ) == -1 ) { ret = -1; } } else { @@ -684,7 +653,7 @@ static int processReq( TSRMLS_D ) return ret; } -static void cli_usage( TSRMLS_D ) +static void cli_usage( void ) { static const char * usage = "Usage: php\n" @@ -705,12 +674,12 @@ static void cli_usage( TSRMLS_D ) "\n" " args... Arguments passed to script.\n"; php_output_startup(); - php_output_activate(TSRMLS_C); + php_output_activate(); php_printf( "%s", usage ); #ifdef PHP_OUTPUT_NEWAPI - php_output_end_all(TSRMLS_C); + php_output_end_all(); #else - php_end_ob_buffers(1 TSRMLS_CC); + php_end_ob_buffers(1); #endif } @@ -731,7 +700,7 @@ static int parse_opt( int argc, char * argv[], int *climode, } *php_bind = strdup(*p++); break; - + case 'c': if ( p >= argend ) { fprintf( stderr, "<path> or <file> must be specified following '-c' option.\n"); @@ -786,7 +755,7 @@ static int cli_main( int argc, char * argv[] ) int ret = -1; int c; #if PHP_MAJOR_VERSION >= 7 - zend_string * psKey; + zend_string * psKey; #endif lsapi_mode = 0; /* enter CLI mode */ @@ -809,11 +778,11 @@ static int cli_main( int argc, char * argv[] ) #endif for( ini = ini_defaults; *ini; ini+=2 ) { #if PHP_MAJOR_VERSION >= 7 - psKey = STR_INIT( *ini, strlen( *ini ), 1 ); - zend_alter_ini_entry( psKey, + psKey = zend_string_init(*ini, strlen( *ini ), 1); + zend_alter_ini_entry_chars(psKey, (char *)*(ini+1), strlen( *(ini+1) ), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); - STR_RELEASE( psKey ); + zend_string_release(psKey); #else zend_alter_ini_entry( (char *)*ini, strlen( *ini )+1, (char *)*(ini+1), strlen( *(ini+1) ), @@ -828,28 +797,28 @@ static int cli_main( int argc, char * argv[] ) case 'q': break; case 'i': - if (php_request_startup(TSRMLS_C) != FAILURE) { - php_print_info(0xFFFFFFFF TSRMLS_CC); + if (php_request_startup() != FAILURE) { + php_print_info(0xFFFFFFFF); #ifdef PHP_OUTPUT_NEWAPI - php_output_end_all(TSRMLS_C); + php_output_end_all(); #else - php_end_ob_buffers(1 TSRMLS_CC); + php_end_ob_buffers(1); #endif php_request_shutdown( NULL ); ret = 0; } break; case 'v': - if (php_request_startup(TSRMLS_C) != FAILURE) { + if (php_request_startup() != FAILURE) { #if ZEND_DEBUG php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2016 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); #else php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2016 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); #endif #ifdef PHP_OUTPUT_NEWAPI - php_output_end_all(TSRMLS_C); + php_output_end_all(); #else - php_end_ob_buffers(1 TSRMLS_CC); + php_end_ob_buffers(1); #endif php_request_shutdown( NULL ); ret = 0; @@ -866,7 +835,7 @@ static int cli_main( int argc, char * argv[] ) case 'h': case '?': default: - cli_usage(TSRMLS_C); + cli_usage(); ret = 0; break; @@ -887,32 +856,32 @@ static int cli_main( int argc, char * argv[] ) SG(request_info).argc = argc - (p - argv); SG(request_info).argv = p; - if (php_request_startup(TSRMLS_C) == FAILURE ) { + if (php_request_startup() == FAILURE ) { fclose( file_handle.handle.fp ); ret = 2; } else { if (source_highlight == 1) { zend_syntax_highlighter_ini syntax_highlighter_ini; - + php_get_highlight_struct(&syntax_highlighter_ini); - highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini TSRMLS_CC); + highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini); } else if (source_highlight == 2) { file_handle.filename = *p; file_handle.free_filename = 0; file_handle.opened_path = NULL; - ret = php_lint_script(&file_handle TSRMLS_CC); + ret = php_lint_script(&file_handle); if (ret==SUCCESS) { zend_printf("No syntax errors detected in %s\n", file_handle.filename); } else { zend_printf("Errors parsing %s\n", file_handle.filename); } - + } else { file_handle.filename = *p; file_handle.free_filename = 0; file_handle.opened_path = NULL; - php_execute_script(&file_handle TSRMLS_CC); + php_execute_script(&file_handle); ret = EG(exit_status); } @@ -922,13 +891,13 @@ static int cli_main( int argc, char * argv[] ) php_printf("Could not open input file: %s.\n", *p); } } else { - cli_usage(TSRMLS_C); + cli_usage(); } } }zend_end_try(); - php_module_shutdown(TSRMLS_C); + php_module_shutdown(); #ifdef ZTS tsrm_shutdown(); @@ -984,7 +953,7 @@ void start_children( int children ) running++; break; } - } + } if ( s_stop ) { break; } @@ -1029,7 +998,7 @@ int main( int argc, char * argv[] ) struct timeval tv_req_end; int slow_script_msec = 0; char time_buf[40]; - + #ifdef HAVE_SIGNAL_H #if defined(SIGPIPE) && defined(SIG_IGN) signal(SIGPIPE, SIG_IGN); @@ -1040,8 +1009,12 @@ int main( int argc, char * argv[] ) tsrm_startup(1, 1, 0, NULL); #endif +#ifdef ZEND_SIGNALS + zend_signal_startup(); +#endif + if (argc > 1 ) { - if ( parse_opt( argc, argv, &climode, + if ( parse_opt( argc, argv, &climode, &php_ini_path, &php_bind ) == -1 ) { return 1; } @@ -1065,7 +1038,7 @@ int main( int argc, char * argv[] ) #endif lsapi_sapi_module.executable_location = argv[0]; - + if ( ignore_php_ini ) lsapi_sapi_module.php_ini_ignore = 1; @@ -1101,9 +1074,9 @@ int main( int argc, char * argv[] ) } LSAPI_Init(); - + LSAPI_Init_Env_Parameters( NULL ); - lsapi_mode = 1; + lsapi_mode = 1; slow_script_msec = LSAPI_Get_Slow_Req_Msecs(); @@ -1117,16 +1090,16 @@ int main( int argc, char * argv[] ) if ( slow_script_msec ) { gettimeofday( &tv_req_begin, NULL ); } - ret = processReq(TSRMLS_C); + ret = processReq(); if ( slow_script_msec ) { gettimeofday( &tv_req_end, NULL ); - n = ((long) tv_req_end.tv_sec - tv_req_begin.tv_sec ) * 1000 + n = ((long) tv_req_end.tv_sec - tv_req_begin.tv_sec ) * 1000 + (tv_req_end.tv_usec - tv_req_begin.tv_usec) / 1000; if ( n > slow_script_msec ) { strftime( time_buf, 30, "%d/%b/%Y:%H:%M:%S", localtime( &tv_req_end.tv_sec ) ); fprintf( stderr, "[%s] Slow PHP script: %d ms\n URL: %s %s\n Query String: %s\n Script: %s\n", - time_buf, n, LSAPI_GetRequestMethod(), + time_buf, n, LSAPI_GetRequestMethod(), LSAPI_GetScriptName(), LSAPI_GetQueryString(), LSAPI_GetScriptFileName() ); @@ -1137,7 +1110,7 @@ int main( int argc, char * argv[] ) break; } } - php_module_shutdown(TSRMLS_C); + php_module_shutdown(); #ifdef ZTS tsrm_shutdown(); @@ -1198,11 +1171,7 @@ zend_module_entry litespeed_module_entry = { static int add_associate_array( const char * pKey, int keyLen, const char * pValue, int valLen, void * arg ) { - add_assoc_string_ex( (zval *)arg, (char *)pKey, keyLen+1, (char *)pValue -#if PHP_MAJOR_VERSION < 7 - , 1 -#endif - ); + add_assoc_string_ex((zval *)arg, (char *)pKey, keyLen, (char *)pValue); return 1; } @@ -1256,16 +1225,12 @@ PHP_FUNCTION(litespeed_response_headers) headerBuf[len] = 0; if ( len ) { while( isspace(*++p)); - add_assoc_string_ex(return_value, headerBuf, len+1, p -#if PHP_MAJOR_VERSION < 7 - , 1 -#endif - ); + add_assoc_string_ex(return_value, headerBuf, len, p); } } } h = zend_llist_get_next_ex(&SG(sapi_headers).headers, &pos); - } + } } /* }}} */ @@ -1275,7 +1240,7 @@ PHP_FUNCTION(litespeed_response_headers) Fetch all loaded module names */ PHP_FUNCTION(apache_get_modules) { - static const char * mod_names[] = + static const char * mod_names[] = { "mod_rewrite", "mod_mime", "mod_headers", "mod_expires", "mod_auth_basic", NULL }; @@ -1287,10 +1252,10 @@ PHP_FUNCTION(apache_get_modules) array_init(return_value); while( *name ) { - add_next_index_string(return_value, *name + add_next_index_string(return_value, *name #if PHP_MAJOR_VERSION < 7 , 1 -#endif +#endif ); ++name; } diff --git a/sapi/litespeed/lsapidef.h b/sapi/litespeed/lsapidef.h index 0ddf32d287..56dfe7a3b8 100644 --- a/sapi/litespeed/lsapidef.h +++ b/sapi/litespeed/lsapidef.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -22,18 +22,18 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are -met: +met: * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided - with the distribution. + with the distribution. * Neither the name of the Lite Speed Technologies Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior - written permission. + written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -45,7 +45,7 @@ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -94,7 +94,7 @@ enum /* Values for m_flag in lsapi_packet_header */ #define LSAPI_ENDIAN_LITTLE 0 -#define LSAPI_ENDIAN_BIG 1 +#define LSAPI_ENDIAN_BIG 1 #define LSAPI_ENDIAN_BIT 1 #if defined(__i386__)||defined( __x86_64 )||defined( __x86_64__ ) @@ -137,7 +137,7 @@ struct lsapi_packet_header /* LSAPI request header packet - + 1. struct lsapi_req_header 2. struct lsapi_http_header_index 3. lsapi_header_offset * unknownHeaders @@ -148,7 +148,7 @@ struct lsapi_packet_header struct lsapi_req_header { struct lsapi_packet_header m_pktHeader; - + int32_t m_httpHeaderLen; int32_t m_reqBodyLen; int32_t m_scriptFileOff; /* path to the script file. */ @@ -162,11 +162,11 @@ struct lsapi_req_header struct lsapi_http_header_index -{ +{ int16_t m_headerLen[H_TRANSFER_ENCODING+1]; int32_t m_headerOff[H_TRANSFER_ENCODING+1]; -} ; - +} ; + struct lsapi_header_offset { int32_t nameOff; diff --git a/sapi/litespeed/lsapilib.c b/sapi/litespeed/lsapilib.c index 75bd30e2b9..4fc4c6e2e6 100644 --- a/sapi/litespeed/lsapilib.c +++ b/sapi/litespeed/lsapilib.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -22,18 +22,18 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are -met: +met: * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided - with the distribution. + with the distribution. * Neither the name of the Lite Speed Technologies Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior - written permission. + written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -45,7 +45,7 @@ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -153,7 +153,7 @@ static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] = "HTTP_VIA", "HTTP_TRANSFER_ENCODING" }; - + static int CGI_HEADER_LEN[H_TRANSFER_ENCODING+1] = { 11, 19, 20, 20, 18, 15, 12, 14, 11, 12, 9, 11, 12, 15, 18, 22, 13, 18, 13, 24, 15, 10, 20, 8, 22 }; @@ -184,7 +184,7 @@ static int HTTP_HEADER_LEN[H_TRANSFER_ENCODING+1] = { 6, 14, 15, 15, 13, 10, 12, 14, 6, 7, 4, 6, 7, 10, //user-agent 13,17, 8, 13, 8, 19, 10, 5, 15, 3, 17 }; - + static void lsapi_sigpipe( int sig ) { } @@ -196,7 +196,7 @@ static void lsapi_siguser1( int sig ) #ifndef sighandler_t typedef void (*sighandler_t)(int); #endif - + static void lsapi_signal(int signo, sighandler_t handler) { struct sigaction sa; @@ -219,7 +219,7 @@ static void lsapi_enable_core_dump() #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \ || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) int mib[2]; - size_t len; + size_t len; len = 2; if ( sysctlnametomib("kern.sugid_coredump", mib, &len) == 0 ) @@ -230,7 +230,7 @@ static void lsapi_enable_core_dump() "core dump may not be available!"); } - + #endif #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) @@ -511,7 +511,7 @@ static inline void swapIntEndian( int * pInteger ) b = p[1]; p[1] = p[2]; p[2] = b; - + } static inline void fixEndian( LSAPI_Request * pReq ) @@ -620,7 +620,7 @@ static int lsapi_load_lve_lib() if (s_liblve) { fp_lve_is_available = dlsym(s_liblve, "lve_is_available"); - if (dlerror() == NULL) + if (dlerror() == NULL) { if ( !(*fp_lve_is_available)() ) { @@ -646,7 +646,7 @@ static int init_lve_ex() { int rc; if ( !s_liblve ) - return -1; + return -1; fp_lve_instance_init = dlsym(s_liblve, "lve_instance_init"); fp_lve_destroy = dlsym(s_liblve, "lve_destroy"); fp_lve_enter = dlsym(s_liblve, "lve_enter"); @@ -654,13 +654,13 @@ static int init_lve_ex() if ( s_enable_lve >= LSAPI_CAGEFS_ENABLED ) fp_lve_jail = dlsym(s_liblve, "jail" ); - if ( s_lve == NULL ) + if ( s_lve == NULL ) { rc = (*fp_lve_instance_init)(NULL); s_lve = malloc(rc); } rc = (*fp_lve_instance_init)(s_lve); - if (rc != 0) + if (rc != 0) { perror( "LSAPI: Unable to initialize LVE" ); free( s_lve ); @@ -668,7 +668,7 @@ static int init_lve_ex() return -1; } return 0; - + } #endif @@ -735,7 +735,7 @@ static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char static int lsapi_lve_error( LSAPI_Request * pReq ) { - static const char * headers[] = + static const char * headers[] = { "Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0", "Pragma: no-cache", @@ -751,7 +751,7 @@ static int lsapi_lve_error( LSAPI_Request * pReq ) "Please try again later.\n" "<HR>\n" "</BODY></HTML>\n"; - + LSAPI_ErrResponse_r( pReq, 508, headers, achBody, sizeof( achBody ) - 1 ); return 0; } @@ -785,7 +785,7 @@ static int lsapi_jailLVE( LSAPI_Request * pReq, uid_t uid, struct passwd * pw ) ret = (*fp_lve_jail)( pw, error_msg ); if ( ret < 0 ) { - fprintf( stderr, "LSAPI (%d): LVE jail(%d) ressult: %d, error: %s !\n", + fprintf( stderr, "LSAPI (%d): LVE jail(%d) ressult: %d, error: %s !\n", getpid(), uid, ret, error_msg ); LSAPI_perror_r( pReq, "LSAPI: jail() failure.", NULL ); return -1; @@ -830,7 +830,7 @@ static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * p pw = getpwuid( uid ); #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) if ( s_lve ) - { + { if( lsapi_enterLVE( pReq, uid ) == -1 ) return -1; if ( pw && fp_lve_jail) @@ -847,7 +847,7 @@ static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * p } } #endif - //if ( !uid || !gid ) //do not allow root + //if ( !uid || !gid ) //do not allow root //{ // return -1; //} @@ -903,7 +903,7 @@ static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * p return 0; } -static int lsapi_suexec_auth( LSAPI_Request *pReq, +static int lsapi_suexec_auth( LSAPI_Request *pReq, char * pAuth, int len, char * pUgid, int ugidLen ) { lsapi_MD5_CTX md5ctx; @@ -935,7 +935,7 @@ static int lsapi_changeUGid( LSAPI_Request * pReq ) //with special ID 0x00 //authenticate the suEXEC request; //first one should be MD5( nonce + lscgid secret ) - //remember to clear the secret after verification + //remember to clear the secret after verification //it should be set at the end of special env i = pReq->m_pHeader->m_cntSpecialEnv - 1; if ( i >= 0 ) @@ -951,7 +951,7 @@ static int lsapi_changeUGid( LSAPI_Request * pReq ) { --pReq->m_pHeader->m_cntSpecialEnv; uid = *(uint32_t *)pEnv->pValue; - gid = *(((uint32_t *)pEnv->pValue) + 1 ); + gid = *(((uint32_t *)pEnv->pValue) + 1 ); //fprintf( stderr, "LSAPI: SUEXEC_UGID set UID: %d, GID: %d\n", uid, gid ); } else @@ -961,8 +961,8 @@ static int lsapi_changeUGid( LSAPI_Request * pReq ) } if ( pEnv&& lsapi_suexec_auth( pReq, pAuth->pValue, pAuth->valLen, pEnv->pValue, pEnv->valLen ) == 0 ) { - //read UID, GID from specialEnv - + //read UID, GID from specialEnv + } else { @@ -990,10 +990,10 @@ static int lsapi_changeUGid( LSAPI_Request * pReq ) return -1; } - s_uid = uid; + s_uid = uid; return 0; - + } static int parseContentLenFromHeader(LSAPI_Request * pReq) @@ -1049,7 +1049,7 @@ static int parseRequest( LSAPI_Request * pReq, int totalLen ) pReq->m_pScriptName = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptNameOff; pReq->m_pQueryString = pReq->m_pReqBuf + pReq->m_pHeader->m_queryStringOff; pReq->m_pRequestMethod = pReq->m_pReqBuf + pReq->m_pHeader->m_requestMethodOff; - + pBegin = pReq->m_pReqBuf + (( pBegin - pReq->m_pReqBuf + 7 ) & (~0x7)); pReq->m_pHeaderIndex = ( struct lsapi_http_header_index * )pBegin; pBegin += sizeof( struct lsapi_http_header_index ); @@ -1082,7 +1082,7 @@ static int parseRequest( LSAPI_Request * pReq, int totalLen ) { parseContentLenFromHeader(pReq); } - + return 0; } @@ -1140,7 +1140,7 @@ static inline int lsapi_notify_pid( int fd ) 8 + LSAPI_PACKET_HEADER_LEN ); memmove( &achBuf[8], "\0PID", 4 ); *((int *)&achBuf[12]) = getpid(); - + if ( write( fd, achBuf, 16 ) < 16 ) return -1; return 0; @@ -1164,7 +1164,7 @@ static inline int init_conn_key( int fd ) < LSAPI_PACKET_HEADER_LEN+8 ) return -1; return 0; - + } @@ -1253,9 +1253,9 @@ int LSAPI_Init(void) #if defined(SIGXFSZ) && defined(SIG_IGN) signal(SIGXFSZ, SIG_IGN); #endif - /* let STDOUT function as STDERR, + /* let STDOUT function as STDERR, just in case writing to STDOUT directly */ - dup2( 2, 1 ); + dup2( 2, 1 ); if ( LSAPI_InitRequest( &g_req, LSAPI_SOCK_FILENO ) == -1 ) return -1; g_inited = 1; @@ -1295,8 +1295,8 @@ int LSAPI_InitRequest( LSAPI_Request * pReq, int fd ) { fd = dup( fd ); newfd = open( "/dev/null", O_RDWR ); - dup2( newfd, STDIN_FILENO ); - } + dup2( newfd, STDIN_FILENO ); + } if ( isPipe( fd ) ) { @@ -1329,7 +1329,7 @@ int LSAPI_Accept_r( LSAPI_Request * pReq ) char achPeer[128]; socklen_t len; int nodelay = 1; - + if ( !pReq ) return -1; if ( LSAPI_Finish_r( pReq ) == -1 ) @@ -1355,7 +1355,7 @@ int LSAPI_Accept_r( LSAPI_Request * pReq ) { lsapi_set_nblock( pReq->m_fd , 0 ); if (((struct sockaddr *)&achPeer)->sa_family == AF_INET ) - { + { setsockopt(pReq->m_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay)); } @@ -1399,7 +1399,7 @@ int LSAPI_Finish_r( LSAPI_Request * pReq ) { Flush_RespBuf_r( pReq ); } - + pReq->m_pIovecCur->iov_base = (void *)&finish; pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN; pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN; @@ -1417,7 +1417,7 @@ void LSAPI_Reset_r( LSAPI_Request * pReq ) pReq->m_pRespBufPos = pReq->m_pRespBuf; pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1; pReq->m_pRespHeaderBufPos = pReq->m_pRespHeaderBuf; - + memset( &pReq->m_pHeaderIndex, 0, (char *)(pReq->m_respHeaderLen) - (char *)&pReq->m_pHeaderIndex ); } @@ -1432,7 +1432,7 @@ int LSAPI_Release_r( LSAPI_Request * pReq ) if ( pReq->m_pEnvList ) free( pReq->m_pEnvList ); if ( pReq->m_pRespHeaderBuf ) - free( pReq->m_pRespHeaderBuf ); + free( pReq->m_pRespHeaderBuf ); return 0; } @@ -1468,7 +1468,7 @@ static int readBodyToReqBuf( LSAPI_Request * pReq ) return -1; if ( len > bodyLeft ) len = bodyLeft; - + len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, len ); if ( len > 0 ) pReq->m_bufRead += len; @@ -1499,12 +1499,12 @@ int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, in char * pBufCur = pBuf; char * pCur; char * p; - if (!pReq || (pReq->m_fd ==-1) ||( !pBuf )||(bufLen < 0 )|| !getLF ) + if (!pReq || (pReq->m_fd ==-1) ||( !pBuf )|| !getLF ) return -1; *getLF = 0; while( (left = pBufEnd - pBufCur ) > 0 ) { - + len = pReq->m_bufRead - pReq->m_bufProcessed; if ( len <= 0 ) { @@ -1525,7 +1525,7 @@ int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, in pReq->m_bufProcessed += len; pReq->m_reqBodyRead += len; - + if ( p ) { *getLF = 1; @@ -1533,7 +1533,7 @@ int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, in } } *pBufCur = 0; - + return pBufCur - pBuf; } @@ -1543,11 +1543,11 @@ ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen ) ssize_t len; off_t total; /* char *pOldBuf = pBuf; */ - if (!pReq || (pReq->m_fd ==-1) || ( !pBuf )||(bufLen < 0 )) + if (!pReq || (pReq->m_fd ==-1) || ( !pBuf )) return -1; total = pReq->m_reqBodyLen - pReq->m_reqBodyRead; - + if ( total <= 0 ) return 0; if ( total < bufLen ) @@ -1583,7 +1583,7 @@ ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen ) } pReq->m_reqBodyRead += total; return total; - + } @@ -1596,7 +1596,7 @@ ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len ) ssize_t toWrite; ssize_t packetLen; int skip = 0; - + if ( !pReq || !pBuf || (pReq->m_fd == -1) ) return -1; if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) @@ -1621,13 +1621,13 @@ ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len ) pReq->m_pRespBufPos += len - skip; return len; } - - + + pHeader = pReq->m_respPktHeader; p = pBuf + skip; pEnd = pBuf + len; bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf; - + while( ( toWrite = pEnd - p ) > 0 ) { packetLen = toWrite + bufLen; @@ -1636,7 +1636,7 @@ ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len ) packetLen = LSAPI_MAX_DATA_PACKET_LEN; toWrite = packetLen - bufLen; } - + lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM, packetLen + LSAPI_PACKET_HEADER_LEN ); pReq->m_totalLen += packetLen + LSAPI_PACKET_HEADER_LEN; @@ -1650,7 +1650,7 @@ ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len ) pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf; pReq->m_pIovecCur->iov_len = bufLen; pReq->m_pRespBufPos = pReq->m_pRespBuf; - ++pReq->m_pIovecCur; + ++pReq->m_pIovecCur; bufLen = 0; } @@ -1672,7 +1672,7 @@ ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len ) return p - pBuf; } -#if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) +#if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size ) { ssize_t ret; @@ -1701,7 +1701,7 @@ ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size ) return ret; } #endif - + #if defined(sun) || defined(__sun) #include <sys/sendfile.h> ssize_t gsendfile( int fdOut, int fdIn, off_t *off, size_t size ) @@ -1747,16 +1747,16 @@ ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t siz LSAPI_FinalizeRespHeaders_r( pReq ); } pReq->m_reqState |= LSAPI_ST_RESP_BODY; - + LSAPI_Flush_r(pReq); - + lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM, size + LSAPI_PACKET_HEADER_LEN ); - + if (write(pReq->m_fd, (const char *) pHeader, LSAPI_PACKET_HEADER_LEN ) != LSAPI_PACKET_HEADER_LEN) return -1; - + return gsendfile( pReq->m_fd, fdIn, off, size ); } @@ -1779,7 +1779,7 @@ void Flush_RespBuf_r( LSAPI_Request * pReq ) pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf; pReq->m_pIovecCur->iov_len = bufLen; pReq->m_pRespBufPos = pReq->m_pRespBuf; - ++pReq->m_pIovecCur; + ++pReq->m_pIovecCur; bufLen = 0; } } @@ -1811,11 +1811,11 @@ int LSAPI_Flush_r( LSAPI_Request * pReq ) { Flush_RespBuf_r( pReq ); } - + n = pReq->m_pIovecCur - pReq->m_pIovecToWrite; if ( n > 0 ) { - + ret = lsapi_writev( pReq->m_fd, &pReq->m_pIovecToWrite, n, pReq->m_totalLen ); if ( ret < pReq->m_totalLen ) @@ -1841,7 +1841,7 @@ ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t le int ret; struct iovec iov[2]; struct iovec *pIov; - + if ( !pReq ) return -1; if (( pReq->m_fd == -1 )||(pReq->m_fd == pReq->m_fdListen )) @@ -1850,7 +1850,7 @@ ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t le { LSAPI_Flush_r( pReq ); } - + p = pBuf; pEnd = pBuf + len; @@ -1974,7 +1974,7 @@ struct _headerInfo int compareValueLocation(const void * v1, const void *v2 ) { return ((const struct _headerInfo *)v1)->_value - - ((const struct _headerInfo *)v2)->_value; + ((const struct _headerInfo *)v2)->_value; } int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq, @@ -2005,7 +2005,7 @@ int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq, headers[count]._value = pValue; headers[count]._valueLen = len; ++count; - + //ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i], // pValue, len, arg ); //if ( ret <= 0 ) @@ -2034,7 +2034,7 @@ int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq, ++count; if ( count == 512 ) break; - //ret = (*fn)( pKey, keyLen, + //ret = (*fn)( pKey, keyLen, // pValue, pCur->valueLen, arg ); //if ( ret <= 0 ) // return ret; @@ -2044,13 +2044,13 @@ int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq, qsort( headers, count, sizeof( struct _headerInfo ), compareValueLocation ); for( i = 0; i < count; ++i ) { - ret = (*fn)( headers[i]._name, headers[i]._nameLen, + ret = (*fn)( headers[i]._name, headers[i]._nameLen, headers[i]._value, headers[i]._valueLen, arg ); if ( ret <= 0 ) return ret; } return count; - + } @@ -2111,7 +2111,7 @@ int LSAPI_ForeachHeader_r( LSAPI_Request * pReq, pValue = pReq->m_pHttpHeader + pCur->valueOff; *(pValue + pCur->valueLen ) = 0; - ret = (*fn)( achHeaderName, keyLen, + ret = (*fn)( achHeaderName, keyLen, pValue, pCur->valueLen, arg ); if ( ret <= 0 ) return ret; @@ -2119,7 +2119,7 @@ int LSAPI_ForeachHeader_r( LSAPI_Request * pReq, } } return count + pReq->m_pHeader->m_cntUnknownHeaders; - + } static int EnvForeach( struct LSAPI_key_value_pair * pEnv, @@ -2188,7 +2188,7 @@ int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq ) pReq->m_totalLen += pReq->m_pIovecCur->iov_len; ++pReq->m_pIovecCur; } - + pReq->m_pIovec->iov_len = sizeof( struct lsapi_resp_header) + pReq->m_respHeader.m_respInfo.m_cntHeaders * sizeof( short ); pReq->m_totalLen += pReq->m_pIovec->iov_len; @@ -2201,11 +2201,11 @@ int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq ) } -int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName, +int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName, const char * pHeaderValue ) { int nameLen, valLen, len; - if ( !pReq || !pHeaderName || !pHeaderValue ) + if ( !pReq || !pHeaderName || !pHeaderValue ) return -1; if ( pReq->m_reqState & LSAPI_ST_RESP_BODY ) return -1; @@ -2349,7 +2349,7 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr ) struct addrinfo *res, hints; int doAddrInfo = 0; int port; - + if ( !pBind ) return -1; @@ -2373,7 +2373,7 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr ) if ( !pEnd ) return -1; *pEnd++ = 0; - + if ( *p == '*' ) { strcpy( achAddr, "::" ); @@ -2388,7 +2388,7 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr ) if ( !pEnd ) return -1; *pEnd++ = 0; - + doAddrInfo = 0; if ( *p == '*' ) { @@ -2408,7 +2408,7 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr ) } if ( *pEnd == ':' ) ++pEnd; - + port = atoi( pEnd ); if (( port <= 0 )||( port > 65535 )) return -1; @@ -2429,13 +2429,13 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr ) memcpy(pAddr, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); } - + if ( pAddr->sa_family == AF_INET ) ((struct sockaddr_in *)pAddr)->sin_port = htons( port ); else ((struct sockaddr_in6 *)pAddr)->sin6_port = htons( port ); return 0; - + } int LSAPI_CreateListenSock( const char * pBind, int backlog ) @@ -2481,11 +2481,11 @@ typedef struct _lsapi_prefork_server int m_iChildrenMaxIdleTime; int m_iMaxReqProcessTime; int m_iAvoidFork; - + lsapi_child_status * m_pChildrenStatus; lsapi_child_status * m_pChildrenStatusCur; lsapi_child_status * m_pChildrenStatusEnd; - + }lsapi_prefork_server; static lsapi_prefork_server * g_prefork_server = NULL; @@ -2500,7 +2500,7 @@ int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork ) if ( max_children >= 10000) max_children = 10000; - + g_prefork_server = (lsapi_prefork_server *)malloc( sizeof( lsapi_prefork_server ) ); if ( !g_prefork_server ) return -1; @@ -2514,14 +2514,14 @@ int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork ) setpgid( pid, pid ); g_prefork_server->m_iAvoidFork = avoidFork; g_prefork_server->m_iMaxChildren = max_children; - + g_prefork_server->m_iExtraChildren = ( avoidFork ) ? 0 : (max_children / 3) ; g_prefork_server->m_iMaxIdleChildren = ( avoidFork ) ? (max_children + 1) : (max_children / 3); if ( g_prefork_server->m_iMaxIdleChildren == 0 ) g_prefork_server->m_iMaxIdleChildren = 1; g_prefork_server->m_iChildrenMaxIdleTime = 300; g_prefork_server->m_iMaxReqProcessTime = 3600; - return 0; + return 0; } void LSAPI_Set_Server_fd( int fd ) @@ -2628,7 +2628,7 @@ static void lsapi_sigchild( int signal ) static int lsapi_init_children_status() { int size = 4096; - + char * pBuf; size = (g_prefork_server->m_iMaxChildren + g_prefork_server->m_iExtraChildren ) * sizeof( lsapi_child_status ) * 2; size = (size + 4095 ) / 4096 * 4096; @@ -2656,9 +2656,9 @@ static void dump_debug_info( lsapi_child_status * pStatus, long tmCur ) } s_pid_dump_debug_info = fork(); - fprintf( stderr, "[%s] Possible runaway process, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld\n", - ctime(&tmCur), getpid(), pStatus->m_pid, pStatus->m_iReqCounter, - tmCur - pStatus->m_tmReqBegin, tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart ); + fprintf( stderr, "[%s] Possible runaway process, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld\n", + ctime(&tmCur), getpid(), pStatus->m_pid, pStatus->m_iReqCounter, + tmCur - pStatus->m_tmReqBegin, tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart ); snprintf( achCmd, 1024, "gdb --batch -ex \"attach %d\" -ex \"set height 0\" -ex \"bt\" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2", pStatus->m_pid, pStatus->m_pid ); if ( system( achCmd ) == -1 ) perror( "system()" ); @@ -2681,7 +2681,7 @@ static void lsapi_check_child_status( long tmCur ) ++count; if ( !pStatus->m_inProcess ) { - + if (( g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren)|| ( idle > g_prefork_server->m_iMaxIdleChildren )) { @@ -2701,7 +2701,7 @@ static void lsapi_check_child_status( long tmCur ) } else { - if ( tmCur - pStatus->m_tmReqBegin > + if ( tmCur - pStatus->m_tmReqBegin > g_prefork_server->m_iMaxReqProcessTime ) { if (( ( pStatus->m_iKillSent % 5 ) == 0 )&&( s_dump_debug_info )) @@ -2736,7 +2736,7 @@ static void lsapi_check_child_status( long tmCur ) } if ( abs( g_prefork_server->m_iCurChildren - count ) > 1 ) { - fprintf( stderr, "Children tracking is wrong: PID: %d, Cur Children: %d, count: %d, idle: %d, dying: %d\n", getpid(), + fprintf( stderr, "Children tracking is wrong: PID: %d, Cur Children: %d, count: %d, idle: %d, dying: %d\n", getpid(), g_prefork_server->m_iCurChildren, count, idle, dying ); } @@ -2780,7 +2780,7 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re sigset_t orig_mask; lsapi_init_children_status(); - + setsid(); act.sa_flags = 0; @@ -2870,17 +2870,17 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re sigemptyset( &mask ); sigaddset( &mask, SIGCHLD ); - - if ( sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0 ) + + if ( sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0 ) { perror( "sigprocmask(SIG_BLOCK) to block SIGCHLD" ); } pid = fork(); - + if ( !pid ) { - if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0) + if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0) perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK in child" ); g_prefork_server = NULL; s_ppid = getppid(); @@ -2922,7 +2922,7 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re close( pReq->m_fd ); pReq->m_fd = -1; - if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0) + if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0) perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK" ); } @@ -2971,7 +2971,7 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq ) s_pChildStatus->m_tmWaitBegin = time( NULL ); } - + while( g_running ) { if ( pReq->m_fd != -1 ) @@ -2990,7 +2990,7 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq ) if ( !g_running ) return -1; if ((s_req_processed)&&( s_pChildStatus )&&( s_pChildStatus->m_iKillSent )) - return -1; + return -1; FD_ZERO( &readfds ); FD_SET( fd, &readfds ); timeout.tv_sec = 1; @@ -3018,7 +3018,7 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq ) else if ( ret >= 1 ) { if (s_req_processed && ( s_pChildStatus )&&( s_pChildStatus->m_iKillSent )) - return -1; + return -1; if ( fd == pReq->m_fdListen ) { pReq->m_fd = lsapi_accept( pReq->m_fdListen ); @@ -3066,7 +3066,7 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq ) LSAPI_Reset_r( pReq ); } return -1; - + } void LSAPI_Set_Max_Reqs( int reqs ) @@ -3135,19 +3135,19 @@ static void unset_lsapi_envs() #else env = environ; #endif - while( env != NULL && *env != NULL ) + while( env != NULL && *env != NULL ) { - if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 ) - || (!strncmp( *env, "PHPRC=", 6 )&&(!s_uid))) - { + if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 ) + || (!strncmp( *env, "PHPRC=", 6 )&&(!s_uid))) + { char ** del = env; - do + do *del = del[1]; while( *del++ ); } else ++env; - } + } } static int lsapi_initSuEXEC() @@ -3174,7 +3174,7 @@ static int lsapi_initSuEXEC() } p = getenv( "LSAPI_SECRET" ); if (( !p )||( readSecret(p) == -1 )) - return -1; + return -1; if ( g_prefork_server ) { if ( g_prefork_server->m_iMaxChildren < 100 ) @@ -3224,7 +3224,7 @@ int LSAPI_Init_Env_Parameters( fn_select_t fp ) if ( p ) { avoidFork = atoi( p ); - } + } p = getenv( "LSAPI_ACCEPT_NOTIFY" ); if ( p ) @@ -3233,7 +3233,7 @@ int LSAPI_Init_Env_Parameters( fn_select_t fp ) } p = getenv( "LSAPI_SLOW_REQ_MSECS" ); - if ( p ) + if ( p ) { n = atoi( p ); LSAPI_Set_Slow_Req_Msecs( n ); @@ -3283,26 +3283,26 @@ int LSAPI_Init_Env_Parameters( fn_select_t fp ) p = getenv( "LSAPI_EXTRA_CHILDREN" ); if ( p ) LSAPI_Set_Extra_Children( atoi( p ) ); - + p = getenv( "LSAPI_MAX_IDLE_CHILDREN" ); if ( p ) LSAPI_Set_Max_Idle_Children( atoi( p ) ); - + p = getenv( "LSAPI_PGRP_MAX_IDLE" ); if ( p ) { LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) ); } - + p = getenv( "LSAPI_MAX_PROCESS_TIME" ); - if ( p ) + if ( p ) LSAPI_Set_Max_Process_Time( atoi( p ) ); - + if ( getenv( "LSAPI_PPID_NO_CHECK" ) ) { LSAPI_No_Check_ppid(); } - + p = getenv( "LSAPI_DUMP_DEBUG_INFO" ); if ( p ) s_dump_debug_info = atoi( p ); @@ -3318,7 +3318,7 @@ int LSAPI_Init_Env_Parameters( fn_select_t fp ) } -int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders, +int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders, const char * pBody, int bodyLen ) { LSAPI_SetRespStatus_r( pReq, code ); diff --git a/sapi/litespeed/lsapilib.h b/sapi/litespeed/lsapilib.h index 5ecde2155f..5b5ca15f2c 100644 --- a/sapi/litespeed/lsapilib.h +++ b/sapi/litespeed/lsapilib.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -22,18 +22,18 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are -met: +met: * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided - with the distribution. + with the distribution. * Neither the name of the Lite Speed Technologies Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior - written permission. + written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -45,7 +45,7 @@ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ @@ -83,7 +83,7 @@ typedef struct lsapi_request char * m_pReqBuf; int m_reqBufSize; - + char * m_pRespBuf; char * m_pRespBufEnd; char * m_pRespBufPos; @@ -96,7 +96,7 @@ typedef struct lsapi_request struct iovec * m_pIovec; struct iovec * m_pIovecEnd; struct iovec * m_pIovecCur; - struct iovec * m_pIovecToWrite; + struct iovec * m_pIovecToWrite; struct lsapi_packet_header * m_respPktHeaderEnd; @@ -108,7 +108,7 @@ typedef struct lsapi_request struct lsapi_http_header_index * m_pHeaderIndex; struct lsapi_header_offset * m_pUnknownHeader; - + char * m_pScriptFile; char * m_pScriptName; char * m_pQueryString; @@ -120,9 +120,9 @@ typedef struct lsapi_request off_t m_reqBodyRead; int m_bufProcessed; int m_bufRead; - + struct lsapi_packet_header m_respPktHeader[5]; - + struct lsapi_resp_header m_respHeader; short m_respHeaderLen[LSAPI_MAX_RESP_HEADERS]; void * m_pAppData; @@ -168,7 +168,7 @@ int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ); char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name ); - + ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t len ); @@ -189,7 +189,7 @@ int LSAPI_Flush_r( LSAPI_Request * pReq ); int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len ); -int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName, +int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName, const char * pHeaderValue ); int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders, @@ -331,7 +331,7 @@ static inline ssize_t LSAPI_Write( const char * pBuf, ssize_t len ) static inline ssize_t LSAPI_sendfile( int fdIn, off_t* off, size_t size ) { - return LSAPI_sendfile_r(&g_req, fdIn, off, size ); + return LSAPI_sendfile_r(&g_req, fdIn, off, size ); } static inline ssize_t LSAPI_Write_Stderr( const char * pBuf, ssize_t len ) diff --git a/sapi/milter/CREDITS b/sapi/milter/CREDITS deleted file mode 100644 index cd00d6774b..0000000000 --- a/sapi/milter/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -Sendmail Milter -Harald Radi diff --git a/sapi/milter/EXPERIMENTAL b/sapi/milter/EXPERIMENTAL deleted file mode 100644 index 293159a693..0000000000 --- a/sapi/milter/EXPERIMENTAL +++ /dev/null @@ -1,5 +0,0 @@ -this module is experimental, -its functions may change their names -or move to extension all together -so do not rely to much on them -you have been warned! diff --git a/sapi/milter/Makefile.frag b/sapi/milter/Makefile.frag deleted file mode 100644 index f193f56b01..0000000000 --- a/sapi/milter/Makefile.frag +++ /dev/null @@ -1,8 +0,0 @@ -milter: $(SAPI_MILTER_PATH) - -$(SAPI_MILTER_PATH): $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_MILTER_OBJS) - $(BUILD_MILTER) - -install-milter: $(SAPI_MILTER_PATH) - @$(INSTALL) -m 0755 $(SAPI_MILTER_PATH) $(INSTALL_ROOT)$(bindir)/php-milter - diff --git a/sapi/milter/TODO b/sapi/milter/TODO deleted file mode 100644 index 4a427ea131..0000000000 --- a/sapi/milter/TODO +++ /dev/null @@ -1,5 +0,0 @@ -threaded version still leaks mem, don't know why -extensions aren't loaded -stdout to syslog -testing -documentation
\ No newline at end of file diff --git a/sapi/milter/config.m4 b/sapi/milter/config.m4 deleted file mode 100644 index a69ab2e1e7..0000000000 --- a/sapi/milter/config.m4 +++ /dev/null @@ -1,31 +0,0 @@ -dnl -dnl $Id$ -dnl - -PHP_ARG_WITH(milter, for Milter support, -[ --with-milter[=DIR] Build PHP as Milter application], no, no) - -if test "$PHP_MILTER" != "no"; then - if test "$PHP_MILTER" = "yes"; then - if test -f /usr/lib/libmilter.a ; then - MILTERPATH=/usr/lib - else - if test -f /usr/lib/libmilter/libmilter.a ; then - MILTERPATH=/usr/lib/libmilter - else - AC_MSG_ERROR([Unable to find libmilter.a]) - fi - fi - else - MILTERPATH=$PHP_MILTER - fi - - SAPI_MILTER_PATH=sapi/milter/php-milter - PHP_BUILD_THREAD_SAFE - PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/sapi/milter/Makefile.frag,$abs_srcdir/sapi/milter,sapi/milter) - PHP_SELECT_SAPI(milter, program, php_milter.c getopt.c,,'$(SAPI_MILTER_PATH)') - PHP_ADD_LIBRARY_WITH_PATH(milter, $MILTERPATH,) - BUILD_MILTER="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_MILTER_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_MILTER_PATH)" - PHP_SUBST(SAPI_MILTER_PATH) - PHP_SUBST(BUILD_MILTER) -fi diff --git a/sapi/milter/getopt.c b/sapi/milter/getopt.c deleted file mode 100644 index f5874d577e..0000000000 --- a/sapi/milter/getopt.c +++ /dev/null @@ -1,173 +0,0 @@ -/* Borrowed from Apache NT Port */ - -#include <stdio.h> -#include <string.h> -#include <assert.h> -#include <stdlib.h> -#include "php_getopt.h" -#define OPTERRCOLON (1) -#define OPTERRNF (2) -#define OPTERRARG (3) - - -char *ap_php_optarg; -int ap_php_optind = 1; -static int ap_php_opterr = 1; - -static int -ap_php_optiserr(int argc, char * const *argv, int oint, const char *optstr, - int optchr, int err) -{ - if (ap_php_opterr) - { - fprintf(stderr, "Error in argument %d, char %d: ", oint, optchr+1); - switch(err) - { - case OPTERRCOLON: - fprintf(stderr, ": in flags\n"); - break; - case OPTERRNF: - fprintf(stderr, "option not found %c\n", argv[oint][optchr]); - break; - case OPTERRARG: - fprintf(stderr, "no argument for option %c\n", argv[oint][optchr]); - break; - default: - fprintf(stderr, "unknown\n"); - break; - } - } - return('?'); -} - -int ap_php_getopt(int argc, char* const *argv, const char *optstr) -{ - static int optchr = 0; - static int dash = 0; /* have already seen the - */ - - char *cp; - - if (ap_php_optind >= argc) - return(EOF); - if (!dash && (argv[ap_php_optind][0] != '-')) - return(EOF); - if (!dash && (argv[ap_php_optind][0] == '-') && !argv[ap_php_optind][1]) - { - /* - * use to specify stdin. Need to let pgm process this and - * the following args - */ - return(EOF); - } - if ((argv[ap_php_optind][0] == '-') && (argv[ap_php_optind][1] == '-')) - { - /* -- indicates end of args */ - ap_php_optind++; - return(EOF); - } - if (!dash) - { - assert((argv[ap_php_optind][0] == '-') && argv[ap_php_optind][1]); - dash = 1; - optchr = 1; - } - - /* Check if the guy tries to do a -: kind of flag */ - assert(dash); - if (argv[ap_php_optind][optchr] == ':') - { - dash = 0; - ap_php_optind++; - return(ap_php_optiserr(argc, argv, ap_php_optind-1, optstr, optchr, OPTERRCOLON)); - } - if (!(cp = strchr(optstr, argv[ap_php_optind][optchr]))) - { - int errind = ap_php_optind; - int errchr = optchr; - - if (!argv[ap_php_optind][optchr+1]) - { - dash = 0; - ap_php_optind++; - } - else - optchr++; - return(ap_php_optiserr(argc, argv, errind, optstr, errchr, OPTERRNF)); - } - if (cp[1] == ':') - { - /* Check for cases where the value of the argument - is in the form -<arg> <val> or in the form -<arg><val> */ - dash = 0; - if(!argv[ap_php_optind][2]) { - ap_php_optind++; - if (ap_php_optind == argc) - return(ap_php_optiserr(argc, argv, ap_php_optind-1, optstr, optchr, OPTERRARG)); - ap_php_optarg = argv[ap_php_optind++]; - } - else - { - ap_php_optarg = &argv[ap_php_optind][2]; - ap_php_optind++; - } - return(*cp); - } - else - { - if (!argv[ap_php_optind][optchr+1]) - { - dash = 0; - ap_php_optind++; - } - else - optchr++; - return(*cp); - } - assert(0); - return(0); /* never reached */ -} - -#ifdef TESTGETOPT -int - main (int argc, char **argv) - { - int c; - extern char *ap_php_optarg; - extern int ap_php_optind; - int aflg = 0; - int bflg = 0; - int errflg = 0; - char *ofile = NULL; - - while ((c = ap_php_getopt(argc, argv, "abo:")) != EOF) - switch (c) { - case 'a': - if (bflg) - errflg++; - else - aflg++; - break; - case 'b': - if (aflg) - errflg++; - else - bflg++; - break; - case 'o': - ofile = ap_php_optarg; - (void)printf("ofile = %s\n", ofile); - break; - case '?': - errflg++; - } - if (errflg) { - (void)fprintf(stderr, - "usage: cmd [-a|-b] [-o <filename>] files...\n"); - exit (2); - } - for ( ; ap_php_optind < argc; ap_php_optind++) - (void)printf("%s\n", argv[ap_php_optind]); - return 0; - } - -#endif /* TESTGETOPT */ diff --git a/sapi/milter/milter.php b/sapi/milter/milter.php deleted file mode 100644 index 0878f2a4d9..0000000000 --- a/sapi/milter/milter.php +++ /dev/null @@ -1,132 +0,0 @@ -<?php -/** - * example milter script - * - * run: php-milter -D -p /path/to/sock milter.php - * - * for details on how to set up sendmail and configure the milter see - * http://www.sendmail.com/partner/resources/development/milter_api/ - * - * for api details see - * http://www.sendmail.com/partner/resources/development/milter_api/api.html - * - * below is a list of all callbacks, that are available through the milter sapi, - * if you leave one or more out they simply won't get called (e.g. if you secify an - * empty php file, the milter would do nothing :) - */ - -/** - * this function is called once on sapi startup, - * here you can specify the actions the filter may take - * - * see http://www.sendmail.com/partner/resources/development/milter_api/smfi_register.html#flags - */ - -function milter_log($msg) -{ - $GLOBALS['log'] = fopen("/tmp/milter.log", "a"); - fwrite($GLOBALS['log'], date("[H:i:s d.m.Y]") . "\t{$msg}\n"); - fclose($GLOBALS['log']); -} - -function milter_init() { - milter_log("-- startup --"); - milter_log("milter_init()"); - smfi_setflags(SMFIF_ADDHDRS); -} - -/** - * is called once, at the start of each SMTP connection - */ -function milter_connect($connect) -{ - milter_log("milter_connect('$connect')"); -} - -/** - * is called whenever the client sends a HELO/EHLO command. - * It may therefore be called between zero and three times. - */ -function milter_helo($helo) -{ - milter_log("milter_helo('$helo')"); -} - -/** - * is called once at the beginning of each message, - * before milter_envrcpt. - */ -function milter_envfrom($args) -{ - milter_log("milter_envfrom(args[])"); - foreach ($args as $ix => $arg) { - milter_log("\targs[$ix] = $arg"); - } -} - -/** - * is called once per recipient, hence one or more times per message, - * immediately after milter_envfrom - */ -function milter_envrcpt($args) -{ - milter_log("milter_envrcpt(args[])"); - foreach ($args as $ix => $arg) { - milter_log("\targs[$ix] = $arg"); - } -} - -/** - * is called zero or more times between milter_envrcpt and milter_eoh, - * once per message header - */ -function milter_header($header, $value) -{ - milter_log("milter_header('$header', '$value')"); -} - -/** - * is called once after all headers have been sent and processed. - */ -function milter_eoh() -{ - milter_log("milter_eoh()"); -} - -/** - * is called zero or more times between milter_eoh and milter_eom. - */ -function milter_body($bodypart) -{ - milter_log("milter_body('$bodypart')"); -} - -/** - * is called once after all calls to milter_body for a given message. - * most of the api functions, that alter the message can only be called - * within this callback. - */ -function milter_eom() -{ - milter_log("milter_eom()"); - /* add PHP header to the message */ - smfi_addheader("X-PHP", phpversion()); -} - -/** - * may be called at any time during message processing - * (i.e. between some message-oriented routine and milter_eom). - */ -function milter_abort() -{ - milter_log("milter_abort()"); -} - -/** - * is always called once at the end of each connection. - */ -function milter_close() -{ - milter_log("milter_close()"); -} -?> diff --git a/sapi/milter/php_getopt.h b/sapi/milter/php_getopt.h deleted file mode 100644 index 40da432b59..0000000000 --- a/sapi/milter/php_getopt.h +++ /dev/null @@ -1,7 +0,0 @@ -/* Borrowed from Apache NT Port */ -#include "php.h" - -extern char *ap_php_optarg; -extern int ap_php_optind; - -int ap_php_getopt(int argc, char* const *argv, const char *optstr); diff --git a/sapi/milter/php_milter.c b/sapi/milter/php_milter.c deleted file mode 100644 index d285944f02..0000000000 --- a/sapi/milter/php_milter.c +++ /dev/null @@ -1,1213 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 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: Harald Radi <phanto@php.net> | - | Parts based on CGI SAPI Module by | - | Rasmus Lerdorf, Stig Bakken and Zeev Suraski | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#include "php.h" -#include "php_globals.h" -#include "php_variables.h" -#include "zend_modules.h" - -#ifndef ZTS -#error SRM sapi module is only useable in thread-safe mode -#endif - -#include "SAPI.h" - -#include <stdio.h> -#include "php.h" -#if HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#if HAVE_UNISTD_H -#include <unistd.h> -#endif -#if HAVE_SIGNAL_H -#include <signal.h> -#endif -#if HAVE_SETLOCALE -#include <locale.h> -#endif -#include "zend.h" -#include "zend_extensions.h" -#include "php_ini.h" -#include "php_globals.h" -#include "php_main.h" -#include "fopen_wrappers.h" -#include "ext/standard/php_standard.h" - -#ifdef __riscos__ -#include <unixlib/local.h> -#endif - -#include "zend_compile.h" -#include "zend_execute.h" -#include "zend_highlight.h" -#include "zend_indent.h" - -#include "libmilter/mfapi.h" - -#include "php_getopt.h" - -#define OPTSTRING "ac:d:Def:hnp:vVz:?" -#define MG(v) TSRMG(milter_globals_id, zend_milter_globals *, v) - -#define IS_NONE "%s(): This function must not be called outside of a milter callback function's scope" -#define NOT_EOM "%s(): This function can only be used inside the milter_eom callback's scope" -#define NOT_INIT "%s(): This function can only be used inside the milter_init callback's scope" - -#define MLFI_NONE 0 -#define MLFI_CONNECT 1 -#define MLFI_HELO 2 -#define MLFI_ENVFROM 3 -#define MLFI_ENVRCPT 4 -#define MLFI_HEADER 5 -#define MLFI_EOH 6 -#define MLFI_BODY 7 -#define MLFI_EOM 8 -#define MLFI_ABORT 9 -#define MLFI_CLOSE 10 -#define MLFI_INIT 11 - -/* {{{ globals - */ -extern char *ap_php_optarg; -extern int ap_php_optind; - -static int flag_debug=0; -static char *filename = NULL; - -/* per thread */ -ZEND_BEGIN_MODULE_GLOBALS(milter) - SMFICTX *ctx; - int state; - int initialized; -ZEND_END_MODULE_GLOBALS(milter) - -ZEND_DECLARE_MODULE_GLOBALS(milter) -/* }}} */ - -/* this method is called only once when the milter starts */ -/* {{{ Init Milter -*/ -static int mlfi_init() -{ - int ret = 0; - zend_file_handle file_handle; - zval function_name, retval; - int status; - TSRMLS_FETCH(); - - /* request startup */ - if (php_request_startup(TSRMLS_C)==FAILURE) { - SG(headers_sent) = 1; - SG(request_info).no_headers = 1; - php_request_shutdown((void *) 0); - - return -1; - } - - /* disable headers */ - SG(headers_sent) = 1; - SG(request_info).no_headers = 1; - - if (filename == NULL) { - php_printf("No input file specified"); - return SMFIS_TEMPFAIL; - } - - if (!(file_handle.handle.fp = VCWD_FOPEN(filename, "rb"))) { - php_printf("Could not open input file: %s\n", filename); - return SMFIS_TEMPFAIL; - } - - file_handle.type = ZEND_HANDLE_FP; - file_handle.filename = filename; - file_handle.free_filename = 0; - file_handle.opened_path = NULL; - - php_execute_script(&file_handle TSRMLS_CC); - - /* call userland */ - INIT_ZVAL(function_name); - - ZVAL_STRING(&function_name, "milter_init", 0); - - /* set the milter context for possible use in API functions */ - MG(state) = MLFI_INIT; - - status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC); - - MG(state) = MLFI_NONE; - MG(initialized) = 1; - - if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) { - ret = Z_LVAL(retval); - } - - php_request_shutdown((void *) 0); - - return ret; -} -/* }}} */ - -/* {{{ Milter callback functions - */ - -/* connection info filter, is called whenever sendmail connects to the milter */ -/* {{{ mlfi_connect() -*/ -static sfsistat mlfi_connect(SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr) -{ - zend_file_handle file_handle; - zval function_name, retval, *param[1]; - int status; - TSRMLS_FETCH(); - - /* request startup */ - if (php_request_startup(TSRMLS_C)==FAILURE) { - SG(headers_sent) = 1; - SG(request_info).no_headers = 1; - php_request_shutdown((void *) 0); - - return SMFIS_TEMPFAIL; - } - - /* disable headers */ - SG(headers_sent) = 1; - SG(request_info).no_headers = 1; - - if (filename == NULL) { - php_printf("No input file specified"); - return SMFIS_TEMPFAIL; - } - - if (!(file_handle.handle.fp = VCWD_FOPEN(filename, "rb"))) { - php_printf("Could not open input file: %s\n", filename); - return SMFIS_TEMPFAIL; - } - - file_handle.type = ZEND_HANDLE_FP; - file_handle.filename = filename; - file_handle.free_filename = 0; - file_handle.opened_path = NULL; - - php_execute_script(&file_handle TSRMLS_CC); - - /* call userland */ - INIT_ZVAL(function_name); - - ALLOC_ZVAL(param[0]); - INIT_PZVAL(param[0]); - - ZVAL_STRING(&function_name, "milter_connect", 0); - ZVAL_STRING(param[0], hostname, 1); - - /* set the milter context for possible use in API functions */ - MG(ctx) = ctx; - MG(state) = MLFI_CONNECT; - - status = call_user_function(CG(function_table), NULL, &function_name, &retval, 1, param TSRMLS_CC); - - MG(state) = MLFI_NONE; - zval_ptr_dtor(param); - if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) { - return Z_LVAL(retval); - } - - return SMFIS_CONTINUE; -} -/* }}} */ - -/* SMTP HELO command filter */ -/* {{{ mlfi_helo() -*/ -static sfsistat mlfi_helo(SMFICTX *ctx, char *helohost) -{ - zval function_name, retval, *param[1]; - int status; - TSRMLS_FETCH(); - - /* call userland */ - INIT_ZVAL(function_name); - - ALLOC_ZVAL(param[0]); - INIT_PZVAL(param[0]); - - ZVAL_STRING(&function_name, "milter_helo", 0); - ZVAL_STRING(param[0], helohost, 1); - - /* set the milter context for possible use in API functions */ - MG(ctx) = ctx; - MG(state) = MLFI_HELO; - - status = call_user_function(CG(function_table), NULL, &function_name, &retval, 1, param TSRMLS_CC); - - MG(state) = MLFI_NONE; - zval_ptr_dtor(param); - - if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) { - return Z_LVAL(retval); - } - - return SMFIS_CONTINUE; -} -/* }}} */ - -/* envelope sender filter */ -/* {{{ mlfi_envform() -*/ -static sfsistat mlfi_envfrom(SMFICTX *ctx, char **argv) -{ - zval function_name, retval, *param[1]; - int status; - TSRMLS_FETCH(); - - /* call userland */ - INIT_ZVAL(function_name); - - ALLOC_ZVAL(param[0]); - INIT_PZVAL(param[0]); - - ZVAL_STRING(&function_name, "milter_envfrom", 0); - array_init(param[0]); - - while (*argv) { - add_next_index_string(param[0], *argv, 1); - argv++; - } - - /* set the milter context for possible use in API functions */ - MG(ctx) = ctx; - MG(state) = MLFI_ENVFROM; - - status = call_user_function(CG(function_table), NULL, &function_name, &retval, 1, param TSRMLS_CC); - - MG(state) = MLFI_NONE; - zval_ptr_dtor(param); - - if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) { - return Z_LVAL(retval); - } - - return SMFIS_CONTINUE; -} -/* }}} */ - -/* envelope recipient filter */ -/* {{{ mlfi_envrcpt() -*/ -static sfsistat mlfi_envrcpt(SMFICTX *ctx, char **argv) -{ - zval function_name, retval, *param[1]; - int status; - TSRMLS_FETCH(); - - /* call userland */ - INIT_ZVAL(function_name); - - ALLOC_ZVAL(param[0]); - INIT_PZVAL(param[0]); - - ZVAL_STRING(&function_name, "milter_envrcpt", 0); - array_init(param[0]); - - while (*argv) { - add_next_index_string(param[0], *argv, 1); - argv++; - } - - /* set the milter context for possible use in API functions */ - MG(ctx) = ctx; - MG(state) = MLFI_ENVRCPT; - - status = call_user_function(CG(function_table), NULL, &function_name, &retval, 1, param TSRMLS_CC); - - MG(state) = MLFI_NONE; - - zval_ptr_dtor(param); - - if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) { - return Z_LVAL(retval); - } - - return SMFIS_CONTINUE; -} -/* }}} */ - -/* header filter */ -/* {{{ mlfi_header() -*/ -static sfsistat mlfi_header(SMFICTX *ctx, char *headerf, char *headerv) -{ - zval function_name, retval, *param[2]; - int status; - TSRMLS_FETCH(); - - /* call userland */ - INIT_ZVAL(function_name); - - ALLOC_ZVAL(param[0]); - ALLOC_ZVAL(param[1]); - INIT_PZVAL(param[0]); - INIT_PZVAL(param[1]); - - ZVAL_STRING(&function_name, "milter_header", 0); - ZVAL_STRING(param[0], headerf, 1); - ZVAL_STRING(param[1], headerv, 1); - - /* set the milter context for possible use in API functions */ - MG(ctx) = ctx; - MG(state) = MLFI_HEADER; - - status = call_user_function(CG(function_table), NULL, &function_name, &retval, 2, param TSRMLS_CC); - - MG(state) = MLFI_NONE; - - zval_ptr_dtor(¶m[0]); - zval_ptr_dtor(¶m[1]); - - if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) { - return Z_LVAL(retval); - } - - return SMFIS_CONTINUE; -} -/* }}} */ - -/* end of header */ -/* {{{ mlfi_eoh() -*/ -static sfsistat mlfi_eoh(SMFICTX *ctx) -{ - zval function_name, retval; - int status; - TSRMLS_FETCH(); - - /* call userland */ - INIT_ZVAL(function_name); - ZVAL_STRING(&function_name, "milter_eoh", 0); - - /* set the milter context for possible use in API functions */ - MG(ctx) = ctx; - MG(state) = MLFI_EOH; - - status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC); - - MG(state) = MLFI_NONE; - - if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) { - return Z_LVAL(retval); - } - - return SMFIS_CONTINUE; -} -/* }}} */ - -/* body block */ -/* {{{ mlfi_body() -*/ -static sfsistat mlfi_body(SMFICTX *ctx, u_char *bodyp, size_t len) -{ - zval function_name, retval, *param[1]; - int status; - TSRMLS_FETCH(); - - /* call userland */ - INIT_ZVAL(function_name); - - ALLOC_ZVAL(param[0]); - INIT_PZVAL(param[0]); - - ZVAL_STRING(&function_name, "milter_body", 0); - ZVAL_STRINGL(param[0], (char*)bodyp, len, 1); /*alex*/ - - /* set the milter context for possible use in API functions */ - MG(ctx) = ctx; - MG(state) = MLFI_BODY; - - status = call_user_function(CG(function_table), NULL, &function_name, &retval, 1, param TSRMLS_CC); - - MG(state) = MLFI_NONE; - - zval_ptr_dtor(param); - - if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) { - return Z_LVAL(retval); - } - - return SMFIS_CONTINUE; -} -/* }}} */ - -/* end of message */ -/* {{{ mlfi_eom() -*/ -static sfsistat mlfi_eom(SMFICTX *ctx) -{ - zval function_name, retval; - int status; - TSRMLS_FETCH(); - - /* call userland */ - INIT_ZVAL(function_name); - ZVAL_STRING(&function_name, "milter_eom", 0); - - /* set the milter context for possible use in API functions */ - MG(ctx) = ctx; - MG(state) = MLFI_EOM; - - status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC); - - MG(state) = MLFI_NONE; - - if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) { - return Z_LVAL(retval); - } - - return SMFIS_CONTINUE; -} -/* }}} */ - -/* message aborted */ -/* {{{ mlfi_abort() -*/ -static sfsistat mlfi_abort(SMFICTX *ctx) -{ - zval function_name, retval; - int status; - TSRMLS_FETCH(); - - /* call userland */ - INIT_ZVAL(function_name); - ZVAL_STRING(&function_name, "milter_abort", 0); - - /* set the milter context for possible use in API functions */ - MG(ctx) = ctx; - MG(state) = MLFI_ABORT; - - status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC); - - MG(state) = MLFI_NONE; - - if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) { - return Z_LVAL(retval); - } - - return SMFIS_CONTINUE; -} -/* }}} */ - -/* connection cleanup */ -/* {{{ mlfi_close() -*/ -static sfsistat mlfi_close(SMFICTX *ctx) -{ - int ret = SMFIS_CONTINUE; - zval function_name, retval; - int status; - TSRMLS_FETCH(); - - if (!SG(sapi_started) && SUCCESS != php_request_startup(TSRMLS_C)) { - return ret; - } - - /* call userland */ - INIT_ZVAL(function_name); - ZVAL_STRING(&function_name, "milter_close", 0); - - /* set the milter context for possible use in API functions */ - MG(ctx) = ctx; - MG(state) = MLFI_CLOSE; - - status = call_user_function(CG(function_table), NULL, &function_name, &retval, 0, NULL TSRMLS_CC); - - MG(state) = MLFI_NONE; - - if (status == SUCCESS && Z_TYPE(retval) == IS_LONG) { - ret = Z_LVAL(retval); - } - - php_request_shutdown((void *) 0); - - return ret; -} -/* }}} */ -/* }}} */ - -/* {{{ Milter entry struct - */ -static struct smfiDesc smfilter = { - "php-milter", /* filter name */ - SMFI_VERSION, /* version code -- leave untouched */ - 0, /* flags */ - mlfi_connect, /* info filter callback */ - mlfi_helo, /* HELO filter callback */ - mlfi_envfrom, /* envelope filter callback */ - mlfi_envrcpt, /* envelope recipient filter callback */ - mlfi_header, /* header filter callback */ - mlfi_eoh, /* end of header callback */ - mlfi_body, /* body filter callback */ - mlfi_eom, /* end of message callback */ - mlfi_abort, /* message aborted callback */ - mlfi_close, /* connection cleanup callback */ -}; -/* }}} */ - -/* {{{ PHP Milter API - */ - -/* {{{ proto void smfi_setflags(long flags) - Sets the flags describing the actions the filter may take. */ -PHP_FUNCTION(smfi_setflags) -{ - long flags; - - /* valid only in the init callback */ - if (MG(state) != MLFI_INIT) { - php_error(E_WARNING, NOT_INIT, get_active_function_name(TSRMLS_C)); - } else if (zend_parse_parameters(1 TSRMLS_CC, "l", &flags) == SUCCESS) { - flags = flags & (SMFIF_ADDHDRS|SMFIF_CHGHDRS|SMFIF_CHGBODY|SMFIF_ADDRCPT|SMFIF_DELRCPT); - smfilter.xxfi_flags = flags; - } -} -/* }}} */ - -/* {{{ proto void smfi_settimeout(long timeout) - Sets the number of seconds libmilter will wait for an MTA connection before timing out a socket. */ -PHP_FUNCTION(smfi_settimeout) -{ - long timeout; - - /* valid only in the init callback */ - if (MG(state) != MLFI_INIT) { - php_error(E_WARNING, NOT_INIT, get_active_function_name(TSRMLS_C)); - } else if (zend_parse_parameters(1 TSRMLS_CC, "l", &timeout) == SUCCESS) { - smfi_settimeout(timeout); - } -} -/* }}} */ - -/* {{{ proto string smfi_getsymval(string macro) - Returns the value of the given macro or NULL if the macro is not defined. */ -PHP_FUNCTION(smfi_getsymval) -{ - char *symname, *ret; - int len; - - /* valid in any callback */ - if (MG(state) == MLFI_NONE) { - php_error(E_WARNING, IS_NONE, get_active_function_name(TSRMLS_C)); - } else if (zend_parse_parameters(1 TSRMLS_CC, "s", &symname, &len) == SUCCESS) { - if ((ret = smfi_getsymval(MG(ctx), symname)) != NULL) { - RETURN_STRING(ret, 1); - } - } - - RETURN_NULL(); -} -/* }}} */ - -/* {{{ proto bool smfi_setreply(string rcode, string xcode, string message) - Directly set the SMTP error reply code for this connection. - This code will be used on subsequent error replies resulting from actions taken by this filter. */ -PHP_FUNCTION(smfi_setreply) -{ - char *rcode, *xcode, *message; - int len; - - /* valid in any callback */ - if (MG(state) == MLFI_NONE) { - php_error(E_WARNING, IS_NONE, get_active_function_name(TSRMLS_C)); - } else if (zend_parse_parameters(3 TSRMLS_CC, "sss", &rcode, &len, &xcode, &len, &message, &len) == SUCCESS) { - if (smfi_setreply(MG(ctx), rcode, xcode, message) == MI_SUCCESS) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto bool smfi_addheader(string headerf, string headerv) - Adds a header to the current message. */ -PHP_FUNCTION(smfi_addheader) -{ - char *f, *v; - int len; - - /* valid only in milter_eom */ - if (MG(state) != MLFI_EOM) { - php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C)); - } else if (zend_parse_parameters(2 TSRMLS_CC, "ss", &f, &len, &v, &len) == SUCCESS) { - if (smfi_addheader(MG(ctx), f, v) == MI_SUCCESS) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto bool smfi_chgheader(string headerf, string headerv) - Changes a header's value for the current message. */ -PHP_FUNCTION(smfi_chgheader) -{ - char *f, *v; - long idx; - int len; - - /* valid only in milter_eom */ - if (MG(state) != MLFI_EOM) { - php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C)); - } else if (zend_parse_parameters(3 TSRMLS_CC, "sls", &f, &len, &idx, &v, &len) == SUCCESS) { - if (smfi_chgheader(MG(ctx), f, idx, v) == MI_SUCCESS) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto bool smfi_addrcpt(string rcpt) - Add a recipient to the message envelope. */ -PHP_FUNCTION(smfi_addrcpt) -{ - char *rcpt; - int len; - - /* valid only in milter_eom */ - if (MG(state) != MLFI_EOM) { - php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C)); - } else if (zend_parse_parameters(1 TSRMLS_CC, "s", &rcpt, &len) == SUCCESS) { - if (smfi_addrcpt(MG(ctx), rcpt) == MI_SUCCESS) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto bool smfi_delrcpt(string rcpt) - Removes the named recipient from the current message's envelope. */ -PHP_FUNCTION(smfi_delrcpt) -{ - char *rcpt; - int len; - - /* valid only in milter_eom */ - if (MG(state) != MLFI_EOM) { - php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C)); - } else if (zend_parse_parameters(1 TSRMLS_CC, "s", &rcpt, &len) == SUCCESS) { - if (smfi_delrcpt(MG(ctx), rcpt) == MI_SUCCESS) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} -/* }}} */ - -/* {{{ proto bool smfi_replacebody(string body) - Replaces the body of the current message. If called more than once, - subsequent calls result in data being appended to the new body. */ -PHP_FUNCTION(smfi_replacebody) -{ - char *body; - int len; - - /* valid only in milter_eom */ - if (MG(state) != MLFI_EOM) { - php_error(E_WARNING, NOT_EOM, get_active_function_name(TSRMLS_C)); - } else if (zend_parse_parameters(1 TSRMLS_CC, "s", &body, &len) == SUCCESS) { - if (smfi_replacebody(MG(ctx), (u_char*)body, len) == MI_SUCCESS) { - RETURN_TRUE; - } - } - - RETURN_FALSE; -} -/* }}} */ - -/* {{{ PHP_MINIT_FUNCTION - */ -PHP_MINIT_FUNCTION(milter) -{ - REGISTER_LONG_CONSTANT("SMFIS_CONTINUE", SMFIS_CONTINUE, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SMFIS_REJECT", SMFIS_REJECT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SMFIS_DISCARD", SMFIS_DISCARD, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SMFIS_ACCEPT", SMFIS_ACCEPT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SMFIS_TEMPFAIL", SMFIS_TEMPFAIL, CONST_CS | CONST_PERSISTENT); - - REGISTER_LONG_CONSTANT("SMFIF_ADDHDRS", SMFIF_ADDHDRS, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SMFIF_CHGHDRS", SMFIF_CHGHDRS, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SMFIF_CHGBODY", SMFIF_CHGBODY, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SMFIF_ADDRCPT", SMFIF_ADDRCPT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("SMFIF_DELRCPT", SMFIF_DELRCPT, CONST_CS | CONST_PERSISTENT); - - ZEND_INIT_MODULE_GLOBALS(milter, NULL, NULL); - - MG(state) = MLFI_NONE; - MG(initialized) = 0; - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_MINFO_FUNCTION - */ -PHP_MINFO_FUNCTION(milter) -{ - php_info_print_table_start(); - php_info_print_table_header(2, "Milter support", "enabled"); - php_info_print_table_end(); -} -/* }}} */ -/* }}} */ - -/* {{{ arginfo */ -ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_setflags, 0, 0, 1) - ZEND_ARG_INFO(0, flags) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_settimeout, 0, 0, 1) - ZEND_ARG_INFO(0, timeout) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_getsymval, 0, 0, 1) - ZEND_ARG_INFO(0, macro) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_setreply, 0, 0, 3) - ZEND_ARG_INFO(0, rcode) - ZEND_ARG_INFO(0, xcode) - ZEND_ARG_INFO(0, message) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_addheader, 0, 0, 2) - ZEND_ARG_INFO(0, headerf) - ZEND_ARG_INFO(0, headerv) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_chgheader, 0, 0, 2) - ZEND_ARG_INFO(0, headerf) - ZEND_ARG_INFO(0, headerv) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_addrcpt, 0, 0, 1) - ZEND_ARG_INFO(0, rcpt) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_delrcpt, 0, 0, 1) - ZEND_ARG_INFO(0, rcpt) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_smfi_replacebody, 0, 0, 1) - ZEND_ARG_INFO(0, body) -ZEND_END_ARG_INFO() -/* }}} */ - -/* {{{ milter_functions[] -*/ -const static zend_function_entry milter_functions[] = { - PHP_FE(smfi_setflags, arginfo_smfi_setflags) - PHP_FE(smfi_settimeout, arginfo_smfi_settimeout) - PHP_FE(smfi_getsymval, arginfo_smfi_getsymval) - PHP_FE(smfi_setreply, arginfo_smfi_setreply) - PHP_FE(smfi_addheader, arginfo_smfi_addheader) - PHP_FE(smfi_chgheader, arginfo_smfi_chgheader) - PHP_FE(smfi_addrcpt, arginfo_smfi_addrcpt) - PHP_FE(smfi_delrcpt, arginfo_smfi_delrcpt) - PHP_FE(smfi_replacebody, arginfo_smfi_replacebody) - PHP_FE_END -}; -/* }}} */ - -/* {{{ Zend module entry -*/ -static zend_module_entry php_milter_module = { - STANDARD_MODULE_HEADER, - "Milter", - milter_functions, - PHP_MINIT(milter), - NULL, - NULL, - NULL, - PHP_MINFO(milter), - "0.1.0", - STANDARD_MODULE_PROPERTIES -}; -/* }}} */ - -/* {{{ Milter SAPI -*/ -static int sapi_milter_ub_write(const char *str, uint str_length TSRMLS_DC) -{ - return str_length; -} - -static void sapi_milter_flush(void *server_context) -{ -} - -static void sapi_milter_register_variables(zval *track_vars_array TSRMLS_DC) -{ - php_register_variable ("SERVER_SOFTWARE", "Sendmail Milter", track_vars_array TSRMLS_CC); -} - -static int sapi_milter_post_read(char *buf, uint count_bytes TSRMLS_DC) -{ - return 0; -} - -static char* sapi_milter_read_cookies(TSRMLS_D) -{ - return NULL; -} - -static int sapi_milter_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - return SAPI_HEADER_SENT_SUCCESSFULLY; -} - -static int php_milter_startup(sapi_module_struct *sapi_module) -{ - if (php_module_startup(sapi_module, &php_milter_module, 1) == FAILURE) { - return FAILURE; - } - return SUCCESS; -} -/* }}} */ - -/* {{{ sapi_module_struct milter_sapi_module -*/ -static sapi_module_struct milter_sapi_module = { - "milter", /* name */ - "Sendmail Milter SAPI", /* pretty name */ - - php_milter_startup, /* startup */ - php_module_shutdown_wrapper, /* shutdown */ - - NULL, /* activate */ - NULL, /* deactivate */ - - sapi_milter_ub_write, /* unbuffered write */ - sapi_milter_flush, /* flush */ - NULL, /* get uid */ - NULL, /* getenv */ - - php_error, /* error handler */ - - NULL, /* header handler */ - sapi_milter_send_headers, /* send headers handler */ - NULL, /* send header handler */ - - sapi_milter_post_read, /* read POST data */ - sapi_milter_read_cookies, /* read Cookies */ - - sapi_milter_register_variables, /* register server variables */ - NULL, /* Log message */ - NULL, /* Get request time */ - NULL, /* Child terminate */ - - NULL, /* Block interruptions */ - NULL, /* Unblock interruptions */ - - STANDARD_SAPI_MODULE_PROPERTIES -}; -/* }}} */ - -/**** -* ripped from cli, has to be cleaned up ! -*/ - -/* {{{ php_milter_usage -*/ -static void php_milter_usage(char *argv0) -{ - char *prog; - - prog = strrchr(argv0, '/'); - if (prog) { - prog++; - } else { - prog = "php-milter"; - } - - printf( "Usage: %s [options] [-f] <file> [args...]\n" - " %s [options] [-- args...]\n" - " -a Run interactively\n" - " -c <path>|<file> Look for php.ini file in this directory\n" - " -n No php.ini file will be used\n" - " -d foo[=bar] Define INI entry foo with value 'bar'\n" - " -D run as daemon\n" - " -e Generate extended information for debugger/profiler\n" - " -f <file> Parse <file>.\n" - " -h This help\n" - " -p <socket> path to create socket\n" - " -v Version number\n" - " -V <n> set debug level to n (1 or 2).\n" - " -z <file> Load Zend extension <file>.\n" - " args... Arguments passed to script. Use -- args when first argument \n" - " starts with - or script is read from stdin\n" - , prog, prog); -} -/* }}} */ - -static void define_command_line_ini_entry(char *arg) /* {{{ */ -{ - char *name, *value; - - name = arg; - value = strchr(arg, '='); - if (value) { - *value = 0; - value++; - } else { - value = "1"; - } - zend_alter_ini_entry(name, strlen(name)+1, value, strlen(value), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); -} -/* }}} */ - -/* {{{ main -*/ -int main(int argc, char *argv[]) -{ - char *sock = NULL; - int dofork = 0; - - int exit_status = SUCCESS; - int c; -/* temporary locals */ - int orig_optind=ap_php_optind; - char *orig_optarg=ap_php_optarg; - int interactive=0; - char *param_error=NULL; -/* end of temporary locals */ - - void ***tsrm_ls; - -#ifdef HAVE_SIGNAL_H -#if defined(SIGPIPE) && defined(SIG_IGN) - signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE in standalone mode so - that sockets created via fsockopen() - don't kill PHP if the remote site - closes it. in apache|apxs mode apache - does that for us! thies@thieso.net - 20000419 */ -#endif -#endif - - - tsrm_startup(1, 1, 0, NULL); - tsrm_ls = ts_resource(0); - sapi_startup(&milter_sapi_module); - - while ((c=ap_php_getopt(argc, argv, OPTSTRING))!=-1) { - switch (c) { - case 'c': - milter_sapi_module.php_ini_path_override = strdup(ap_php_optarg); - break; - case 'n': - milter_sapi_module.php_ini_ignore = 1; - break; - } - } - ap_php_optind = orig_optind; - ap_php_optarg = orig_optarg; - - milter_sapi_module.executable_location = argv[0]; - - - sapi_module.startup(&milter_sapi_module); - - zend_first_try { - while ((c=ap_php_getopt(argc, argv, OPTSTRING))!=-1) { - switch (c) { - case '?': - php_output_tearup(); - SG(headers_sent) = 1; - php_milter_usage(argv[0]); - php_output_teardown(); - exit(1); - break; - } - } - ap_php_optind = orig_optind; - ap_php_optarg = orig_optarg; - - /* Set some CLI defaults */ - SG(options) |= SAPI_OPTION_NO_CHDIR; - zend_alter_ini_entry("html_errors", 12, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); - zend_alter_ini_entry("max_execution_time", 19, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); - - zend_uv.html_errors = 0; /* tell the engine we're in non-html mode */ - - while ((c = ap_php_getopt(argc, argv, OPTSTRING)) != -1) { - switch (c) { - - case 'a': /* interactive mode */ - printf("Interactive mode enabled\n\n"); - interactive=1; - break; - - case 'C': /* don't chdir to the script directory */ - /* This is default so NOP */ - break; - case 'd': /* define ini entries on command line */ - define_command_line_ini_entry(ap_php_optarg); - break; - - case 'D': /* daemon */ - dofork = 1; - break; - - case 'e': /* enable extended info output */ - CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO; - break; - - case 'f': /* parse file */ - filename = ap_php_optarg; - break; - - case 'h': /* help & quit */ - case '?': - php_output_tearup(); - SG(headers_sent) = 1; - php_milter_usage(argv[0]); - php_output_teardown(); - exit(1); - break; - - case 'p': /* socket */ - sock = strdup(ap_php_optarg); - break; - - case 'v': /* show php version & quit */ - if (php_request_startup(TSRMLS_C)==FAILURE) { - zend_ini_deactivate(TSRMLS_C); - php_module_shutdown(TSRMLS_C); - sapi_shutdown(); - tsrm_shutdown(); - - exit(1); - } - SG(headers_sent) = 1; - SG(request_info).no_headers = 1; - php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2016 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); - php_output_teardown(); - exit(1); - break; - - case 'V': /* verbose */ - flag_debug = atoi(ap_php_optarg); - break; - - case 'z': /* load extension file */ - zend_load_extension(ap_php_optarg); - break; - - default: - break; - } - } - - if (param_error) { - SG(headers_sent) = 1; - SG(request_info).no_headers = 1; - PUTS(param_error); - exit(1); - } - - CG(interactive) = interactive; - - /* only set script_file if not set already and not in direct mode and not at end of parameter list */ - if (argc > ap_php_optind && !filename) { - filename=argv[ap_php_optind]; - ap_php_optind++; - } - - /* check if file exists, exit else */ - - if (dofork) { - switch(fork()) { - case -1: /* Uh-oh, we have a problem forking. */ - fprintf(stderr, "Uh-oh, couldn't fork!\n"); - exit(errno); - break; - case 0: /* Child */ - break; - default: /* Parent */ - exit(0); - } - } - - if (sock) { - struct stat junk; - if (stat(sock,&junk) == 0) unlink(sock); - } - - openlog("php-milter", LOG_PID, LOG_MAIL); - - if ((exit_status = mlfi_init())) { - syslog(1, "mlfi_init failed."); - closelog(); - goto err; - } - - smfi_setconn(sock); - if (smfi_register(smfilter) == MI_FAILURE) { - syslog(1, "smfi_register failed."); - fprintf(stderr, "smfi_register failed\n"); - closelog(); - goto err; - } else { - exit_status = smfi_main(); - } - - closelog(); - - if (milter_sapi_module.php_ini_path_override) { - free(milter_sapi_module.php_ini_path_override); - } - - } zend_catch { - exit_status = EG(exit_status); - } zend_end_try(); - -err: - php_module_shutdown(TSRMLS_C); - sapi_shutdown(); - tsrm_shutdown(); - - exit(exit_status); -} -/* }}} */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/sapi/milter/php_milter.h b/sapi/milter/php_milter.h deleted file mode 100644 index 72d7ac51ee..0000000000 --- a/sapi/milter/php_milter.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef PHP_MILTER_H -#define PHP_MILTER_H - -#include "libmilter/mfapi.h" - -#define MLFI_NONE 0 -#define MLFI_CONNECT 1 -#define MLFI_HELO 2 -#define MLFI_ENVFROM 3 -#define MLFI_ENVRCPT 4 -#define MLFI_HEADER 5 -#define MLFI_EOH 6 -#define MLFI_BODY 7 -#define MLFI_EOM 8 -#define MLFI_ABORT 9 -#define MLFI_CLOSE 10 -#define MLFI_INIT 11 - -#define MG(v) TSRMG(milter_globals_id, zend_milter_globals *, v) - -typedef struct { - pthread_t thread; - MUTEX_T receiver; - MUTEX_T sender; - SMFICTX *ctx; - sfsistat retval; - int message; - void **args; -} worker_thread; - -#endif diff --git a/sapi/nsapi/CREDITS b/sapi/nsapi/CREDITS deleted file mode 100644 index 2a05919862..0000000000 --- a/sapi/nsapi/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -NSAPI -Jayakumar Muthukumarasamy, Uwe Schindler diff --git a/sapi/nsapi/config.m4 b/sapi/nsapi/config.m4 deleted file mode 100644 index 8923f53227..0000000000 --- a/sapi/nsapi/config.m4 +++ /dev/null @@ -1,39 +0,0 @@ -dnl -dnl $Id$ -dnl - -PHP_ARG_WITH(nsapi, for NSAPI support, -[ --with-nsapi=DIR Build PHP as NSAPI module for Netscape/iPlanet/Sun Webserver], no, no) - -if test "$PHP_NSAPI" != "no"; then - if test ! -d $PHP_NSAPI/bin ; then - AC_MSG_ERROR(Please specify the path to the root of your Netscape/iPlanet/Sun Webserver using --with-nsapi=DIR) - fi - AC_MSG_CHECKING([for NSAPI include files]) - if test -d $PHP_NSAPI/include ; then - NSAPI_INC_DIR="$PHP_NSAPI/include" - AC_MSG_RESULT([Netscape 3.x / Sun 7.x style]) - AC_CHECK_HEADERS([$NSAPI_INC_DIR/nsapi.h]) - NSAPI_INCLUDE="-I$NSAPI_INC_DIR" - fi - if test -d $PHP_NSAPI/plugins/include ; then - NSAPI_INC_DIR="$PHP_NSAPI/plugins/include" - AC_MSG_RESULT([iPlanet 4.x / Sun 6.x style]) - AC_CHECK_HEADERS([$NSAPI_INC_DIR/nsapi.h]) - NSAPI_INCLUDE="$NSAPI_INCLUDE -I$NSAPI_INC_DIR" - fi - if test -z "$NSAPI_INCLUDE"; then - AC_MSG_ERROR([Please check you have nsapi.h in either $PHP_NSAPI/include or $PHP_NSAPI/plugins/include]) - fi - - PHP_EVAL_INCLINE($NSAPI_INCLUDE) - PHP_BUILD_THREAD_SAFE - AC_DEFINE(HAVE_NSAPI, 1, [Whether you have a Netscape/iPlanet/Sun Webserver]) - PHP_SELECT_SAPI(nsapi, shared, nsapi.c) - INSTALL_IT="\$(INSTALL) -m 0755 $SAPI_SHARED \$(INSTALL_ROOT)$PHP_NSAPI/bin/" -fi - - -dnl ## Local Variables: -dnl ## tab-width: 4 -dnl ## End: diff --git a/sapi/nsapi/config.w32 b/sapi/nsapi/config.w32 deleted file mode 100644 index 17b86d20e4..0000000000 --- a/sapi/nsapi/config.w32 +++ /dev/null @@ -1,20 +0,0 @@ -// vim:ft=javascript -// $Id$ - -ARG_ENABLE('nsapi', 'Build NSAPI for Netscape/iPlanet/SunONE webservers', 'no'); - -ARG_WITH('nsapi-includes', 'Where to find NSAPI headers', null); -ARG_WITH('nsapi-libs', 'Where to find NSAPI libraries', null); - -if (PHP_NSAPI != "no") { - if (PHP_ZTS == "no") { - WARNING("NSAPI module requires an --enable-zts build of PHP"); - PHP_NSAPI = "no" - } else if (CHECK_HEADER_ADD_INCLUDE("nsapi.h", "CFLAGS_NSAPI", - PHP_NSAPI + ';' + PHP_NSAPI_INCLUDES) && - CHECK_LIB("ns-httpd*.lib", "nsapi", PHP_NSAPI + ";" + PHP_NSAPI_LIBS)) { - SAPI('nsapi', 'nsapi.c', 'php' + PHP_VERSION + 'nsapi.dll', '/D XP_WIN32 '); - } else { - WARNING("Could not find NSAPI headers/libraries"); - } -} diff --git a/sapi/nsapi/nsapi-readme.txt b/sapi/nsapi/nsapi-readme.txt deleted file mode 100644 index 10ad9f7eed..0000000000 --- a/sapi/nsapi/nsapi-readme.txt +++ /dev/null @@ -1,154 +0,0 @@ -Configuration of your Netscape/iPlanet/Sun Webserver for PHP5 ------------------------------------------------------------------ - -These instructions are targeted at Netscape Enterprise Web Server and -SUN/Netscape Alliance iPlanet Web Server and the new Sun Java System Webserver. -On other web servers your milage may vary. - -Firstly you may need to add some paths to the LD_LIBRARY_PATH -environment for Netscape to find all the shared libs. This is best done -in the start script for your Netscape server. Windows users can -probably skip this step. The start script is located in: - - <path-to-netscape-server>/https-servername/start - - -Netscape/iPlanet/Sun config files are located in: - - <path-to-server>/https-servername/config - - -Add the following line to mime.types (you can do that by the administration server): - - type=magnus-internal/x-httpd-php exts=php - - -Place the following two lines after mime.types init in -<path-to-server>/https-servername/config/obj.conf (for servers < 6) or -for iPlanet/Sun Webserver 6.0 and above however at the end of the -<path-to-server>/https-servername/config/magnus.conf file: - - Init fn="load-modules" funcs="php5_init,php5_execute,php5_auth_trans" shlib="/path/to/phplibrary" - Init fn=php5_init errorString="Failed to initialize PHP!" [php_ini="/path/to/php.ini"] - -The "shlib" will vary depending on your OS: - - Unix: "<path-to-server>/bin/libphp5.so". - Windows: "c:/path/to/php5/php5nsapi.dll" - - -In obj.conf (for virtual server classes [Sun 6.0+] in their vserver.obj.conf): - - <Object name="default"> - . - . - . - # NOTE this next line should happen after all 'ObjectType' and before - # all 'AddLog' lines - # You can modify some entries in php.ini request specific by adding it to the Service - # directive, e.g. doc_root="/path" - # For boolean ini-keys please use 0/1 as value, NOT "On","Off",... (this will not work - # correctly), e.g. zlib.output_compression=1 instead of zlib.output_compression="On" - - Service fn="php5_execute" type="magnus-internal/x-httpd-php" [inikey=value ...] - . - . - . - </Object> - -This is only needed if you want to configure a directory that only consists of -PHP scripts (same like a cgi-bin directory): - - <Object name="x-httpd-php"> - ObjectType fn="force-type" type="magnus-internal/x-httpd-php" - Service fn="php5_execute" [inikey=value ...] - </Object> - -After that you can configure a directory in the Administration server and assign it -the style "x-httpd-php". All files in it will get executed as PHP. This is nice to -hide PHP usage by renaming files to .html - -Note: The stacksize that PHP uses depends on the configuration of the webserver. If you get -crashes with very large PHP scripts, it is recommended to raise it with the Admin Server -(in the section "MAGNUS EDITOR"). - - -Authentication configuration ----------------------------- - -PHP authentication cannot be used with any other authentication. ALL -AUTHENTICATION IS PASSED TO YOUR PHP SCRIPT. To configure PHP -Authentication for the entire server, add the following line: - - <Object name="default"> - AuthTrans fn=php5_auth_trans - . - . - . - . - </Object> - - -To use PHP Authentication on a single directory, add the following: - - <Object ppath="d:\path\to\authenticated\dir\*"> - AuthTrans fn=php5_auth_trans - </Object> - - -Special use for error pages or self-made directory listings ------------------------------------------------------------ - -You can use PHP to generate the error pages for "404 Not Found" -or similar. Add the following line to the object in obj.conf for -every error page you want to overwrite: - - Error fn="php5_execute" code=XXX script="/path/to/script.php" [inikey=value inikey=value...] - -where XXX ist the HTTP error code. Please delete any other Error -directives which could interfere with yours. -If you want to place a page for all errors that could exist, leave -the "code" parameter out. Your script can get the HTTP status code -with $_SERVER['ERROR_TYPE']. - -Another posibility is to generate self-made directory listings. -Just generate a PHP script which displays a directory listing and -replace the corresponding default Service line for -type="magnus-internal/directory" in obj.conf with the following: - - Service fn="php5_execute" type="magnus-internal/directory" script="/path/to/script.php" [inikey=value inikey=value...] - -For both error and directory listing pages the original URI and -translated URI are in the variables $_SERVER['PATH_INFO'] and -$_SERVER['PATH_TRANSLATED']. - - -Note about nsapi_virtual() and subrequests ------------------------------------------- - -The NSAPI module now supports the nsapi_virtual() function (alias: virtual()) -to make subrequests on the webserver and insert the result in the webpage. -The problem is, that this function uses some undocumented features from -the NSAPI library. - -Under Unix this is not a problem, because the module automatically looks -for the needed functions and uses them if available. If not, nsapi_virtual() -is disabled. - -Under Windows limitations in the DLL handling need the use of a automatic -detection of the most recent ns-httpdXX.dll file. This is tested for servers -till version 6.1. If a newer version of the Sun server is used, the detection -fails and nsapi_virtual() is disabled. - -If this is the case, try the following: -Add the following parameter to php5_init in magnus.conf: - - Init fn=php5_init ... server_lib="ns-httpdXX.dll" - -where XX is the correct DLL version number. To get it, look in the server-root -for the correct DLL name. The DLL with the biggest filesize is the right one. - -But be warned: SUPPORT FOR nsapi_virtual() IS EXPERIMENTAL !!! - - -$Id$ diff --git a/sapi/nsapi/nsapi.c b/sapi/nsapi/nsapi.c deleted file mode 100644 index 71d7860a23..0000000000 --- a/sapi/nsapi/nsapi.c +++ /dev/null @@ -1,1104 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 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: Jayakumar Muthukumarasamy <jk@kasenna.com> | - | Uwe Schindler <uwe@thetaphi.de> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -/* - * PHP includes - */ -#define NSAPI 1 - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#include "php_variables.h" -#include "ext/standard/info.h" -#include "php_ini.h" -#include "php_globals.h" -#include "SAPI.h" -#include "php_main.h" -#include "php_version.h" -#include "TSRM.h" -#include "ext/standard/php_standard.h" -#include <sys/types.h> -#include <sys/stat.h> - -#ifndef RTLD_DEFAULT -#define RTLD_DEFAULT NULL -#endif - -/* - * If neither XP_UNIX not XP_WIN32 is defined use PHP_WIN32 - */ -#if !defined(XP_UNIX) && !defined(XP_WIN32) -#ifdef PHP_WIN32 -#define XP_WIN32 -#else -#define XP_UNIX -#endif -#endif - -/* - * The manual define of HPUX is to fix bug #46020, nsapi.h needs this to detect HPUX - */ -#ifdef __hpux -#define HPUX -#endif - -/* - * NSAPI includes - */ -#include "nsapi.h" - -/* fix for gcc4 visibility issue */ -#ifndef PHP_WIN32 -# undef NSAPI_PUBLIC -# define NSAPI_PUBLIC PHPAPI -#endif - -#define NSLS_D struct nsapi_request_context *request_context -#define NSLS_DC , NSLS_D -#define NSLS_C request_context -#define NSLS_CC , NSLS_C -#define NSG(v) (request_context->v) - -/* - * ZTS needs to be defined for NSAPI to work - */ -#if !defined(ZTS) -#error "NSAPI module needs ZTS to be defined" -#endif - -/* - * Structure to encapsulate the NSAPI request in SAPI - */ -typedef struct nsapi_request_context { - pblock *pb; - Session *sn; - Request *rq; - int read_post_bytes; - char *path_info; - int fixed_script; /* 0 if script is from URI, 1 if script is from "script" parameter */ - short http_error; /* 0 in normal mode; for errors the HTTP error code */ -} nsapi_request_context; - -/* - * Mappings between NSAPI names and environment variables. This - * mapping was obtained from the sample programs at the iplanet - * website. - */ -typedef struct nsapi_equiv { - const char *env_var; - const char *nsapi_eq; -} nsapi_equiv; - -static nsapi_equiv nsapi_reqpb[] = { - { "QUERY_STRING", "query" }, - { "REQUEST_LINE", "clf-request" }, - { "REQUEST_METHOD", "method" }, - { "PHP_SELF", "uri" }, - { "SERVER_PROTOCOL", "protocol" } -}; -static size_t nsapi_reqpb_size = sizeof(nsapi_reqpb)/sizeof(nsapi_reqpb[0]); - -static nsapi_equiv nsapi_vars[] = { - { "AUTH_TYPE", "auth-type" }, - { "CLIENT_CERT", "auth-cert" }, - { "REMOTE_USER", "auth-user" } -}; -static size_t nsapi_vars_size = sizeof(nsapi_vars)/sizeof(nsapi_vars[0]); - -static nsapi_equiv nsapi_client[] = { - { "HTTPS_KEYSIZE", "keysize" }, - { "HTTPS_SECRETSIZE", "secret-keysize" }, - { "REMOTE_ADDR", "ip" }, - { "REMOTE_HOST", "ip" } -}; -static size_t nsapi_client_size = sizeof(nsapi_client)/sizeof(nsapi_client[0]); - -/* this parameters to "Service"/"Error" are NSAPI ones which should not be php.ini keys and are excluded */ -static char *nsapi_exclude_from_ini_entries[] = { "fn", "type", "method", "directive", "code", "reason", "script", "bucket", NULL }; - -static void nsapi_free(void *addr) -{ - if (addr != NULL) { - FREE(addr); - } -} - - -/*******************/ -/* PHP module part */ -/*******************/ - -PHP_MINIT_FUNCTION(nsapi); -PHP_MSHUTDOWN_FUNCTION(nsapi); -PHP_RINIT_FUNCTION(nsapi); -PHP_RSHUTDOWN_FUNCTION(nsapi); -PHP_MINFO_FUNCTION(nsapi); - -PHP_FUNCTION(nsapi_virtual); -PHP_FUNCTION(nsapi_request_headers); -PHP_FUNCTION(nsapi_response_headers); - -ZEND_BEGIN_MODULE_GLOBALS(nsapi) - long read_timeout; -ZEND_END_MODULE_GLOBALS(nsapi) - -ZEND_DECLARE_MODULE_GLOBALS(nsapi) - -#define NSAPI_G(v) TSRMG(nsapi_globals_id, zend_nsapi_globals *, v) - - -/* {{{ arginfo */ -ZEND_BEGIN_ARG_INFO_EX(arginfo_nsapi_virtual, 0, 0, 1) - ZEND_ARG_INFO(0, uri) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_nsapi_request_headers, 0) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO(arginfo_nsapi_response_headers, 0) -ZEND_END_ARG_INFO() -/* }}} */ - -/* {{{ nsapi_functions[] - * - * Every user visible function must have an entry in nsapi_functions[]. - */ -const zend_function_entry nsapi_functions[] = { - PHP_FE(nsapi_virtual, arginfo_nsapi_virtual) /* Make subrequest */ - PHP_FALIAS(virtual, nsapi_virtual, arginfo_nsapi_virtual) /* compatibility */ - PHP_FE(nsapi_request_headers, arginfo_nsapi_request_headers) /* get request headers */ - PHP_FALIAS(getallheaders, nsapi_request_headers, arginfo_nsapi_request_headers) /* compatibility */ - PHP_FALIAS(apache_request_headers, nsapi_request_headers, arginfo_nsapi_request_headers) /* compatibility */ - PHP_FE(nsapi_response_headers, arginfo_nsapi_response_headers) /* get response headers */ - PHP_FALIAS(apache_response_headers, nsapi_response_headers, arginfo_nsapi_response_headers) /* compatibility */ - {NULL, NULL, NULL} -}; -/* }}} */ - -/* {{{ nsapi_module_entry - */ -zend_module_entry nsapi_module_entry = { - STANDARD_MODULE_HEADER, - "nsapi", - nsapi_functions, - PHP_MINIT(nsapi), - PHP_MSHUTDOWN(nsapi), - NULL, - NULL, - PHP_MINFO(nsapi), - NO_VERSION_YET, - STANDARD_MODULE_PROPERTIES -}; -/* }}} */ - -/* {{{ PHP_INI - */ -PHP_INI_BEGIN() - STD_PHP_INI_ENTRY("nsapi.read_timeout", "60", PHP_INI_ALL, OnUpdateLong, read_timeout, zend_nsapi_globals, nsapi_globals) -PHP_INI_END() -/* }}} */ - -/* newer servers hide this functions from the programmer so redefine the functions dynamically - thanks to Chris Elving from Sun for the function declarations */ -typedef int (*nsapi_servact_prototype)(Session *sn, Request *rq); -nsapi_servact_prototype nsapi_servact_uri2path = NULL; -nsapi_servact_prototype nsapi_servact_pathchecks = NULL; -nsapi_servact_prototype nsapi_servact_fileinfo = NULL; -nsapi_servact_prototype nsapi_servact_service = NULL; - -#ifdef PHP_WIN32 -/* The following dll-names for nsapi are in use at this time. The undocumented - * servact_* functions are always in the newest one, older ones are supported by - * the server only by wrapping the function table nothing else. So choose - * the newest one found in process space for dynamic linking */ -static char *nsapi_dlls[] = { "ns-httpd40.dll", "ns-httpd36.dll", "ns-httpd35.dll", "ns-httpd30.dll", NULL }; -/* if user specifies an other dll name by server_lib parameter - * it is placed in the following variable and only this DLL is - * checked for the servact_* functions */ -char *nsapi_dll = NULL; -#endif - -/* {{{ php_nsapi_init_dynamic_symbols - */ -static void php_nsapi_init_dynamic_symbols(void) -{ - /* find address of internal NSAPI functions */ -#ifdef PHP_WIN32 - register int i; - DL_HANDLE module = NULL; - if (nsapi_dll) { - /* try user specified server_lib */ - module = GetModuleHandle(nsapi_dll); - if (!module) { - log_error(LOG_WARN, "php5_init", NULL, NULL, "Cannot find DLL specified by server_lib parameter: %s", nsapi_dll); - } - } else { - /* find a LOADED dll module from nsapi_dlls */ - for (i=0; nsapi_dlls[i]; i++) { - if (module = GetModuleHandle(nsapi_dlls[i])) { - break; - } - } - } - if (!module) return; -#else - DL_HANDLE module = RTLD_DEFAULT; -#endif - nsapi_servact_uri2path = (nsapi_servact_prototype)DL_FETCH_SYMBOL(module, "INTservact_uri2path"); - nsapi_servact_pathchecks = (nsapi_servact_prototype)DL_FETCH_SYMBOL(module, "INTservact_pathchecks"); - nsapi_servact_fileinfo = (nsapi_servact_prototype)DL_FETCH_SYMBOL(module, "INTservact_fileinfo"); - nsapi_servact_service = (nsapi_servact_prototype)DL_FETCH_SYMBOL(module, "INTservact_service"); - if (!(nsapi_servact_uri2path && nsapi_servact_pathchecks && nsapi_servact_fileinfo && nsapi_servact_service)) { - /* not found - could be cause they are undocumented */ - nsapi_servact_uri2path = NULL; - nsapi_servact_pathchecks = NULL; - nsapi_servact_fileinfo = NULL; - nsapi_servact_service = NULL; - } -} -/* }}} */ - -/* {{{ php_nsapi_init_globals - */ -static void php_nsapi_init_globals(zend_nsapi_globals *nsapi_globals) -{ - nsapi_globals->read_timeout = 60; -} -/* }}} */ - -/* {{{ PHP_MINIT_FUNCTION - */ -PHP_MINIT_FUNCTION(nsapi) -{ - php_nsapi_init_dynamic_symbols(); - ZEND_INIT_MODULE_GLOBALS(nsapi, php_nsapi_init_globals, NULL); - REGISTER_INI_ENTRIES(); - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_MSHUTDOWN_FUNCTION - */ -PHP_MSHUTDOWN_FUNCTION(nsapi) -{ - UNREGISTER_INI_ENTRIES(); - return SUCCESS; -} -/* }}} */ - -/* {{{ PHP_MINFO_FUNCTION - */ -PHP_MINFO_FUNCTION(nsapi) -{ - php_info_print_table_start(); - php_info_print_table_row(2, "NSAPI Module Revision", "$Id$"); - php_info_print_table_row(2, "Server Software", system_version()); - php_info_print_table_row(2, "Sub-requests with nsapi_virtual()", - (nsapi_servact_service)?((zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0))?"not supported with zlib.output_compression":"enabled"):"not supported on this platform" ); - php_info_print_table_end(); - - DISPLAY_INI_ENTRIES(); -} -/* }}} */ - -/* {{{ proto bool nsapi_virtual(string uri) - Perform an NSAPI sub-request */ -/* This function is equivalent to <!--#include virtual...--> - * in SSI. It does an NSAPI sub-request. It is useful - * for including CGI scripts or .shtml files, or anything else - * that you'd parse through webserver. - */ -PHP_FUNCTION(nsapi_virtual) -{ - int uri_len,rv; - char *uri,*value; - Request *rq; - nsapi_request_context *rc = (nsapi_request_context *)SG(server_context); - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &uri, &uri_len) == FAILURE) { - return; - } - - if (!nsapi_servact_service) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include uri '%s' - Sub-requests not supported on this platform", uri); - RETURN_FALSE; - } else if (zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include uri '%s' - Sub-requests do not work with zlib.output_compression", uri); - RETURN_FALSE; - } else { - php_output_end_all(TSRMLS_C); - php_header(TSRMLS_C); - - /* do the sub-request */ - /* thanks to Chris Elving from Sun for this code sniplet */ - if ((rq = request_restart_internal(uri, NULL)) == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include uri '%s' - Internal request creation failed", uri); - RETURN_FALSE; - } - - /* insert host of current request to get page from same vhost */ - param_free(pblock_remove("host", rq->headers)); - if (value = pblock_findval("host", rc->rq->headers)) { - pblock_nvinsert("host", value, rq->headers); - } - - /* go through the normal request stages as given in obj.conf, - but leave out the logging/error section */ - do { - rv = (*nsapi_servact_uri2path)(rc->sn, rq); - if (rv != REQ_PROCEED) { - continue; - } - - rv = (*nsapi_servact_pathchecks)(rc->sn, rq); - if (rv != REQ_PROCEED) { - continue; - } - - rv = (*nsapi_servact_fileinfo)(rc->sn, rq); - if (rv != REQ_PROCEED) { - continue; - } - - rv = (*nsapi_servact_service)(rc->sn, rq); - } while (rv == REQ_RESTART); - - if (rq->status_num != 200) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include uri '%s' - HTTP status code %d during subrequest", uri, rq->status_num); - request_free(rq); - RETURN_FALSE; - } - - request_free(rq); - - RETURN_TRUE; - } -} -/* }}} */ - -/* {{{ proto array nsapi_request_headers(void) - Get all headers from the request */ -PHP_FUNCTION(nsapi_request_headers) -{ - register int i; - struct pb_entry *entry; - nsapi_request_context *rc = (nsapi_request_context *)SG(server_context); - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - array_init(return_value); - - for (i=0; i < rc->rq->headers->hsize; i++) { - entry=rc->rq->headers->ht[i]; - while (entry) { - add_assoc_string(return_value, entry->param->name, entry->param->value, 1); - entry=entry->next; - } - } -} -/* }}} */ - -/* {{{ proto array nsapi_response_headers(void) - Get all headers from the response */ -PHP_FUNCTION(nsapi_response_headers) -{ - register int i; - struct pb_entry *entry; - nsapi_request_context *rc = (nsapi_request_context *)SG(server_context); - - if (zend_parse_parameters_none() == FAILURE) { - return; - } - - array_init(return_value); - - for (i=0; i < rc->rq->srvhdrs->hsize; i++) { - entry=rc->rq->srvhdrs->ht[i]; - while (entry) { - add_assoc_string(return_value, entry->param->name, entry->param->value, 1); - entry=entry->next; - } - } -} -/* }}} */ - - -/*************/ -/* SAPI part */ -/*************/ - -static int sapi_nsapi_ub_write(const char *str, unsigned int str_length TSRMLS_DC) -{ - int retval; - nsapi_request_context *rc = (nsapi_request_context *)SG(server_context); - - if (!SG(headers_sent)) { - sapi_send_headers(TSRMLS_C); - } - - retval = net_write(rc->sn->csd, (char *)str, str_length); - if (retval == IO_ERROR /* -1 */ || retval == IO_EOF /* 0 */) { - php_handle_aborted_connection(); - } - return retval; -} - -/* modified version of apache2 */ -static void sapi_nsapi_flush(void *server_context) -{ - nsapi_request_context *rc = (nsapi_request_context *)server_context; - TSRMLS_FETCH(); - - if (!rc) { - /* we have no context, so no flushing needed. This fixes a SIGSEGV on shutdown */ - return; - } - - if (!SG(headers_sent)) { - sapi_send_headers(TSRMLS_C); - } - - /* flushing is only supported in iPlanet servers from version 6.1 on, make it conditional */ -#if NSAPI_VERSION >= 302 - if (net_flush(rc->sn->csd) < 0) { - php_handle_aborted_connection(); - } -#endif -} - -/* callback for zend_llist_apply on SAPI_HEADER_DELETE_ALL operation */ -static int php_nsapi_remove_header(sapi_header_struct *sapi_header TSRMLS_DC) -{ - char *header_name, *p; - nsapi_request_context *rc = (nsapi_request_context *)SG(server_context); - - /* copy the header, because NSAPI needs reformatting and we do not want to change the parameter */ - header_name = pool_strdup(rc->sn->pool, sapi_header->header); - - /* extract name, this works, if only the header without ':' is given, too */ - if (p = strchr(header_name, ':')) { - *p = 0; - } - - /* header_name to lower case because NSAPI reformats the headers and wants lowercase */ - for (p=header_name; *p; p++) { - *p=tolower(*p); - } - - /* remove the header */ - param_free(pblock_remove(header_name, rc->rq->srvhdrs)); - pool_free(rc->sn->pool, header_name); - - return ZEND_HASH_APPLY_KEEP; -} - -static int sapi_nsapi_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - char *header_name, *header_content, *p; - nsapi_request_context *rc = (nsapi_request_context *)SG(server_context); - - switch(op) { - case SAPI_HEADER_DELETE_ALL: - /* this only deletes headers set or overwritten by PHP, headers previously set by NSAPI are left intact */ - zend_llist_apply(&sapi_headers->headers, (llist_apply_func_t) php_nsapi_remove_header TSRMLS_CC); - return 0; - - case SAPI_HEADER_DELETE: - /* reuse the zend_llist_apply callback function for this, too */ - php_nsapi_remove_header(sapi_header TSRMLS_CC); - return 0; - - case SAPI_HEADER_ADD: - case SAPI_HEADER_REPLACE: - /* copy the header, because NSAPI needs reformatting and we do not want to change the parameter */ - header_name = pool_strdup(rc->sn->pool, sapi_header->header); - - /* split header and align pointer for content */ - header_content = strchr(header_name, ':'); - if (header_content) { - *header_content = 0; - do { - header_content++; - } while (*header_content==' '); - - /* header_name to lower case because NSAPI reformats the headers and wants lowercase */ - for (p=header_name; *p; p++) { - *p=tolower(*p); - } - - /* if REPLACE, remove first. "Content-type" is always removed, as SAPI has a bug according to this */ - if (op==SAPI_HEADER_REPLACE || strcmp(header_name, "content-type")==0) { - param_free(pblock_remove(header_name, rc->rq->srvhdrs)); - } - /* ADD header to nsapi table */ - pblock_nvinsert(header_name, header_content, rc->rq->srvhdrs); - } - - pool_free(rc->sn->pool, header_name); - return SAPI_HEADER_ADD; - - default: - return 0; - } -} - -static int sapi_nsapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - int retval; - nsapi_request_context *rc = (nsapi_request_context *)SG(server_context); - - if (SG(sapi_headers).send_default_content_type) { - char *hd; - param_free(pblock_remove("content-type", rc->rq->srvhdrs)); - hd = sapi_get_default_content_type(TSRMLS_C); - pblock_nvinsert("content-type", hd, rc->rq->srvhdrs); - efree(hd); - } - - protocol_status(rc->sn, rc->rq, SG(sapi_headers).http_response_code, NULL); - retval = protocol_start_response(rc->sn, rc->rq); - - if (retval == REQ_PROCEED || retval == REQ_NOACTION) { - return SAPI_HEADER_SENT_SUCCESSFULLY; - } else { - return SAPI_HEADER_SEND_FAILED; - } -} - -static int sapi_nsapi_read_post(char *buffer, uint count_bytes TSRMLS_DC) -{ - nsapi_request_context *rc = (nsapi_request_context *)SG(server_context); - char *read_ptr = buffer, *content_length_str = NULL; - uint bytes_read = 0; - int length, content_length = 0; - netbuf *nbuf = rc->sn->inbuf; - - /* - * Yesss! - */ - count_bytes = MIN(count_bytes, SG(request_info).content_length-rc->read_post_bytes); - content_length = SG(request_info).content_length; - - if (content_length <= 0) { - return 0; - } - - /* - * Gobble any pending data in the netbuf. - */ - length = nbuf->cursize - nbuf->pos; - length = MIN(count_bytes, length); - if (length > 0) { - memcpy(read_ptr, nbuf->inbuf + nbuf->pos, length); - bytes_read += length; - read_ptr += length; - content_length -= length; - nbuf->pos += length; - } - - /* - * Read the remaining from the socket. - */ - while (content_length > 0 && bytes_read < count_bytes) { - int bytes_to_read = count_bytes - bytes_read; - - if (content_length < bytes_to_read) { - bytes_to_read = content_length; - } - - length = net_read(rc->sn->csd, read_ptr, bytes_to_read, NSAPI_G(read_timeout)); - - if (length == IO_ERROR || length == IO_EOF) { - break; - } - - bytes_read += length; - read_ptr += length; - content_length -= length; - } - - if ( bytes_read > 0 ) { - rc->read_post_bytes += bytes_read; - } - return bytes_read; -} - -static char *sapi_nsapi_read_cookies(TSRMLS_D) -{ - char *cookie_string; - nsapi_request_context *rc = (nsapi_request_context *)SG(server_context); - - cookie_string = pblock_findval("cookie", rc->rq->headers); - return cookie_string; -} - -static void sapi_nsapi_register_server_variables(zval *track_vars_array TSRMLS_DC) -{ - nsapi_request_context *rc = (nsapi_request_context *)SG(server_context); - register size_t i; - int pos; - char *value,*p; - char buf[32]; - struct pb_entry *entry; - - for (i = 0; i < nsapi_reqpb_size; i++) { - value = pblock_findval(nsapi_reqpb[i].nsapi_eq, rc->rq->reqpb); - if (value) { - php_register_variable((char *)nsapi_reqpb[i].env_var, value, track_vars_array TSRMLS_CC); - } - } - - for (i=0; i < rc->rq->headers->hsize; i++) { - entry=rc->rq->headers->ht[i]; - while (entry) { - if (strcasecmp(entry->param->name, "content-length")==0 || strcasecmp(entry->param->name, "content-type")==0) { - value=estrdup(entry->param->name); - pos = 0; - } else { - spprintf(&value, 0, "HTTP_%s", entry->param->name); - pos = 5; - } - if (value) { - for(p = value + pos; *p; p++) { - *p = toupper(*p); - if (!isalnum(*p)) { - *p = '_'; - } - } - php_register_variable(value, entry->param->value, track_vars_array TSRMLS_CC); - efree(value); - } - entry=entry->next; - } - } - - for (i = 0; i < nsapi_vars_size; i++) { - value = pblock_findval(nsapi_vars[i].nsapi_eq, rc->rq->vars); - if (value) { - php_register_variable((char *)nsapi_vars[i].env_var, value, track_vars_array TSRMLS_CC); - } - } - - for (i = 0; i < nsapi_client_size; i++) { - value = pblock_findval(nsapi_client[i].nsapi_eq, rc->sn->client); - if (value) { - php_register_variable((char *)nsapi_client[i].env_var, value, track_vars_array TSRMLS_CC); - } - } - - if (value = session_dns(rc->sn)) { - php_register_variable("REMOTE_HOST", value, track_vars_array TSRMLS_CC); - nsapi_free(value); - } - - slprintf(buf, sizeof(buf), "%d", conf_getglobals()->Vport); - php_register_variable("SERVER_PORT", buf, track_vars_array TSRMLS_CC); - php_register_variable("SERVER_NAME", conf_getglobals()->Vserver_hostname, track_vars_array TSRMLS_CC); - - value = http_uri2url_dynamic("", "", rc->sn, rc->rq); - php_register_variable("SERVER_URL", value, track_vars_array TSRMLS_CC); - nsapi_free(value); - - php_register_variable("SERVER_SOFTWARE", system_version(), track_vars_array TSRMLS_CC); - if (security_active) { - php_register_variable("HTTPS", "ON", track_vars_array TSRMLS_CC); - } - php_register_variable("GATEWAY_INTERFACE", "CGI/1.1", track_vars_array TSRMLS_CC); - - /* DOCUMENT_ROOT */ - if (value = request_translate_uri("/", rc->sn)) { - pos = strlen(value); - php_register_variable_safe("DOCUMENT_ROOT", value, pos-1, track_vars_array TSRMLS_CC); - nsapi_free(value); - } - - /* PATH_INFO / PATH_TRANSLATED */ - if (rc->path_info) { - if (value = request_translate_uri(rc->path_info, rc->sn)) { - php_register_variable("PATH_TRANSLATED", value, track_vars_array TSRMLS_CC); - nsapi_free(value); - } - php_register_variable("PATH_INFO", rc->path_info, track_vars_array TSRMLS_CC); - } - - /* Create full Request-URI & Script-Name */ - if (SG(request_info).request_uri) { - pos = strlen(SG(request_info).request_uri); - - if (SG(request_info).query_string) { - spprintf(&value, 0, "%s?%s", SG(request_info).request_uri, SG(request_info).query_string); - if (value) { - php_register_variable("REQUEST_URI", value, track_vars_array TSRMLS_CC); - efree(value); - } - } else { - php_register_variable_safe("REQUEST_URI", SG(request_info).request_uri, pos, track_vars_array TSRMLS_CC); - } - - if (rc->path_info) { - pos -= strlen(rc->path_info); - if (pos<0) { - pos = 0; - } - } - php_register_variable_safe("SCRIPT_NAME", SG(request_info).request_uri, pos, track_vars_array TSRMLS_CC); - } - php_register_variable("SCRIPT_FILENAME", SG(request_info).path_translated, track_vars_array TSRMLS_CC); - - /* special variables in error mode */ - if (rc->http_error) { - slprintf(buf, sizeof(buf), "%d", rc->http_error); - php_register_variable("ERROR_TYPE", buf, track_vars_array TSRMLS_CC); - } -} - -static void nsapi_log_message(char *message TSRMLS_DC) -{ - nsapi_request_context *rc = (nsapi_request_context *)SG(server_context); - - if (rc) { - log_error(LOG_INFORM, pblock_findval("fn", rc->pb), rc->sn, rc->rq, "%s", message); - } else { - log_error(LOG_INFORM, "php5", NULL, NULL, "%s", message); - } -} - -static double sapi_nsapi_get_request_time(TSRMLS_D) -{ - return REQ_TIME( ((nsapi_request_context *)SG(server_context))->rq ); -} - -static int php_nsapi_startup(sapi_module_struct *sapi_module) -{ - if (php_module_startup(sapi_module, &nsapi_module_entry, 1)==FAILURE) { - return FAILURE; - } - return SUCCESS; -} - -static struct stat* sapi_nsapi_get_stat(TSRMLS_D) -{ - return request_stat_path( - SG(request_info).path_translated, - ((nsapi_request_context *)SG(server_context))->rq - ); -} - -static sapi_module_struct nsapi_sapi_module = { - "nsapi", /* name */ - "NSAPI", /* pretty name */ - - php_nsapi_startup, /* startup */ - php_module_shutdown_wrapper, /* shutdown */ - - NULL, /* activate */ - NULL, /* deactivate */ - - sapi_nsapi_ub_write, /* unbuffered write */ - sapi_nsapi_flush, /* flush */ - sapi_nsapi_get_stat, /* get uid/stat */ - NULL, /* getenv */ - - php_error, /* error handler */ - - sapi_nsapi_header_handler, /* header handler */ - sapi_nsapi_send_headers, /* send headers handler */ - NULL, /* send header handler */ - - sapi_nsapi_read_post, /* read POST data */ - sapi_nsapi_read_cookies, /* read Cookies */ - - sapi_nsapi_register_server_variables, /* register server variables */ - nsapi_log_message, /* Log message */ - sapi_nsapi_get_request_time, /* Get request time */ - NULL, /* Child terminate */ - - NULL, /* Block interruptions */ - NULL, /* Unblock interruptions */ - - STANDARD_SAPI_MODULE_PROPERTIES -}; - -static void nsapi_php_ini_entries(NSLS_D TSRMLS_DC) -{ - struct pb_entry *entry; - register int i,j,ok; - - for (i=0; i < NSG(pb)->hsize; i++) { - entry=NSG(pb)->ht[i]; - while (entry) { - /* exclude standard entries given to "Service" which should not go into ini entries */ - ok=1; - for (j=0; nsapi_exclude_from_ini_entries[j]; j++) { - ok&=(strcasecmp(entry->param->name, nsapi_exclude_from_ini_entries[j])!=0); - } - - if (ok) { - /* change the ini entry */ - if (zend_alter_ini_entry(entry->param->name, strlen(entry->param->name)+1, - entry->param->value, strlen(entry->param->value), - PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE)==FAILURE) { - log_error(LOG_WARN, pblock_findval("fn", NSG(pb)), NSG(sn), NSG(rq), "Cannot change php.ini key \"%s\" to \"%s\"", entry->param->name, entry->param->value); - } - } - entry=entry->next; - } - } -} - -void NSAPI_PUBLIC php5_close(void *vparam) -{ - if (nsapi_sapi_module.shutdown) { - nsapi_sapi_module.shutdown(&nsapi_sapi_module); - } - - if (nsapi_sapi_module.php_ini_path_override) { - free(nsapi_sapi_module.php_ini_path_override); - } - -#ifdef PHP_WIN32 - if (nsapi_dll) { - free(nsapi_dll); - nsapi_dll = NULL; - } -#endif - - sapi_shutdown(); - tsrm_shutdown(); - - log_error(LOG_INFORM, "php5_close", NULL, NULL, "Shutdown PHP Module"); -} - -/********************************************************* -/ init SAF -/ -/ Init fn="php5_init" [php_ini="/path/to/php.ini"] [server_lib="ns-httpdXX.dll"] -/ Initialize the NSAPI module in magnus.conf -/ -/ php_ini: gives path to php.ini file -/ server_lib: (only Win32) gives name of DLL (without path) to look for -/ servact_* functions -/ -/*********************************************************/ -int NSAPI_PUBLIC php5_init(pblock *pb, Session *sn, Request *rq) -{ - php_core_globals *core_globals; - char *strval; - int threads=128; /* default for server */ - - /* fetch max threads from NSAPI and initialize TSRM with it */ - threads=conf_getglobals()->Vpool_maxthreads; - if (threads<1) { - threads=128; /* default for server */ - } - tsrm_startup(threads, 1, 0, NULL); - - core_globals = ts_resource(core_globals_id); - - /* look if php_ini parameter is given to php5_init */ - if (strval = pblock_findval("php_ini", pb)) { - nsapi_sapi_module.php_ini_path_override = strdup(strval); - } - -#ifdef PHP_WIN32 - /* look if server_lib parameter is given to php5_init - * (this disables the automatic search for the newest ns-httpdXX.dll) */ - if (strval = pblock_findval("server_lib", pb)) { - nsapi_dll = strdup(strval); - } -#endif - - /* start SAPI */ - sapi_startup(&nsapi_sapi_module); - nsapi_sapi_module.startup(&nsapi_sapi_module); - - daemon_atrestart(&php5_close, NULL); - - log_error(LOG_INFORM, pblock_findval("fn", pb), sn, rq, "Initialized PHP Module (%d threads expected)", threads); - return REQ_PROCEED; -} - -/********************************************************* -/ normal use in Service directive: -/ -/ Service fn="php5_execute" type=... method=... [inikey=inivalue inikey=inivalue...] -/ -/ use in Service for a directory to supply a php-made directory listing instead of server default: -/ -/ Service fn="php5_execute" type="magnus-internal/directory" script="/path/to/script.php" [inikey=inivalue inikey=inivalue...] -/ -/ use in Error SAF to display php script as error page: -/ -/ Error fn="php5_execute" code=XXX script="/path/to/script.php" [inikey=inivalue inikey=inivalue...] -/ Error fn="php5_execute" reason="Reason" script="/path/to/script.php" [inikey=inivalue inikey=inivalue...] -/ -/*********************************************************/ -int NSAPI_PUBLIC php5_execute(pblock *pb, Session *sn, Request *rq) -{ - int retval; - nsapi_request_context *request_context; - zend_file_handle file_handle = {0}; - struct stat *fst; - - char *path_info; - char *query_string = pblock_findval("query", rq->reqpb); - char *uri = pblock_findval("uri", rq->reqpb); - char *request_method = pblock_findval("method", rq->reqpb); - char *content_type = pblock_findval("content-type", rq->headers); - char *content_length = pblock_findval("content-length", rq->headers); - char *directive = pblock_findval("Directive", pb); - int error_directive = (directive && !strcasecmp(directive, "error")); - int fixed_script = 1; - - /* try to use script parameter -> Error or Service for directory listing */ - char *path_translated = pblock_findval("script", pb); - - TSRMLS_FETCH(); - - /* if script parameter is missing: normal use as Service SAF */ - if (!path_translated) { - path_translated = pblock_findval("path", rq->vars); - path_info = pblock_findval("path-info", rq->vars); - fixed_script = 0; - if (error_directive) { - /* go to next error directive if script parameter is missing */ - log_error(LOG_WARN, pblock_findval("fn", pb), sn, rq, "Missing 'script' parameter"); - return REQ_NOACTION; - } - } else { - /* in error the path_info is the uri to the requested page */ - path_info = pblock_findval("uri", rq->reqpb); - } - - /* check if this uri was included in an other PHP script with nsapi_virtual() - by looking for a request context in the current thread */ - if (SG(server_context)) { - /* send 500 internal server error */ - log_error(LOG_WARN, pblock_findval("fn", pb), sn, rq, "Cannot make nesting PHP requests with nsapi_virtual()"); - if (error_directive) { - return REQ_NOACTION; - } else { - protocol_status(sn, rq, 500, NULL); - return REQ_ABORTED; - } - } - - request_context = (nsapi_request_context *)pool_malloc(sn->pool, sizeof(nsapi_request_context)); - if (!request_context) { - log_error(LOG_CATASTROPHE, pblock_findval("fn", pb), sn, rq, "Insufficient memory to process PHP request!"); - return REQ_ABORTED; - } - request_context->pb = pb; - request_context->sn = sn; - request_context->rq = rq; - request_context->read_post_bytes = 0; - request_context->fixed_script = fixed_script; - request_context->http_error = (error_directive) ? rq->status_num : 0; - request_context->path_info = path_info; - - SG(server_context) = request_context; - SG(request_info).query_string = query_string; - SG(request_info).request_uri = uri; - SG(request_info).request_method = request_method; - SG(request_info).path_translated = path_translated; - SG(request_info).content_type = content_type; - SG(request_info).content_length = (content_length == NULL) ? 0 : strtoul(content_length, 0, 0); - SG(sapi_headers).http_response_code = (error_directive) ? rq->status_num : 200; - - nsapi_php_ini_entries(NSLS_C TSRMLS_CC); - - php_handle_auth_data(pblock_findval("authorization", rq->headers) TSRMLS_CC); - - file_handle.type = ZEND_HANDLE_FILENAME; - file_handle.filename = SG(request_info).path_translated; - file_handle.free_filename = 0; - file_handle.opened_path = NULL; - - fst = request_stat_path(SG(request_info).path_translated, rq); - if (fst && S_ISREG(fst->st_mode)) { - if (php_request_startup(TSRMLS_C) == SUCCESS) { - php_execute_script(&file_handle TSRMLS_CC); - php_request_shutdown(NULL); - retval=REQ_PROCEED; - } else { - /* send 500 internal server error */ - log_error(LOG_WARN, pblock_findval("fn", pb), sn, rq, "Cannot prepare PHP engine!"); - if (error_directive) { - retval=REQ_NOACTION; - } else { - protocol_status(sn, rq, 500, NULL); - retval=REQ_ABORTED; - } - } - } else { - /* send 404 because file not found */ - log_error(LOG_WARN, pblock_findval("fn", pb), sn, rq, "Cannot execute PHP script: %s (File not found)", SG(request_info).path_translated); - if (error_directive) { - retval=REQ_NOACTION; - } else { - protocol_status(sn, rq, 404, NULL); - retval=REQ_ABORTED; - } - } - - pool_free(sn->pool, request_context); - SG(server_context) = NULL; - - return retval; -} - -/********************************************************* -/ authentication -/ -/ we have to make a 'fake' authenticator for netscape so it -/ will pass authentication through to php, and allow us to -/ check authentication with our scripts. -/ -/ php5_auth_trans -/ main function called from netscape server to authenticate -/ a line in obj.conf: -/ funcs=php5_auth_trans shlib="path/to/this/phpnsapi.dll" -/ and: -/ <Object ppath="path/to/be/authenticated/by/php/*"> -/ AuthTrans fn="php5_auth_trans" -/*********************************************************/ -int NSAPI_PUBLIC php5_auth_trans(pblock * pb, Session * sn, Request * rq) -{ - /* This is a DO NOTHING function that allows authentication - * information - * to be passed through to PHP scripts. - */ - return REQ_PROCEED; -} - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/sapi/nsapi/php5nsapi.dsp b/sapi/nsapi/php5nsapi.dsp deleted file mode 100644 index 6cd0079b43..0000000000 --- a/sapi/nsapi/php5nsapi.dsp +++ /dev/null @@ -1,135 +0,0 @@ -# Microsoft Developer Studio Project File - Name="php5nsapi" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=php5nsapi - 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 "php5nsapi.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 "php5nsapi.mak" CFG="php5nsapi - Win32 Debug_TS"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "php5nsapi - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "php5nsapi - Win32 Release_TS_inline" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "php5nsapi - 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)" == "php5nsapi - Win32 Release_TS"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "php5nsapi___Win32_Release_TS"
-# PROP BASE Intermediate_Dir "php5nsapi___Win32_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 "php5nsapi_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "..\..\..\php_build\nsapi30\include\\" /I "..\..\include" /I "..\..\win32" /I "..\..\Zend" /I "..\.." /I "..\..\..\bindlib_w32" /I "..\..\main" /I "..\..\tsrm" /D ZEND_DEBUG=0 /D "NDEBUG" /D "XP_WIN32" /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "_WINDOWS" /D "_USRDLL" /D "php5nsapi_EXPORTS" /D "WIN32" /D "_MBCS" /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /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 ns-httpd30.lib php5ts.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 /base:"0x62000000" /version:4.0 /dll /machine:I386 /libpath:"..\..\..\php_build\nsapi30\lib\\" /libpath:"..\..\Release_TS" /libpath:"..\..\TSRM\Release_TS" /libpath:"..\..\Zend\Release_TS"
-
-!ELSEIF "$(CFG)" == "php5nsapi - Win32 Release_TS_inline"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "php5nsapi___Win32_Release_TS_inline"
-# PROP BASE Intermediate_Dir "php5nsapi___Win32_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 "php5nsapi_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I "..\..\..\php_build\nsapi30\include\\" /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 "XP_WIN32" /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "_WINDOWS" /D "_USRDLL" /D "php5nsapi_EXPORTS" /D "WIN32" /D "_MBCS" /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /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 ns-httpd30.lib php5ts.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 /base:"0x62000000" /version:4.0 /dll /machine:I386 /libpath:"..\..\..\php_build\nsapi30\lib\\" /libpath:"..\..\Release_TS_inline" /libpath:"..\..\TSRM\Release_TS_inline" /libpath:"..\..\Zend\Release_TS_inline"
-
-!ELSEIF "$(CFG)" == "php5nsapi - Win32 Debug_TS"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "php5nsapi___Win32_Debug_TS"
-# PROP BASE Intermediate_Dir "php5nsapi___Win32_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 Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "php5nsapi_EXPORTS" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /I "..\..\..\php_build\nsapi30\include\\" /I "..\..\include" /I "..\..\win32" /I "..\..\Zend" /I "..\.." /I "..\..\..\bindlib_w32" /I "..\..\main" /I "..\..\tsrm" /D "_Debug_TS" /D ZEND_DEBUG=1 /D "_DEBUG" /D "XP_WIN32" /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "_WINDOWS" /D "_USRDLL" /D "php5nsapi_EXPORTS" /D "WIN32" /D "_MBCS" /FR /YX /FD /GZ /c
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /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 ns-httpd30.lib php5ts_debug.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 /base:"0x62000000" /version:4.0 /dll /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\php_build\nsapi30\lib\\" /libpath:"..\..\Debug_TS" /libpath:"..\..\TSRM\Debug_TS" /libpath:"..\..\Zend\Debug_TS"
-
-!ENDIF
-
-# Begin Target
-
-# Name "php5nsapi - Win32 Release_TS"
-# Name "php5nsapi - Win32 Release_TS_inline"
-# Name "php5nsapi - Win32 Debug_TS"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\nsapi.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# Begin Group "Resource Files"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-# End Group
-# End Target
-# End Project
diff --git a/sapi/phpdbg/.travis.yml b/sapi/phpdbg/.travis.yml index d5b492e7cf..2e777fbe13 100644 --- a/sapi/phpdbg/.travis.yml +++ b/sapi/phpdbg/.travis.yml @@ -4,7 +4,6 @@ env: - PHP="PHP-5.4" - PHP="PHP-5.5" - PHP="PHP-5.6" -- PHP="master" before_script: ./travis/ci.sh diff --git a/sapi/phpdbg/Makefile.frag b/sapi/phpdbg/Makefile.frag index 36c7512d69..e0cdfe25ef 100644 --- a/sapi/phpdbg/Makefile.frag +++ b/sapi/phpdbg/Makefile.frag @@ -14,7 +14,7 @@ $(BUILD_BINARY): $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_PHPDBG_OBJS) $(builddir)/phpdbg_lexer.lo: $(srcdir)/phpdbg_parser.h $(srcdir)/phpdbg_lexer.c: $(srcdir)/phpdbg_lexer.l - @(cd $(top_srcdir); $(RE2C) $(RE2C_FLAGS) --no-generation-date -cbdFo $(srcdir)/phpdbg_lexer.c $(srcdir)/phpdbg_lexer.l) + @(cd $(top_srcdir); $(RE2C) $(RE2C_FLAGS) --no-generation-date -cbdFo sapi/phpdbg/phpdbg_lexer.c sapi/phpdbg/phpdbg_lexer.l) $(srcdir)/phpdbg_parser.h: $(srcdir)/phpdbg_parser.c $(srcdir)/phpdbg_parser.c: $(srcdir)/phpdbg_parser.y diff --git a/sapi/phpdbg/README.md b/sapi/phpdbg/README.md index e7e5c731a8..a2a84deb7b 100644 --- a/sapi/phpdbg/README.md +++ b/sapi/phpdbg/README.md @@ -1,7 +1,7 @@ The interactive PHP debugger ============================ -Implemented as a SAPI module, phpdbg can excert complete control over the environment without impacting the functionality or performance of your code. +Implemented as a SAPI module, phpdbg can exert complete control over the environment without impacting the functionality or performance of your code. phpdbg aims to be a lightweight, powerful, easy to use debugging platform for PHP 5.4+ diff --git a/sapi/phpdbg/config.m4 b/sapi/phpdbg/config.m4 index d78a439af0..9fb4e62984 100644 --- a/sapi/phpdbg/config.m4 +++ b/sapi/phpdbg/config.m4 @@ -3,12 +3,15 @@ dnl $Id$ dnl PHP_ARG_ENABLE(phpdbg, for phpdbg support, -[ --enable-phpdbg Build phpdbg], no, no) +[ --enable-phpdbg Build phpdbg], yes, yes) + +PHP_ARG_ENABLE(phpdbg-webhelper, for phpdbg web SAPI support, +[ --enable-phpdbg-webhelper Build phpdbg web SAPI support], no) PHP_ARG_ENABLE(phpdbg-debug, for phpdbg debug build, -[ --enable-phpdbg-debug Build phpdbg in debug mode], no, no) +[ --enable-phpdbg-debug Build phpdbg in debug mode], no, no) -if test "$PHP_PHPDBG" != "no"; then +if test "$BUILD_PHPDBG" = "" && test "$PHP_PHPDBG" != "no"; then AC_HEADER_TIOCGWINSZ AC_DEFINE(HAVE_PHPDBG, 1, [ ]) @@ -18,8 +21,8 @@ if test "$PHP_PHPDBG" != "no"; then AC_DEFINE(PHPDBG_DEBUG, 0, [ ]) fi - PHP_PHPDBG_CFLAGS="-D_GNU_SOURCE" - PHP_PHPDBG_FILES="phpdbg.c phpdbg_parser.c phpdbg_lexer.c phpdbg_prompt.c phpdbg_help.c phpdbg_break.c phpdbg_print.c phpdbg_bp.c phpdbg_opcode.c phpdbg_list.c phpdbg_utils.c phpdbg_info.c phpdbg_cmd.c phpdbg_set.c phpdbg_frame.c phpdbg_watch.c phpdbg_btree.c" + PHP_PHPDBG_CFLAGS="-D_GNU_SOURCE -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1" + PHP_PHPDBG_FILES="phpdbg.c phpdbg_parser.c phpdbg_lexer.c phpdbg_prompt.c phpdbg_help.c phpdbg_break.c phpdbg_print.c phpdbg_bp.c phpdbg_opcode.c phpdbg_list.c phpdbg_utils.c phpdbg_info.c phpdbg_cmd.c phpdbg_set.c phpdbg_frame.c phpdbg_watch.c phpdbg_btree.c phpdbg_sigsafe.c phpdbg_wait.c phpdbg_io.c phpdbg_eol.c phpdbg_out.c" if test "$PHP_READLINE" != "no" -o "$PHP_LIBEDIT" != "no"; then PHPDBG_EXTRA_LIBS="$PHP_READLINE_LIBS" @@ -62,6 +65,10 @@ if test "$PHP_PHPDBG" != "no"; then PHP_SUBST(BUILD_PHPDBG_SHARED) fi +if test "$PHP_PHPDBG_WEBHELPER" != "no"; then + PHP_NEW_EXTENSION(phpdbg_webhelper, phpdbg_rinit_hook.c phpdbg_webdata_transfer.c, $ext_shared) +fi + dnl ## Local Variables: dnl ## tab-width: 4 dnl ## End: diff --git a/sapi/phpdbg/config.w32 b/sapi/phpdbg/config.w32 index 17e15b6ced..2d907ee697 100644 --- a/sapi/phpdbg/config.w32 +++ b/sapi/phpdbg/config.w32 @@ -1,14 +1,25 @@ ARG_ENABLE('phpdbg', 'Build phpdbg', 'no'); ARG_ENABLE('phpdbgs', 'Build phpdbg shared', 'no'); +ARG_ENABLE('phpdbg-webhelper', 'Build phpdbg webhelper', 'yes'); -PHPDBG_SOURCES='phpdbg.c phpdbg_prompt.c phpdbg_cmd.c phpdbg_info.c phpdbg_help.c phpdbg_break.c phpdbg_print.c phpdbg_bp.c phpdbg_opcode.c phpdbg_list.c phpdbg_utils.c phpdbg_set.c phpdbg_frame.c phpdbg_watch.c phpdbg_win.c phpdbg_btree.c phpdbg_parser.c phpdbg_lexer.c'; +PHPDBG_SOURCES='phpdbg.c phpdbg_prompt.c phpdbg_cmd.c phpdbg_info.c phpdbg_help.c phpdbg_break.c ' + + 'phpdbg_print.c phpdbg_bp.c phpdbg_opcode.c phpdbg_list.c phpdbg_utils.c ' + + 'phpdbg_set.c phpdbg_frame.c phpdbg_watch.c phpdbg_win.c phpdbg_btree.c '+ + 'phpdbg_parser.c phpdbg_lexer.c phpdbg_sigsafe.c phpdbg_wait.c phpdbg_io.c ' + + 'phpdbg_sigio_win32.c phpdbg_eol.c phpdbg_out.c'; PHPDBG_DLL='php' + PHP_VERSION + 'phpdbg.dll'; PHPDBG_EXE='phpdbg.exe'; +PHPDBG_CFLAGS='/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1'; if (PHP_PHPDBG == "yes") { - SAPI('phpdbg', PHPDBG_SOURCES, PHPDBG_EXE); + SAPI('phpdbg', PHPDBG_SOURCES, PHPDBG_EXE, PHPDBG_CFLAGS); ADD_FLAG("LIBS_PHPDBG", "ws2_32.lib user32.lib"); ADD_FLAG("CFLAGS_PHPDBG", "/D YY_NO_UNISTD_H"); + ADD_FLAG("LDFLAGS_PHPDBG", "/stack:8388608"); + + if (PHP_PHPDBG_WEBHELPER == "yes") { + EXTENSION('phpdbg_webhelper', 'phpdbg_rinit_hook.c phpdbg_webdata_transfer.c'); + } } if (PHP_PHPDBGS == "yes") { diff --git a/sapi/phpdbg/create-test.php b/sapi/phpdbg/create-test.php new file mode 100644 index 0000000000..0d79fad5dd --- /dev/null +++ b/sapi/phpdbg/create-test.php @@ -0,0 +1,150 @@ +#!/usr/bin/env php +<?php + +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2016 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: Bob Weinand <bwoebi@php.net> | + +----------------------------------------------------------------------+ +*/ + +##### +## This is just a helper for intercepting stdin/stdout and the file and create a half-finished test. +## The output still may need adapting to match file names etc. +##### + +error_reporting(-1); + +$phpdbg = getenv('TEST_PHPDBG_EXECUTABLE') ?: null; +$pass_options = ' -qbI -n -d "error_reporting=32767" -d "display_errors=1" -d "display_startup_errors=1" -d "log_errors=0"'; +$file = ""; +$cmdargv = ""; + +if (isset($argc) && $argc > 1) { + $post_ddash = false; + for ($i = 1; $i < $argc; $i++) { + if ($argv[$i][0] == "-" && !$post_ddash) { + switch (substr($argv[$i], 1)) { + case "p": + $phpdbg = $argv[++$i]; + break; + case "n": + $pass_options .= " -n"; + break; + case "d": + $pass_options .= " -d ".escapeshellarg($argv[++$i]); + $ini[] = $argv[$i]; + break; + case "-": + $post_ddash = true; + break; + } + } else { + $real_argv[] = $argv[$i]; + } + } + if (isset($real_argv[0])) { + $file = realpath($real_argv[0]); + $cmdargv = implode(" ", array_map("escapeshellarg", array_slice($real_argv, 1))); + } +} + +$proc = proc_open("$phpdbg $pass_options $file -- $cmdargv", [["pipe", "r"], ["pipe", "w"], ["pipe", "w"]], $pipes); +if (!$proc) { + die("Couldn't start phpdbg\n"); +} + +$input = $output = ""; + +stream_set_blocking(STDIN, false); + +do { + $r = [$pipes[1], STDIN]; + $w = $e = null; + $n = @stream_select($r, $w, $e, null); + + if ($n > 0) { + if ("" != $in = fread(STDIN, 1024)) { + $input .= $in; + fwrite($pipes[0], $in); + continue; + } + + if (feof(STDIN)) { + die("stdin closed?!\n"); + } + + if (feof($pipes[1])) { + $n = false; + } else { + $output .= $c = fgetc($pipes[1]); + echo $c; + } + } +} while ($n !== false); + +stream_set_blocking(STDIN, true); + +print "\n"; +if (!isset($name)) { + print "Specify the test description: "; + $desc = trim(fgets(STDIN)); +} +while (!isset($testfile)) { + print "Specify the test file name (leave empty to write to stderr): "; + $testfile = trim(fgets(STDIN)); + if ($testfile != "" && file_exists($testfile)) { + print "That file already exists. Type y or yes to overwrite: "; + $y = trim(fgets(STDIN)); + if ($y !== "y" && $y !== "yes") { + unset($testfile); + } + } +} + +$output = str_replace("string(".strlen($file).") \"$file\"", 'string(%d) "%s"', $output); +$output = str_replace($file, "%s", $output); +$input = trim($input); + +$testdata = <<<TEST +--TEST-- +$desc +--PHPDBG-- +$input +--EXPECTF-- +$output +TEST; + +if (!empty($ini)) { + $testdata .= "\n--INI--\n".implode("\n", $ini); +} +if ($cmdargv != "") { + $testdata .= "\n--ARGS--\n$cmdargv"; +} +if ($file != "") { + $testdata .= "\n--FILE--\n".file_get_contents($file); +} + +if ($testfile == "") { + print "\n"; +} elseif (file_put_contents($testfile, $testdata)) { + print "Test saved to $testfile\n"; +} else { + print "The test could not be saved to $testfile; outputting on stderr now\n"; + $testfile = ""; +} + +if ($testfile == "") { + fwrite(STDERR, $testdata); +} diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index 01a4b5e4b4..68a164c499 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -21,6 +21,7 @@ #if !defined(ZEND_SIGNALS) || defined(_WIN32) # include <signal.h> #endif + #include "phpdbg.h" #include "phpdbg_prompt.h" #include "phpdbg_bp.h" @@ -28,7 +29,12 @@ #include "phpdbg_list.h" #include "phpdbg_utils.h" #include "phpdbg_set.h" +#include "phpdbg_io.h" #include "zend_alloc.h" +#include "phpdbg_eol.h" +#include "phpdbg_print.h" + +#include "ext/standard/basic_functions.h" /* {{{ remote console headers */ #ifndef _WIN32 @@ -36,20 +42,39 @@ # include <sys/select.h> # include <sys/time.h> # include <sys/types.h> +# include <sys/poll.h> # include <netinet/in.h> # include <unistd.h> # include <arpa/inet.h> #endif /* }}} */ +#if defined(PHP_WIN32) && defined(HAVE_OPENSSL) +# include "openssl/applink.c" +#endif + +#if defined(PHP_WIN32) && defined(ZTS) +ZEND_TSRMLS_CACHE_DEFINE() +#endif + ZEND_DECLARE_MODULE_GLOBALS(phpdbg); +int phpdbg_startup_run = 0; -static zend_bool phpdbg_booted = 0; +static PHP_INI_MH(OnUpdateEol) +{ + if (!new_value) { + return FAILURE; + } -#if PHP_VERSION_ID >= 50500 -void (*zend_execute_old)(zend_execute_data *execute_data TSRMLS_DC); -#else -void (*zend_execute_old)(zend_op_array *op_array TSRMLS_DC); -#endif + return phpdbg_eol_global_update(ZSTR_VAL(new_value)); +} + +PHP_INI_BEGIN() + STD_PHP_INI_ENTRY("phpdbg.path", "", PHP_INI_SYSTEM | PHP_INI_PERDIR, OnUpdateString, socket_path, zend_phpdbg_globals, phpdbg_globals) + STD_PHP_INI_ENTRY("phpdbg.eol", "2", PHP_INI_ALL, OnUpdateEol, socket_path, zend_phpdbg_globals, phpdbg_globals) +PHP_INI_END() + +static zend_bool phpdbg_booted = 0; +static zend_bool phpdbg_fully_started = 0; static inline void php_phpdbg_globals_ctor(zend_phpdbg_globals *pg) /* {{{ */ { @@ -60,33 +85,51 @@ static inline void php_phpdbg_globals_ctor(zend_phpdbg_globals *pg) /* {{{ */ pg->colors[1] = NULL; pg->colors[2] = NULL; + pg->lines = phpdbg_get_terminal_height(); pg->exec = NULL; pg->exec_len = 0; pg->buffer = NULL; + pg->last_was_newline = 1; pg->ops = NULL; pg->vmret = 0; + pg->in_execution = 0; pg->bp_count = 0; pg->flags = PHPDBG_DEFAULT_FLAGS; pg->oplog = NULL; - pg->io[PHPDBG_STDIN] = NULL; - pg->io[PHPDBG_STDOUT] = NULL; - pg->io[PHPDBG_STDERR] = NULL; + memset(pg->io, 0, sizeof(pg->io)); pg->frame.num = 0; + pg->sapi_name_ptr = NULL; + pg->socket_fd = -1; + pg->socket_server_fd = -1; + pg->unclean_eval = 0; + + pg->req_id = 0; + pg->err_buf.active = 0; + pg->err_buf.type = 0; + + pg->input_buflen = 0; + pg->sigsafe_mem.mem = NULL; + pg->sigsegv_bailout = NULL; + + pg->oplog_list = NULL; + +#ifdef PHP_WIN32 + pg->sigio_watcher_thread = INVALID_HANDLE_VALUE; + memset(&pg->swd, 0, sizeof(struct win32_sigio_watcher_data)); +#endif + + pg->eol = PHPDBG_EOL_LF; } /* }}} */ static PHP_MINIT_FUNCTION(phpdbg) /* {{{ */ { ZEND_INIT_MODULE_GLOBALS(phpdbg, php_phpdbg_globals_ctor, NULL); -#if PHP_VERSION_ID >= 50500 - zend_execute_old = zend_execute_ex; + REGISTER_INI_ENTRIES(); + zend_execute_ex = phpdbg_execute_ex; -#else - zend_execute_old = zend_execute; - zend_execute = phpdbg_execute_ex; -#endif REGISTER_STRINGL_CONSTANT("PHPDBG_VERSION", PHPDBG_VERSION, sizeof(PHPDBG_VERSION)-1, CONST_CS|CONST_PERSISTENT); - + REGISTER_LONG_CONSTANT("PHPDBG_FILE", FILE_PARAM, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PHPDBG_METHOD", METHOD_PARAM, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PHPDBG_LINENO", NUMERIC_PARAM, CONST_CS|CONST_PERSISTENT); @@ -99,61 +142,63 @@ static PHP_MINIT_FUNCTION(phpdbg) /* {{{ */ return SUCCESS; } /* }}} */ -static void php_phpdbg_destroy_bp_file(void *brake) /* {{{ */ +static void php_phpdbg_destroy_bp_file(zval *brake) /* {{{ */ { - zend_hash_destroy((HashTable*)brake); + zend_hash_destroy(Z_ARRVAL_P(brake)); + efree(Z_ARRVAL_P(brake)); } /* }}} */ -static void php_phpdbg_destroy_bp_symbol(void *brake) /* {{{ */ +static void php_phpdbg_destroy_bp_symbol(zval *brake) /* {{{ */ { - efree((char*)((phpdbg_breaksymbol_t*)brake)->symbol); + efree((char *) ((phpdbg_breaksymbol_t *) Z_PTR_P(brake))->symbol); + efree(Z_PTR_P(brake)); } /* }}} */ -static void php_phpdbg_destroy_bp_opcode(void *brake) /* {{{ */ +static void php_phpdbg_destroy_bp_opcode(zval *brake) /* {{{ */ { - efree((char*)((phpdbg_breakop_t*)brake)->name); + efree((char *) ((phpdbg_breakop_t *) Z_PTR_P(brake))->name); + efree(Z_PTR_P(brake)); } /* }}} */ - -static void php_phpdbg_destroy_bp_methods(void *brake) /* {{{ */ +static void php_phpdbg_destroy_bp_opline(zval *brake) /* {{{ */ { - zend_hash_destroy((HashTable*)brake); + efree(Z_PTR_P(brake)); } /* }}} */ -static void php_phpdbg_destroy_bp_condition(void *data) /* {{{ */ +static void php_phpdbg_destroy_bp_methods(zval *brake) /* {{{ */ { - phpdbg_breakcond_t *brake = (phpdbg_breakcond_t*) data; + zend_hash_destroy(Z_ARRVAL_P(brake)); + efree(Z_ARRVAL_P(brake)); +} /* }}} */ - if (brake) { - if (brake->ops) { - TSRMLS_FETCH(); +static void php_phpdbg_destroy_bp_condition(zval *data) /* {{{ */ +{ + phpdbg_breakcond_t *brake = (phpdbg_breakcond_t *) Z_PTR_P(data); - destroy_op_array( - brake->ops TSRMLS_CC); - efree(brake->ops); - } - efree((char*)brake->code); + if (brake->ops) { + destroy_op_array(brake->ops); + efree(brake->ops); } + efree((char*) brake->code); + efree(brake); } /* }}} */ -static void php_phpdbg_destroy_registered(void *data) /* {{{ */ +static void php_phpdbg_destroy_registered(zval *data) /* {{{ */ { - zend_function *function = (zend_function*) data; - TSRMLS_FETCH(); - - destroy_zend_function( - function TSRMLS_CC); + zend_function *function = (zend_function *) Z_PTR_P(data); + destroy_zend_function(function); } /* }}} */ static PHP_RINIT_FUNCTION(phpdbg) /* {{{ */ { - zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], 8, NULL, php_phpdbg_destroy_bp_file, 0); + zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], 8, NULL, php_phpdbg_destroy_bp_file, 0); + zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], 8, NULL, php_phpdbg_destroy_bp_file, 0); zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], 8, NULL, php_phpdbg_destroy_bp_symbol, 0); zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], 8, NULL, php_phpdbg_destroy_bp_methods, 0); zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], 8, NULL, php_phpdbg_destroy_bp_methods, 0); zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], 8, NULL, php_phpdbg_destroy_bp_methods, 0); - zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], 8, NULL, NULL, 0); + zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], 8, NULL, php_phpdbg_destroy_bp_opline, 0); zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], 8, NULL, php_phpdbg_destroy_bp_opcode, 0); zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], 8, NULL, php_phpdbg_destroy_bp_methods, 0); zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], 8, NULL, php_phpdbg_destroy_bp_condition, 0); @@ -168,6 +213,7 @@ static PHP_RINIT_FUNCTION(phpdbg) /* {{{ */ static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */ { zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE]); + zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING]); zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM]); zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE]); zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE]); @@ -177,43 +223,45 @@ static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */ zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD]); zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_COND]); zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP]); + zend_hash_destroy(&PHPDBG_G(file_sources)); zend_hash_destroy(&PHPDBG_G(seek)); zend_hash_destroy(&PHPDBG_G(registered)); zend_hash_destroy(&PHPDBG_G(watchpoints)); zend_llist_destroy(&PHPDBG_G(watchlist_mem)); if (PHPDBG_G(buffer)) { - efree(PHPDBG_G(buffer)); + free(PHPDBG_G(buffer)); PHPDBG_G(buffer) = NULL; } - + if (PHPDBG_G(exec)) { efree(PHPDBG_G(exec)); PHPDBG_G(exec) = NULL; } - if (PHPDBG_G(prompt)[0]) { - free(PHPDBG_G(prompt)[0]); - } - if (PHPDBG_G(prompt)[1]) { - free(PHPDBG_G(prompt)[1]); - } - - PHPDBG_G(prompt)[0] = NULL; - PHPDBG_G(prompt)[1] = NULL; - if (PHPDBG_G(oplog)) { - fclose( - PHPDBG_G(oplog)); + fclose(PHPDBG_G(oplog)); PHPDBG_G(oplog) = NULL; } if (PHPDBG_G(ops)) { - destroy_op_array(PHPDBG_G(ops) TSRMLS_CC); + destroy_op_array(PHPDBG_G(ops)); efree(PHPDBG_G(ops)); PHPDBG_G(ops) = NULL; } + if (PHPDBG_G(oplog_list)) { + phpdbg_oplog_list *cur = PHPDBG_G(oplog_list); + do { + phpdbg_oplog_list *prev = cur->prev; + efree(cur); + cur = prev; + } while (cur != NULL); + + zend_arena_destroy(PHPDBG_G(oplog_arena)); + PHPDBG_G(oplog_list) = NULL; + } + return SUCCESS; } /* }}} */ @@ -224,99 +272,97 @@ static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */ If the request to set the context fails, boolean false is returned, and an E_WARNING raised */ static PHP_FUNCTION(phpdbg_exec) { - char *exec = NULL; - int exec_len = 0; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &exec, &exec_len) == FAILURE) { + zend_string *exec; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &exec) == FAILURE) { return; } { - struct stat sb; + zend_stat_t sb; zend_bool result = 1; - if (VCWD_STAT(exec, &sb) != FAILURE) { + if (VCWD_STAT(ZSTR_VAL(exec), &sb) != FAILURE) { if (sb.st_mode & (S_IFREG|S_IFLNK)) { if (PHPDBG_G(exec)) { - ZVAL_STRINGL(return_value, PHPDBG_G(exec), PHPDBG_G(exec_len), 1); + ZVAL_STRINGL(return_value, PHPDBG_G(exec), PHPDBG_G(exec_len)); efree(PHPDBG_G(exec)); result = 0; } - PHPDBG_G(exec) = estrndup(exec, exec_len); - PHPDBG_G(exec_len) = exec_len; + PHPDBG_G(exec) = estrndup(ZSTR_VAL(exec), ZSTR_LEN(exec)); + PHPDBG_G(exec_len) = ZSTR_LEN(exec); - if (result) - ZVAL_BOOL(return_value, 1); + if (result) { + ZVAL_TRUE(return_value); + } } else { - zend_error( - E_WARNING, "Failed to set execution context (%s), not a regular file or symlink", exec); - ZVAL_BOOL(return_value, 0); + zend_error(E_WARNING, "Failed to set execution context (%s), not a regular file or symlink", ZSTR_VAL(exec)); + ZVAL_FALSE(return_value); } } else { - zend_error( - E_WARNING, "Failed to set execution context (%s) the file does not exist", exec); + zend_error(E_WARNING, "Failed to set execution context (%s) the file does not exist", ZSTR_VAL(exec)); - ZVAL_BOOL(return_value, 0); + ZVAL_FALSE(return_value); } } } /* }}} */ -/* {{{ proto void phpdbg_break_next() +/* {{{ proto void phpdbg_break() instructs phpdbg to insert a breakpoint at the next opcode */ static PHP_FUNCTION(phpdbg_break_next) { - if (zend_parse_parameters_none() != SUCCESS) { - return; - } else if (EG(current_execute_data) && EG(active_op_array)) { - zend_ulong opline_num = (EG(current_execute_data)->opline - - EG(active_op_array)->opcodes); + zend_execute_data *ex = EG(current_execute_data); - phpdbg_set_breakpoint_opline_ex( - &EG(active_op_array)->opcodes[opline_num+1] TSRMLS_CC); + while (ex && ex->func && !ZEND_USER_CODE(ex->func->type)) { + ex = ex->prev_execute_data; } + + if (zend_parse_parameters_none() == FAILURE || !ex) { + return; + } + + phpdbg_set_breakpoint_opline_ex((phpdbg_opline_ptr_t) ex->opline + 1); } /* }}} */ /* {{{ proto void phpdbg_break_file(string file, integer line) */ static PHP_FUNCTION(phpdbg_break_file) { - char *file = NULL; - int flen = 0; - long line; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &file, &flen, &line) == FAILURE) { - return; - } - - phpdbg_set_breakpoint_file(file, line TSRMLS_CC); + char *file; + size_t flen; + zend_long line; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl", &file, &flen, &line) == FAILURE) { + return; + } + + phpdbg_set_breakpoint_file(file, line); } /* }}} */ /* {{{ proto void phpdbg_break_method(string class, string method) */ static PHP_FUNCTION(phpdbg_break_method) { - char *class = NULL, - *method = NULL; - int clen = 0, - mlen = 0; + char *class = NULL, *method = NULL; + size_t clen = 0, mlen = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &class, &clen, &method, &mlen) == FAILURE) { - return; - } + if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &class, &clen, &method, &mlen) == FAILURE) { + return; + } - phpdbg_set_breakpoint_method(class, method TSRMLS_CC); + phpdbg_set_breakpoint_method(class, method); } /* }}} */ /* {{{ proto void phpdbg_break_function(string function) */ static PHP_FUNCTION(phpdbg_break_function) { - char *function = NULL; - int function_len; + char *function = NULL; + size_t function_len; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &function, &function_len) == FAILURE) { - return; - } + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &function, &function_len) == FAILURE) { + return; + } - phpdbg_set_breakpoint_symbol(function, function_len TSRMLS_CC); + phpdbg_set_breakpoint_symbol(function, function_len); } /* }}} */ /* {{{ proto void phpdbg_clear(void) @@ -324,6 +370,7 @@ static PHP_FUNCTION(phpdbg_break_function) static PHP_FUNCTION(phpdbg_clear) { zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE]); + zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING]); zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM]); zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE]); zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE]); @@ -336,11 +383,11 @@ static PHP_FUNCTION(phpdbg_clear) /* {{{ proto void phpdbg_color(integer element, string color) */ static PHP_FUNCTION(phpdbg_color) { - long element = 0L; - char *color = NULL; - int color_len = 0; + zend_long element; + char *color; + size_t color_len; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &element, &color, &color_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "ls", &element, &color, &color_len) == FAILURE) { return; } @@ -348,7 +395,7 @@ static PHP_FUNCTION(phpdbg_color) case PHPDBG_COLOR_NOTICE: case PHPDBG_COLOR_ERROR: case PHPDBG_COLOR_PROMPT: - phpdbg_set_color_ex(element, color, color_len TSRMLS_CC); + phpdbg_set_color_ex(element, color, color_len); break; default: zend_error(E_ERROR, "phpdbg detected an incorrect color constant"); @@ -359,30 +406,299 @@ static PHP_FUNCTION(phpdbg_color) static PHP_FUNCTION(phpdbg_prompt) { char *prompt = NULL; - int prompt_len = 0; + size_t prompt_len = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &prompt, &prompt_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &prompt, &prompt_len) == FAILURE) { return; } - phpdbg_set_prompt(prompt TSRMLS_CC); + phpdbg_set_prompt(prompt); } /* }}} */ +/* {{{ proto void phpdbg_start_oplog() */ +static PHP_FUNCTION(phpdbg_start_oplog) +{ + phpdbg_oplog_list *prev; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + prev = PHPDBG_G(oplog_list); + + if (!prev) { + PHPDBG_G(oplog_arena) = zend_arena_create(64 * 1024); + + PHPDBG_G(oplog_cur) = ((phpdbg_oplog_entry *) zend_arena_alloc(&PHPDBG_G(oplog_arena), sizeof(phpdbg_oplog_entry))) + 1; + PHPDBG_G(oplog_cur)->next = NULL; + } + + PHPDBG_G(oplog_list) = emalloc(sizeof(phpdbg_oplog_list)); + PHPDBG_G(oplog_list)->prev = prev; + PHPDBG_G(oplog_list)->start = PHPDBG_G(oplog_cur); +} + +static void phpdbg_oplog_fill_executable(zend_op_array *op_array, HashTable *insert_ht, zend_bool by_opcode) { + /* ignore RECV_* opcodes */ + zend_op *cur = op_array->opcodes + op_array->num_args + !!(op_array->fn_flags & ZEND_ACC_VARIADIC); + zend_op *end = op_array->opcodes + op_array->last; + + zend_long insert_idx; + zval zero; + ZVAL_LONG(&zero, 0); + + /* ignore autogenerated return (well, not too precise with finally branches, but that's okay) */ + if (op_array->last >= 1 && (((end - 1)->opcode == ZEND_RETURN || (end - 1)->opcode == ZEND_RETURN_BY_REF || (end - 1)->opcode == ZEND_GENERATOR_RETURN) + && ((op_array->last > 1 && ((end - 2)->opcode == ZEND_RETURN || (end - 2)->opcode == ZEND_RETURN_BY_REF || (end - 2)->opcode == ZEND_GENERATOR_RETURN || (end - 2)->opcode == ZEND_THROW)) + || op_array->function_name == NULL || (end - 1)->extended_value == -1))) { + end--; + } + + for (; cur < end; cur++) { + if (cur->opcode == ZEND_NOP || cur->opcode == ZEND_OP_DATA || cur->opcode == ZEND_FE_FREE || cur->opcode == ZEND_FREE || cur->opcode == ZEND_ASSERT_CHECK || cur->opcode == ZEND_VERIFY_RETURN_TYPE + || cur->opcode == ZEND_DECLARE_CONST || cur->opcode == ZEND_DECLARE_CLASS || cur->opcode == ZEND_DECLARE_INHERITED_CLASS || cur->opcode == ZEND_DECLARE_FUNCTION + || cur->opcode == ZEND_DECLARE_INHERITED_CLASS_DELAYED || cur->opcode == ZEND_VERIFY_ABSTRACT_CLASS || cur->opcode == ZEND_ADD_TRAIT || cur->opcode == ZEND_BIND_TRAITS + || cur->opcode == ZEND_DECLARE_ANON_CLASS || cur->opcode == ZEND_DECLARE_ANON_INHERITED_CLASS || cur->opcode == ZEND_FAST_RET || cur->opcode == ZEND_TICKS + || cur->opcode == ZEND_EXT_STMT || cur->opcode == ZEND_EXT_FCALL_BEGIN || cur->opcode == ZEND_EXT_FCALL_END || cur->opcode == ZEND_EXT_NOP || cur->opcode == ZEND_BIND_GLOBAL) { + continue; + } + + if (by_opcode) { + insert_idx = cur - op_array->opcodes; + } else { + insert_idx = cur->lineno; + } + + if (cur->opcode == ZEND_NEW && (cur + 1)->opcode == ZEND_DO_FCALL) { + cur++; + } + + zend_hash_index_update(insert_ht, insert_idx, &zero); + } +} + +static inline HashTable* phpdbg_add_empty_array(HashTable *ht, zend_string *name) { + zval *ht_zv = zend_hash_find(ht, name); + if (!ht_zv) { + zval zv; + array_init(&zv); + ht_zv = zend_hash_add_new(ht, name, &zv); + } + return Z_ARR_P(ht_zv); +} + +/* {{{ proto void phpdbg_end_oplog() */ +static PHP_FUNCTION(phpdbg_get_executable) +{ + HashTable *options = NULL; + zval *option_buffer; + zend_bool by_function = 0; + zend_bool by_opcode = 0; + HashTable *insert_ht; + + zend_function *func; + zend_class_entry *ce; + zend_string *name; + HashTable *files = &PHPDBG_G(file_sources); + HashTable files_tmp; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|H", &options) == FAILURE) { + return; + } + + if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("functions")))) { + by_function = zend_is_true(option_buffer); + } + + if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("opcodes")))) { + if (by_function) { + by_opcode = zend_is_true(option_buffer); + } + } + + if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("files")))) { + ZVAL_DEREF(option_buffer); + if (Z_TYPE_P(option_buffer) == IS_ARRAY && zend_hash_num_elements(Z_ARR_P(option_buffer)) > 0) { + zval *filename; + + files = &files_tmp; + zend_hash_init(files, 0, NULL, NULL, 0); + + ZEND_HASH_FOREACH_VAL(Z_ARR_P(option_buffer), filename) { + zend_hash_add_empty_element(files, zval_get_string(filename)); + } ZEND_HASH_FOREACH_END(); + } else { + GC_REFCOUNT(files)++; + } + } else { + GC_REFCOUNT(files)++; + } + + array_init(return_value); + + ZEND_HASH_FOREACH_STR_KEY_PTR(EG(function_table), name, func) { + if (func->type == ZEND_USER_FUNCTION) { + if (zend_hash_exists(files, func->op_array.filename)) { + insert_ht = phpdbg_add_empty_array(Z_ARR_P(return_value), func->op_array.filename); + + if (by_function) { + insert_ht = phpdbg_add_empty_array(insert_ht, name); + } + + phpdbg_oplog_fill_executable(&func->op_array, insert_ht, by_opcode); + } + } + } ZEND_HASH_FOREACH_END(); + + ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), name, ce) { + if (ce->type == ZEND_USER_CLASS) { + if (zend_hash_exists(files, ce->info.user.filename)) { + ZEND_HASH_FOREACH_PTR(&ce->function_table, func) { + if (func->type == ZEND_USER_FUNCTION && zend_hash_exists(files, func->op_array.filename)) { + insert_ht = phpdbg_add_empty_array(Z_ARR_P(return_value), func->op_array.filename); + + if (by_function) { + zend_string *fn_name = strpprintf(ZSTR_LEN(name) + ZSTR_LEN(func->op_array.function_name) + 2, "%.*s::%.*s", (int) ZSTR_LEN(name), ZSTR_VAL(name), (int) ZSTR_LEN(func->op_array.function_name), ZSTR_VAL(func->op_array.function_name)); + insert_ht = phpdbg_add_empty_array(insert_ht, fn_name); + zend_string_release(fn_name); + } + + phpdbg_oplog_fill_executable(&func->op_array, insert_ht, by_opcode); + } + } ZEND_HASH_FOREACH_END(); + } + } + } ZEND_HASH_FOREACH_END(); + + ZEND_HASH_FOREACH_STR_KEY(files, name) { + phpdbg_file_source *source = zend_hash_find_ptr(&PHPDBG_G(file_sources), name); + if (source) { + phpdbg_oplog_fill_executable( + &source->op_array, + phpdbg_add_empty_array(Z_ARR_P(return_value), source->op_array.filename), + by_opcode); + } + } ZEND_HASH_FOREACH_END(); + + if (!--GC_REFCOUNT(files)) { + zend_hash_destroy(files); + } +} + +/* {{{ proto void phpdbg_end_oplog() */ +static PHP_FUNCTION(phpdbg_end_oplog) +{ + phpdbg_oplog_entry *cur; + phpdbg_oplog_list *prev; + + HashTable *options = NULL; + zval *option_buffer; + zend_bool by_function = 0; + zend_bool by_opcode = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|H", &options) == FAILURE) { + return; + } + + if (!PHPDBG_G(oplog_list)) { + zend_error(E_WARNING, "Can not end an oplog without starting it"); + return; + } + + cur = PHPDBG_G(oplog_list)->start; + prev = PHPDBG_G(oplog_list)->prev; + + efree(PHPDBG_G(oplog_list)); + PHPDBG_G(oplog_list) = prev; + + if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("functions")))) { + by_function = zend_is_true(option_buffer); + } + + if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("opcodes")))) { + if (by_function) { + by_opcode = zend_is_true(option_buffer); + } + } + + array_init(return_value); + + { + zend_string *last_file = NULL; + HashTable *file_ht; + zend_string *last_function = (void *)~(uintptr_t)0; + zend_class_entry *last_scope = NULL; + + HashTable *insert_ht; + zend_long insert_idx; + + do { + zval zero; + ZVAL_LONG(&zero, 0); + + if (cur->filename != last_file) { + last_file = cur->filename; + file_ht = insert_ht = phpdbg_add_empty_array(Z_ARR_P(return_value), last_file); + } + + if (by_function) { + if (cur->function_name == NULL) { + if (last_function != NULL) { + insert_ht = file_ht; + } + last_function = NULL; + } else if (cur->function_name != last_function || cur->scope != last_scope) { + zend_string *fn_name; + last_function = cur->function_name; + last_scope = cur->scope; + if (last_scope == NULL) { + fn_name = zend_string_copy(last_function); + } else { + fn_name = strpprintf(ZSTR_LEN(last_function) + ZSTR_LEN(last_scope->name) + 2, "%.*s::%.*s", (int) ZSTR_LEN(last_scope->name), ZSTR_VAL(last_scope->name), (int) ZSTR_LEN(last_function), ZSTR_VAL(last_function)); + } + insert_ht = phpdbg_add_empty_array(Z_ARR_P(return_value), fn_name); + zend_string_release(fn_name); + } + } + + if (by_opcode) { + insert_idx = cur->op - cur->opcodes; + } else { + insert_idx = cur->op->lineno; + } + + { + zval *num = zend_hash_index_find(insert_ht, insert_idx); + if (!num) { + num = zend_hash_index_add_new(insert_ht, insert_idx, &zero); + } + Z_LVAL_P(num)++; + } + + cur = cur->next; + } while (cur != NULL); + } + + if (!prev) { + zend_arena_destroy(PHPDBG_G(oplog_arena)); + } +} + ZEND_BEGIN_ARG_INFO_EX(phpdbg_break_next_arginfo, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(phpdbg_break_file_arginfo, 0, 0, 2) - ZEND_ARG_INFO(0, file) - ZEND_ARG_INFO(0, line) + ZEND_ARG_INFO(0, file) + ZEND_ARG_INFO(0, line) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(phpdbg_break_method_arginfo, 0, 0, 2) - ZEND_ARG_INFO(0, class) - ZEND_ARG_INFO(0, method) + ZEND_ARG_INFO(0, class) + ZEND_ARG_INFO(0, method) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(phpdbg_break_function_arginfo, 0, 0, 1) - ZEND_ARG_INFO(0, function) + ZEND_ARG_INFO(0, function) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(phpdbg_color_arginfo, 0, 0, 0) @@ -401,6 +717,17 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(phpdbg_clear_arginfo, 0, 0, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(phpdbg_start_oplog_arginfo, 0, 0, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(phpdbg_end_oplog_arginfo, 0, 0, 0) + ZEND_ARG_INFO(0, options) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(phpdbg_get_executable_arginfo, 0, 0, 0) + ZEND_ARG_INFO(0, options) +ZEND_END_ARG_INFO() + zend_function_entry phpdbg_user_functions[] = { PHP_FE(phpdbg_clear, phpdbg_clear_arginfo) PHP_FE(phpdbg_break_next, phpdbg_break_next_arginfo) @@ -410,6 +737,9 @@ zend_function_entry phpdbg_user_functions[] = { PHP_FE(phpdbg_exec, phpdbg_exec_arginfo) PHP_FE(phpdbg_color, phpdbg_color_arginfo) PHP_FE(phpdbg_prompt, phpdbg_prompt_arginfo) + PHP_FE(phpdbg_start_oplog, phpdbg_start_oplog_arginfo) + PHP_FE(phpdbg_end_oplog, phpdbg_end_oplog_arginfo) + PHP_FE(phpdbg_get_executable, phpdbg_get_executable_arginfo) #ifdef PHP_FE_END PHP_FE_END #else @@ -441,18 +771,18 @@ static inline int php_sapi_phpdbg_module_startup(sapi_module_struct *module) /* return SUCCESS; } /* }}} */ -static char* php_sapi_phpdbg_read_cookies(TSRMLS_D) /* {{{ */ +static char* php_sapi_phpdbg_read_cookies(void) /* {{{ */ { return NULL; } /* }}} */ -static int php_sapi_phpdbg_header_handler(sapi_header_struct *h, sapi_header_op_enum op, sapi_headers_struct *s TSRMLS_DC) /* {{{ */ +static int php_sapi_phpdbg_header_handler(sapi_header_struct *h, sapi_header_op_enum op, sapi_headers_struct *s) /* {{{ */ { return 0; } /* }}} */ -static int php_sapi_phpdbg_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) /* {{{ */ +static int php_sapi_phpdbg_send_headers(sapi_headers_struct *sapi_headers) /* {{{ */ { /* We do nothing here, this function is needed to prevent that the fallback * header handling is called. */ @@ -460,18 +790,27 @@ static int php_sapi_phpdbg_send_headers(sapi_headers_struct *sapi_headers TSRMLS } /* }}} */ -static void php_sapi_phpdbg_send_header(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC) /* {{{ */ +static void php_sapi_phpdbg_send_header(sapi_header_struct *sapi_header, void *server_context) /* {{{ */ { } /* }}} */ -static void php_sapi_phpdbg_log_message(char *message TSRMLS_DC) /* {{{ */ +static void php_sapi_phpdbg_log_message(char *message) /* {{{ */ { /* - * We must not request TSRM before being boot + * We must not request TSRM before being booted */ if (phpdbg_booted) { - phpdbg_error("%s", message); + if (PHPDBG_G(flags) & PHPDBG_IN_EVAL) { + phpdbg_error("eval", "msg=\"%s\"", "%s", message); + return; + } + + phpdbg_error("php", "msg=\"%s\"", "%s", message); + + if (PHPDBG_G(flags) & PHPDBG_PREVENT_INTERACTIVE) { + return; + } switch (PG(last_error_type)) { case E_ERROR: @@ -479,123 +818,137 @@ static void php_sapi_phpdbg_log_message(char *message TSRMLS_DC) /* {{{ */ case E_COMPILE_ERROR: case E_USER_ERROR: case E_PARSE: - case E_RECOVERABLE_ERROR: - if (!(PHPDBG_G(flags) & PHPDBG_IN_EVAL)) { - phpdbg_list_file( - zend_get_executed_filename(TSRMLS_C), - 3, - zend_get_executed_lineno(TSRMLS_C)-1, - zend_get_executed_lineno(TSRMLS_C) - TSRMLS_CC - ); + case E_RECOVERABLE_ERROR: { + const char *file_char = zend_get_executed_filename(); + zend_string *file = zend_string_init(file_char, strlen(file_char), 0); + phpdbg_list_file(file, 3, zend_get_executed_lineno() - 1, zend_get_executed_lineno()); + zend_string_release(file); + + if (!phpdbg_fully_started) { + return; } do { - switch (phpdbg_interactive(TSRMLS_C)) { + switch (phpdbg_interactive(1)) { case PHPDBG_LEAVE: case PHPDBG_FINISH: case PHPDBG_UNTIL: case PHPDBG_NEXT: return; } - } while (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)); - + } while (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)); + } } - } else fprintf(stdout, "%s\n", message); + } else { + fprintf(stdout, "%s\n", message); + } } /* }}} */ -static int php_sapi_phpdbg_deactivate(TSRMLS_D) /* {{{ */ +static int php_sapi_phpdbg_deactivate(void) /* {{{ */ { fflush(stdout); - if(SG(request_info).argv0) { + if (SG(request_info).argv0) { free(SG(request_info).argv0); SG(request_info).argv0 = NULL; } + return SUCCESS; } /* }}} */ -static void php_sapi_phpdbg_register_vars(zval *track_vars_array TSRMLS_DC) /* {{{ */ +static void php_sapi_phpdbg_register_vars(zval *track_vars_array) /* {{{ */ { - unsigned int len; - char *docroot = ""; + size_t len; + char *docroot = ""; /* In phpdbg mode, we consider the environment to be a part of the server variables */ - php_import_environment_variables(track_vars_array TSRMLS_CC); + php_import_environment_variables(track_vars_array); if (PHPDBG_G(exec)) { len = PHPDBG_G(exec_len); - if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", - &PHPDBG_G(exec), PHPDBG_G(exec_len), &len TSRMLS_CC)) { - php_register_variable("PHP_SELF", PHPDBG_G(exec), - track_vars_array TSRMLS_CC); + if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &PHPDBG_G(exec), PHPDBG_G(exec_len), &len)) { + php_register_variable("PHP_SELF", PHPDBG_G(exec), track_vars_array); } - if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_NAME", - &PHPDBG_G(exec), PHPDBG_G(exec_len), &len TSRMLS_CC)) { - php_register_variable("SCRIPT_NAME", PHPDBG_G(exec), - track_vars_array TSRMLS_CC); + if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_NAME", &PHPDBG_G(exec), PHPDBG_G(exec_len), &len)) { + php_register_variable("SCRIPT_NAME", PHPDBG_G(exec), track_vars_array); } - if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_FILENAME", - &PHPDBG_G(exec), PHPDBG_G(exec_len), &len TSRMLS_CC)) { - php_register_variable("SCRIPT_FILENAME", PHPDBG_G(exec), - track_vars_array TSRMLS_CC); + if (sapi_module.input_filter(PARSE_SERVER, "SCRIPT_FILENAME", &PHPDBG_G(exec), PHPDBG_G(exec_len), &len)) { + php_register_variable("SCRIPT_FILENAME", PHPDBG_G(exec), track_vars_array); } - if (sapi_module.input_filter(PARSE_SERVER, "PATH_TRANSLATED", - &PHPDBG_G(exec), PHPDBG_G(exec_len), &len TSRMLS_CC)) { - php_register_variable("PATH_TRANSLATED", PHPDBG_G(exec), - track_vars_array TSRMLS_CC); + if (sapi_module.input_filter(PARSE_SERVER, "PATH_TRANSLATED", &PHPDBG_G(exec), PHPDBG_G(exec_len), &len)) { + php_register_variable("PATH_TRANSLATED", PHPDBG_G(exec), track_vars_array); } } - /* any old docroot will doo */ - len = 0U; - if (sapi_module.input_filter(PARSE_SERVER, "DOCUMENT_ROOT", - &docroot, len, &len TSRMLS_CC)) { - php_register_variable("DOCUMENT_ROOT", docroot, track_vars_array TSRMLS_CC); + /* any old docroot will do */ + len = 0; + if (sapi_module.input_filter(PARSE_SERVER, "DOCUMENT_ROOT", &docroot, len, &len)) { + php_register_variable("DOCUMENT_ROOT", docroot, track_vars_array); } } /* }}} */ -static inline int php_sapi_phpdbg_ub_write(const char *message, unsigned int length TSRMLS_DC) /* {{{ */ +static inline size_t php_sapi_phpdbg_ub_write(const char *message, size_t length) /* {{{ */ { - return phpdbg_write("%s", message); + if (PHPDBG_G(socket_fd) != -1 && !(PHPDBG_G(flags) & PHPDBG_IS_INTERACTIVE)) { + send(PHPDBG_G(socket_fd), message, length, 0); + } + return phpdbg_script(P_STDOUT, "%.*s", (int) length, message); } /* }}} */ -#if PHP_VERSION_ID >= 50700 -static inline void php_sapi_phpdbg_flush(void *context TSRMLS_DC) /* {{{ */ -{ -#else +/* beginning of struct, see main/streams/plain_wrapper.c line 111 */ +typedef struct { + FILE *file; + int fd; +} php_stdio_stream_data; + +static size_t phpdbg_stdiop_write(php_stream *stream, const char *buf, size_t count) { + php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract; + + while (data->fd >= 0) { + struct stat stat[3]; + memset(stat, 0, sizeof(stat)); + if (((fstat(fileno(stderr), &stat[2]) < 0) & (fstat(fileno(stdout), &stat[0]) < 0)) | (fstat(data->fd, &stat[1]) < 0)) { + break; + } + + if (stat[0].st_dev == stat[1].st_dev && stat[0].st_ino == stat[1].st_ino) { + phpdbg_script(P_STDOUT, "%.*s", (int) count, buf); + return count; + } + if (stat[2].st_dev == stat[1].st_dev && stat[2].st_ino == stat[1].st_ino) { + phpdbg_script_ex(PHPDBG_G(io)[PHPDBG_STDERR].fd, P_STDERR, "%.*s", (int) count, buf); + return count; + } + break; + } + + return PHPDBG_G(php_stdiop_write)(stream, buf, count); +} + static inline void php_sapi_phpdbg_flush(void *context) /* {{{ */ { - TSRMLS_FETCH(); -#endif - - fflush(PHPDBG_G(io)[PHPDBG_STDOUT]); + if (!phpdbg_active_sigsafe_mem()) { + fflush(PHPDBG_G(io)[PHPDBG_STDOUT].ptr); + } } /* }}} */ /* copied from sapi/cli/php_cli.c cli_register_file_handles */ -static void phpdbg_register_file_handles(TSRMLS_D) /* {{{ */ +static void phpdbg_register_file_handles(void) /* {{{ */ { - zval *zin, *zout, *zerr; + zval zin, zout, zerr; php_stream *s_in, *s_out, *s_err; php_stream_context *sc_in=NULL, *sc_out=NULL, *sc_err=NULL; zend_constant ic, oc, ec; - MAKE_STD_ZVAL(zin); - MAKE_STD_ZVAL(zout); - MAKE_STD_ZVAL(zerr); - s_in = php_stream_open_wrapper_ex("php://stdin", "rb", 0, NULL, sc_in); s_out = php_stream_open_wrapper_ex("php://stdout", "wb", 0, NULL, sc_out); s_err = php_stream_open_wrapper_ex("php://stderr", "wb", 0, NULL, sc_err); if (s_in==NULL || s_out==NULL || s_err==NULL) { - FREE_ZVAL(zin); - FREE_ZVAL(zout); - FREE_ZVAL(zerr); if (s_in) php_stream_close(s_in); if (s_out) php_stream_close(s_out); if (s_err) php_stream_close(s_err); @@ -608,34 +961,27 @@ static void phpdbg_register_file_handles(TSRMLS_D) /* {{{ */ s_err->flags |= PHP_STREAM_FLAG_NO_CLOSE; #endif - php_stream_to_zval(s_in, zin); - php_stream_to_zval(s_out, zout); - php_stream_to_zval(s_err, zerr); + php_stream_to_zval(s_in, &zin); + php_stream_to_zval(s_out, &zout); + php_stream_to_zval(s_err, &zerr); - ic.value = *zin; + ic.value = zin; ic.flags = CONST_CS; - ic.name = zend_strndup(ZEND_STRL("STDIN")); - ic.name_len = sizeof("STDIN"); + ic.name = zend_string_init(ZEND_STRL("STDIN"), 0); ic.module_number = 0; - zend_register_constant(&ic TSRMLS_CC); + zend_register_constant(&ic); - oc.value = *zout; + oc.value = zout; oc.flags = CONST_CS; - oc.name = zend_strndup(ZEND_STRL("STDOUT")); - oc.name_len = sizeof("STDOUT"); + oc.name = zend_string_init(ZEND_STRL("STDOUT"), 0); oc.module_number = 0; - zend_register_constant(&oc TSRMLS_CC); + zend_register_constant(&oc); - ec.value = *zerr; + ec.value = zerr; ec.flags = CONST_CS; - ec.name = zend_strndup(ZEND_STRL("STDERR")); - ec.name_len = sizeof("STDERR"); + ec.name = zend_string_init(ZEND_STRL("STDERR"), 0); ec.module_number = 0; - zend_register_constant(&ec TSRMLS_CC); - - FREE_ZVAL(zin); - FREE_ZVAL(zout); - FREE_ZVAL(zerr); + zend_register_constant(&ec); } /* }}} */ @@ -681,18 +1027,21 @@ const opt_struct OPTIONS[] = { /* {{{ */ /* phpdbg options */ {'q', 0, "no banner"}, {'v', 0, "disable quietness"}, - {'s', 0, "enable stepping"}, {'b', 0, "boring colours"}, {'i', 1, "specify init"}, {'I', 0, "ignore init"}, {'O', 1, "opline log"}, {'r', 0, "run"}, + {'e', 0, "generate ext_stmt opcodes"}, {'E', 0, "step-through-eval"}, {'S', 1, "sapi-name"}, #ifndef _WIN32 {'l', 1, "listen"}, {'a', 1, "address-or-any"}, #endif + {'x', 0, "xml output"}, + {'p', 2, "show opcodes"}, + {'h', 0, "help"}, {'V', 0, "version"}, {'-', 0, NULL} }; /* }}} */ @@ -706,14 +1055,12 @@ const char phpdbg_ini_hardcoded[] = "max_execution_time=0\n" "max_input_time=-1\n" "error_log=\n" -"output_buffering=off\0"; +"output_buffering=off\n\0"; /* overwriteable ini defaults must be set in phpdbg_ini_defaults() */ #define INI_DEFAULT(name, value) \ - Z_SET_REFCOUNT(tmp, 0); \ - Z_UNSET_ISREF(tmp); \ - ZVAL_STRINGL(&tmp, zend_strndup(value, sizeof(value)-1), sizeof(value)-1, 0); \ - zend_hash_update(configuration_hash, name, sizeof(name), &tmp, sizeof(zval), NULL); + ZVAL_STRINGL(&tmp, value, sizeof(value) - 1); \ + zend_hash_str_update(configuration_hash, name, sizeof(name) - 1, &tmp); void phpdbg_ini_defaults(HashTable *configuration_hash) /* {{{ */ { @@ -721,199 +1068,181 @@ void phpdbg_ini_defaults(HashTable *configuration_hash) /* {{{ */ INI_DEFAULT("report_zend_debug", "0"); } /* }}} */ -static void phpdbg_welcome(zend_bool cleaning TSRMLS_DC) /* {{{ */ +static void phpdbg_welcome(zend_bool cleaning) /* {{{ */ { /* print blurb */ if (!cleaning) { - phpdbg_notice("Welcome to phpdbg, the interactive PHP debugger, v%s", - PHPDBG_VERSION); - phpdbg_writeln("To get help using phpdbg type \"help\" and press enter"); - phpdbg_notice("Please report bugs to <%s>", PHPDBG_ISSUES); - } else { - phpdbg_notice("Clean Execution Environment"); + phpdbg_xml("<intros>"); + phpdbg_notice("intro", "version=\"%s\"", "Welcome to phpdbg, the interactive PHP debugger, v%s", PHPDBG_VERSION); + phpdbg_writeln("intro", "help=\"help\"", "To get help using phpdbg type \"help\" and press enter"); + phpdbg_notice("intro", "report=\"%s\"", "Please report bugs to <%s>", PHPDBG_ISSUES); + phpdbg_xml("</intros>"); + } else if (phpdbg_startup_run == 0) { + if (!(PHPDBG_G(flags) & PHPDBG_WRITE_XML)) { + phpdbg_notice(NULL, NULL, "Clean Execution Environment"); + } - phpdbg_writeln("Classes\t\t\t%d", zend_hash_num_elements(EG(class_table))); - phpdbg_writeln("Functions\t\t%d", zend_hash_num_elements(EG(function_table))); - phpdbg_writeln("Constants\t\t%d", zend_hash_num_elements(EG(zend_constants))); - phpdbg_writeln("Includes\t\t%d", zend_hash_num_elements(&EG(included_files))); + phpdbg_write("cleaninfo", "classes=\"%d\" functions=\"%d\" constants=\"%d\" includes=\"%d\"", + "Classes %d\n" + "Functions %d\n" + "Constants %d\n" + "Includes %d\n", + zend_hash_num_elements(EG(class_table)), + zend_hash_num_elements(EG(function_table)), + zend_hash_num_elements(EG(zend_constants)), + zend_hash_num_elements(&EG(included_files))); } } /* }}} */ static inline void phpdbg_sigint_handler(int signo) /* {{{ */ { - TSRMLS_FETCH(); - if (EG(in_execution)) { - /* set signalled only when not interactive */ - if (!(PHPDBG_G(flags) & PHPDBG_IS_INTERACTIVE)) { - PHPDBG_G(flags) |= PHPDBG_IS_SIGNALED; - } - } else { + if (PHPDBG_G(flags) & PHPDBG_IS_INTERACTIVE) { /* we quit remote consoles on recv SIGINT */ if (PHPDBG_G(flags) & PHPDBG_IS_REMOTE) { - PHPDBG_G(flags) |= PHPDBG_IS_QUITTING; + PHPDBG_G(flags) |= PHPDBG_IS_STOPPING; zend_bailout(); } - } -} /* }}} */ - -#ifndef _WIN32 -int phpdbg_open_socket(const char *interface, short port) /* {{{ */ -{ - int fd = socket(AF_INET, SOCK_STREAM, 0); - - switch (fd) { - case -1: - return -1; - - default: { - int reuse = 1; - - switch (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*) &reuse, sizeof(reuse))) { - case -1: - close(fd); - return -2; - - default: { - struct sockaddr_in address; - - memset(&address, 0, sizeof(address)); - - address.sin_port = htons(port); - address.sin_family = AF_INET; + } else { + /* set signalled only when not interactive */ + if (PHPDBG_G(flags) & PHPDBG_IS_SIGNALED) { + char mem[PHPDBG_SIGSAFE_MEM_SIZE + 1]; - if ((*interface == '*')) { - address.sin_addr.s_addr = htonl(INADDR_ANY); - } else if (!inet_pton(AF_INET, interface, &address.sin_addr)) { - close(fd); - return -3; - } + phpdbg_set_sigsafe_mem(mem); + zend_try { + phpdbg_force_interruption(); + } zend_end_try() + phpdbg_clear_sigsafe_mem(); - switch (bind(fd, (struct sockaddr *)&address, sizeof(address))) { - case -1: - close(fd); - return -4; + PHPDBG_G(flags) &= ~PHPDBG_IS_SIGNALED; - default: { - listen(fd, 5); - } - } - } + if (PHPDBG_G(flags) & PHPDBG_IS_STOPPING) { + zend_bailout(); } + } else { + PHPDBG_G(flags) |= PHPDBG_IS_SIGNALED; } } - - return fd; } /* }}} */ -static inline void phpdbg_close_sockets(int (*socket)[2], FILE *streams[2]) /* {{{ */ -{ - if ((*socket)[0] >= 0) { - shutdown( - (*socket)[0], SHUT_RDWR); - close((*socket)[0]); +static void phpdbg_remote_close(int socket, FILE *stream) { + if (socket >= 0) { + phpdbg_close_socket(socket); } - if (streams[0]) { - fclose(streams[0]); + if (stream) { + fclose(stream); } +} - if ((*socket)[1] >= 0) { - shutdown( - (*socket)[1], SHUT_RDWR); - close((*socket)[1]); - } +/* don't inline this, want to debug it easily, will inline when done */ +static int phpdbg_remote_init(const char* address, unsigned short port, int server, int *socket, FILE **stream) { + phpdbg_remote_close(*socket, *stream); + + if (server < 0) { + phpdbg_rlog(fileno(stderr), "Initializing connection on %s:%u failed", address, port); - if (streams[1]) { - fclose(streams[1]); + return FAILURE; } -} /* }}} */ -/* don't inline this, want to debug it easily, will inline when done */ + phpdbg_rlog(fileno(stderr), "accepting connections on %s:%u", address, port); + { + struct sockaddr_storage address; + socklen_t size = sizeof(address); + char buffer[20] = {0}; + /* XXX error checks */ + memset(&address, 0, size); + *socket = accept(server, (struct sockaddr *) &address, &size); + inet_ntop(AF_INET, &(((struct sockaddr_in *)&address)->sin_addr), buffer, sizeof(buffer)); -int phpdbg_open_sockets(char *address, int port[2], int (*listen)[2], int (*socket)[2], FILE* streams[2]) /* {{{ */ -{ - if (((*listen)[0]) < 0 && ((*listen)[1]) < 0) { - ((*listen)[0]) = phpdbg_open_socket(address, (short)port[0]); - ((*listen)[1]) = phpdbg_open_socket(address, (short)port[1]); + phpdbg_rlog(fileno(stderr), "connection established from %s", buffer); } - streams[0] = NULL; - streams[1] = NULL; +#ifndef _WIN32 + dup2(*socket, fileno(stdout)); + dup2(*socket, fileno(stdin)); - if ((*listen)[0] < 0 || (*listen)[1] < 0) { - if ((*listen)[0] < 0) { - phpdbg_rlog(stderr, - "console failed to initialize (stdin) on %s:%d", address, port[0]); - } + setbuf(stdout, NULL); - if ((*listen)[1] < 0) { - phpdbg_rlog(stderr, - "console failed to initialize (stdout) on %s:%d", address, port[1]); - } + *stream = fdopen(*socket, "r+"); - if ((*listen)[0] >= 0) { - close((*listen)[0]); - } + phpdbg_set_async_io(*socket); +#endif + return SUCCESS; +} - if ((*listen)[1] >= 0) { - close((*listen)[1]); - } +#ifndef _WIN32 +/* This function *strictly* assumes that SIGIO is *only* used on the remote connection stream */ +void phpdbg_sigio_handler(int sig, siginfo_t *info, void *context) /* {{{ */ +{ + int flags; + size_t newlen; + size_t i/*, last_nl*/; - return FAILURE; - } +// if (!(info->si_band & POLLIN)) { +// return; /* Not interested in writeablility etc., just interested in incoming data */ +// } - phpdbg_close_sockets(socket, streams); + /* only non-blocking reading, avoid non-blocking writing */ + flags = fcntl(PHPDBG_G(io)[PHPDBG_STDIN].fd, F_GETFL, 0); + fcntl(PHPDBG_G(io)[PHPDBG_STDIN].fd, F_SETFL, flags | O_NONBLOCK); - phpdbg_rlog(stderr, - "accepting connections on %s:%d/%d", address, port[0], port[1]); - { - struct sockaddr_in address; - socklen_t size = sizeof(address); - char buffer[20] = {0}; - - { - memset(&address, 0, size); - (*socket)[0] = accept( - (*listen)[0], (struct sockaddr *) &address, &size); - inet_ntop(AF_INET, &address.sin_addr, buffer, sizeof(buffer)); + do { + char mem[PHPDBG_SIGSAFE_MEM_SIZE + 1]; + size_t off = 0; - phpdbg_rlog(stderr, "connection (stdin) from %s", buffer); + if ((newlen = recv(PHPDBG_G(io)[PHPDBG_STDIN].fd, mem, PHPDBG_SIGSAFE_MEM_SIZE, MSG_PEEK)) == (size_t) -1) { + break; } + for (i = 0; i < newlen; i++) { + switch (mem[off + i]) { + case '\x03': /* ^C char */ + if (PHPDBG_G(flags) & PHPDBG_IS_INTERACTIVE) { + break; /* or quit ??? */ + } + if (PHPDBG_G(flags) & PHPDBG_IS_SIGNALED) { + phpdbg_set_sigsafe_mem(mem); + zend_try { + phpdbg_force_interruption(); + } zend_end_try(); + phpdbg_clear_sigsafe_mem(); - { - memset(&address, 0, size); - (*socket)[1] = accept( - (*listen)[1], (struct sockaddr *) &address, &size); - inet_ntop(AF_INET, &address.sin_addr, buffer, sizeof(buffer)); + PHPDBG_G(flags) &= ~PHPDBG_IS_SIGNALED; - phpdbg_rlog(stderr, "connection (stdout) from %s", buffer); + if (PHPDBG_G(flags) & PHPDBG_IS_STOPPING) { + zend_bailout(); + } + } else if (!(PHPDBG_G(flags) & PHPDBG_IS_INTERACTIVE)) { + PHPDBG_G(flags) |= PHPDBG_IS_SIGNALED; + } + break; +/* case '\n': + zend_llist_add_element(PHPDBG_G(stdin), strndup() + last_nl = PHPDBG_G(stdin_buf).len + i; + break; +*/ } } - } + off += i; + } while (0); - dup2((*socket)[0], fileno(stdin)); - dup2((*socket)[1], fileno(stdout)); - - setbuf(stdout, NULL); - streams[0] = fdopen((*socket)[0], "r"); - streams[1] = fdopen((*socket)[1], "w"); - - return SUCCESS; + fcntl(PHPDBG_G(io)[PHPDBG_STDIN].fd, F_SETFL, flags); } /* }}} */ void phpdbg_signal_handler(int sig, siginfo_t *info, void *context) /* {{{ */ { int is_handled = FAILURE; - TSRMLS_FETCH(); switch (sig) { case SIGBUS: case SIGSEGV: - is_handled = phpdbg_watchpoint_segfault_handler(info, context TSRMLS_CC); + if (PHPDBG_G(sigsegv_bailout)) { + LONGJMP(*PHPDBG_G(sigsegv_bailout), FAILURE); + } + is_handled = phpdbg_watchpoint_segfault_handler(info, context); if (is_handled == FAILURE) { #ifdef ZEND_SIGNALS - zend_sigaction(sig, &PHPDBG_G(old_sigsegv_signal), NULL TSRMLS_CC); + zend_sigaction(sig, &PHPDBG_G(old_sigsegv_signal), NULL); #else sigaction(sig, &PHPDBG_G(old_sigsegv_signal), NULL); #endif @@ -924,31 +1253,32 @@ void phpdbg_signal_handler(int sig, siginfo_t *info, void *context) /* {{{ */ } /* }}} */ #endif -static inline zend_mm_heap *phpdbg_mm_get_heap() /* {{{ */ +void phpdbg_sighup_handler(int sig) /* {{{ */ { - zend_mm_heap *mm_heap; - - TSRMLS_FETCH(); - - mm_heap = zend_mm_set_heap(NULL TSRMLS_CC); - zend_mm_set_heap(mm_heap TSRMLS_CC); - - return mm_heap; + exit(0); } /* }}} */ -void *phpdbg_malloc_wrapper(size_t size) /* {{{ */ +void *phpdbg_malloc_wrapper(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */ { - return zend_mm_alloc(phpdbg_mm_get_heap(), size); + return _zend_mm_alloc(zend_mm_get_heap(), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); } /* }}} */ -void phpdbg_free_wrapper(void *p) /* {{{ */ +void phpdbg_free_wrapper(void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */ { - zend_mm_free(phpdbg_mm_get_heap(), p); + zend_mm_heap *heap = zend_mm_get_heap(); + if (UNEXPECTED(heap == p)) { + /* TODO: heap maybe allocated by mmap(zend_mm_init) or malloc(USE_ZEND_ALLOC=0) + * let's prevent it from segfault for now + */ + } else { + phpdbg_watch_efree(p); + return _zend_mm_free(heap, p ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } } /* }}} */ -void *phpdbg_realloc_wrapper(void *ptr, size_t size) /* {{{ */ +void *phpdbg_realloc_wrapper(void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) /* {{{ */ { - return zend_mm_realloc(phpdbg_mm_get_heap(), ptr, size); + return _zend_mm_realloc(zend_mm_get_heap(), ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); } /* }}} */ int main(int argc, char **argv) /* {{{ */ @@ -961,53 +1291,42 @@ int main(int argc, char **argv) /* {{{ */ zend_ulong zend_extensions_len = 0L; zend_bool ini_ignore; char *ini_override; - char *exec; - size_t exec_len; + char *exec = NULL; char *init_file; size_t init_file_len; zend_bool init_file_default; char *oplog_file; size_t oplog_file_len; - zend_ulong flags; + uint64_t flags; char *php_optarg; int php_optind, opt, show_banner = 1; - long cleaning = 0; + long cleaning = -1; + volatile zend_bool quit_immediately = 0; /* somehow some gcc release builds will play a bit around with order in combination with setjmp..., hence volatile */ zend_bool remote = 0; - int run = 0; - int step = 0; - -#ifdef _WIN32 - char *bp_tmp_file = NULL; -#else - char bp_tmp_file[] = "/tmp/phpdbg.XXXXXX"; -#endif - -#ifndef _WIN32 + zend_phpdbg_globals *settings = NULL; + char *bp_tmp = NULL; char *address; - int listen[2]; - int server[2]; - int socket[2]; - FILE* streams[2] = {NULL, NULL}; -#endif - -#ifdef ZTS - void ***tsrm_ls; -#endif + int listen = -1; + int server = -1; + int socket = -1; + FILE* stream = NULL; + char *print_opline_func; + zend_bool ext_stmt = 0; + zend_bool use_mm_wrappers = 0; + zend_bool is_exit; + int exit_status; #ifndef _WIN32 + struct sigaction sigio_struct; struct sigaction signal_struct; signal_struct.sa_sigaction = phpdbg_signal_handler; signal_struct.sa_flags = SA_SIGINFO | SA_NODEFER; + sigemptyset(&signal_struct.sa_mask); + sigio_struct.sa_sigaction = phpdbg_sigio_handler; + sigio_struct.sa_flags = SA_SIGINFO; + sigemptyset(&sigio_struct.sa_mask); address = strdup("127.0.0.1"); - socket[0] = -1; - socket[1] = -1; - listen[0] = -1; - listen[1] = -1; - server[0] = -1; - server[1] = -1; - streams[0] = NULL; - streams[1] = NULL; #endif #ifdef PHP_WIN32 @@ -1019,59 +1338,43 @@ int main(int argc, char **argv) /* {{{ */ #ifdef ZTS tsrm_startup(1, 1, 0, NULL); - - tsrm_ls = ts_resource(0); + (void)ts_resource(0); + ZEND_TSRMLS_CACHE_UPDATE(); #endif -phpdbg_main: - if (!cleaning) { - -#ifdef _WIN32 - bp_tmp_file = malloc(L_tmpnam); - - if (bp_tmp_file) { - if (!tmpnam(bp_tmp_file)) { - free(bp_tmp_file); - bp_tmp_file = NULL; - } - } - - if (!bp_tmp_file) { - phpdbg_error("Unable to create temporary file"); - return 1; - } -#else - if (!mkstemp(bp_tmp_file)) { - memset(bp_tmp_file, 0, sizeof(bp_tmp_file)); - } +#ifdef ZEND_SIGNALS + zend_signal_startup(); #endif - } +phpdbg_main: ini_entries = NULL; ini_entries_len = 0; ini_ignore = 0; ini_override = NULL; zend_extensions = NULL; zend_extensions_len = 0L; - exec = NULL; - exec_len = 0; init_file = NULL; init_file_len = 0; init_file_default = 1; oplog_file = NULL; oplog_file_len = 0; flags = PHPDBG_DEFAULT_FLAGS; + is_exit = 0; php_optarg = NULL; php_optind = 1; opt = 0; - run = 0; - step = 0; sapi_name = NULL; + exit_status = 0; + if (settings) { + exec = settings->exec; + } while ((opt = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) { switch (opt) { case 'r': - run++; + if (settings == NULL) { + phpdbg_startup_run++; + } break; case 'n': ini_ignore = 1; @@ -1155,8 +1458,8 @@ phpdbg_main: flags &= ~PHPDBG_IS_QUIET; break; - case 's': /* set stepping on */ - step = 1; + case 'e': + ext_stmt = 1; break; case 'E': /* stepping through eval on */ @@ -1172,20 +1475,12 @@ phpdbg_main: break; #ifndef _WIN32 - /* if you pass a listen port, we will accept input on listen port */ - /* and write output to listen port * 2 */ - - case 'l': { /* set listen ports */ - if (sscanf(php_optarg, "%d/%d", &listen[0], &listen[1]) != 2) { - if (sscanf(php_optarg, "%d", &listen[0]) != 1) { - /* default to hardcoded ports */ - listen[0] = 4000; - listen[1] = 8000; - } else { - listen[1] = (listen[0] * 2); - } + /* if you pass a listen port, we will read and write on listen port */ + case 'l': /* set listen ports */ + if (sscanf(php_optarg, "%d", &listen) != 1) { + listen = 8000; } - } break; + break; case 'a': { /* set bind address */ free(address); @@ -1195,6 +1490,32 @@ phpdbg_main: } break; #endif + case 'x': + flags |= PHPDBG_WRITE_XML; + break; + + + case 'p': { + print_opline_func = php_optarg; + show_banner = 0; + settings = (void *) 0x1; + } break; + + case 'h': { + sapi_startup(phpdbg); + phpdbg->startup(phpdbg); + PHPDBG_G(flags) = 0; + /* It ain't gonna proceed to real execution anyway, + but the correct descriptor is needed already. */ + PHPDBG_G(io)[PHPDBG_STDOUT].ptr = stdout; + PHPDBG_G(io)[PHPDBG_STDOUT].fd = fileno(stdout); + phpdbg_set_prompt(PHPDBG_DEFAULT_PROMPT); + phpdbg_do_help(NULL); + sapi_deactivate(); + sapi_shutdown(); + return 0; + } break; + case 'V': { sapi_startup(phpdbg); phpdbg->startup(phpdbg); @@ -1206,39 +1527,23 @@ phpdbg_main: PHP_VERSION, get_zend_version() ); - sapi_deactivate(TSRMLS_C); + sapi_deactivate(); sapi_shutdown(); return 0; } break; } + + php_optarg = NULL; } - + /* set exec if present on command line */ - if ((argc > php_optind) && (strcmp(argv[php_optind-1],"--") != SUCCESS)) - { - exec_len = strlen(argv[php_optind]); - if (exec_len) { - if (exec) { - free(exec); - } + if (argc > php_optind && (strcmp(argv[php_optind-1], "--") != SUCCESS)) { + if (!exec && strlen(argv[php_optind])) { exec = strdup(argv[php_optind]); } php_optind++; } -#ifndef _WIN32 - /* setup remote server if necessary */ - if (!cleaning && - (listen[0] > 0 && listen[1] > 0)) { - if (phpdbg_open_sockets(address, listen, &server, &socket, streams) == FAILURE) { - remote = 0; - exit(0); - } - /* set remote flag to stop service shutting down upon quit */ - remote = 1; - } -#endif - if (sapi_name) { phpdbg->name = sapi_name; } @@ -1289,153 +1594,246 @@ phpdbg_main: phpdbg->ini_entries = ini_entries; if (phpdbg->startup(phpdbg) == SUCCESS) { + zend_mm_heap *mm_heap; #ifdef _WIN32 EXCEPTION_POINTERS *xp; __try { #endif - zend_mm_heap *mm_heap = phpdbg_mm_get_heap(); + void* (*_malloc)(size_t); + void (*_free)(void*); + void* (*_realloc)(void*, size_t); - if (mm_heap->use_zend_alloc) { - mm_heap->_malloc = phpdbg_malloc_wrapper; - mm_heap->_realloc = phpdbg_realloc_wrapper; - mm_heap->_free = phpdbg_free_wrapper; - mm_heap->use_zend_alloc = 0; + /* set flags from command line */ + PHPDBG_G(flags) = flags; + + if (settings > (zend_phpdbg_globals *) 0x2) { +#ifdef ZTS + *((zend_phpdbg_globals *) (*((void ***) TSRMLS_CACHE))[TSRM_UNSHUFFLE_RSRC_ID(phpdbg_globals_id)]) = *settings; +#else + phpdbg_globals = *settings; +#endif + free(settings); } - zend_activate(TSRMLS_C); + /* setup remote server if necessary */ + if (cleaning <= 0 && listen > 0) { + server = phpdbg_open_socket(address, listen); + if (-1 > server || phpdbg_remote_init(address, listen, server, &socket, &stream) == FAILURE) { + exit(0); + } - PHPDBG_G(original_free_function) = mm_heap->_free; - mm_heap->_free = phpdbg_watch_efree; +#ifndef _WIN32 + sigaction(SIGIO, &sigio_struct, NULL); +#endif - phpdbg_setup_watchpoints(TSRMLS_C); + /* set remote flag to stop service shutting down upon quit */ + remote = 1; +#ifndef _WIN32 + } else { + + signal(SIGHUP, phpdbg_sighup_handler); +#endif + } + + mm_heap = zend_mm_get_heap(); + zend_mm_get_custom_handlers(mm_heap, &_malloc, &_free, &_realloc); + + use_mm_wrappers = !_malloc && !_realloc && !_free; + + phpdbg_init_list(); + + PHPDBG_G(original_free_function) = _free; + _free = phpdbg_watch_efree; + + if (use_mm_wrappers) { +#if ZEND_DEBUG + zend_mm_set_custom_debug_handlers(mm_heap, phpdbg_malloc_wrapper, phpdbg_free_wrapper, phpdbg_realloc_wrapper); +#else + zend_mm_set_custom_handlers(mm_heap, phpdbg_malloc_wrapper, phpdbg_free_wrapper, phpdbg_realloc_wrapper); +#endif + } else { + zend_mm_set_custom_handlers(mm_heap, _malloc, _free, _realloc); + } + + phpdbg_setup_watchpoints(); #if defined(ZEND_SIGNALS) && !defined(_WIN32) zend_try { - zend_signal_activate(TSRMLS_C); + zend_signal_activate(); } zend_end_try(); #endif #if defined(ZEND_SIGNALS) && !defined(_WIN32) - zend_try { zend_sigaction(SIGSEGV, &signal_struct, &PHPDBG_G(old_sigsegv_signal) TSRMLS_CC); } zend_end_try(); - zend_try { zend_sigaction(SIGBUS, &signal_struct, &PHPDBG_G(old_sigsegv_signal) TSRMLS_CC); } zend_end_try(); + zend_try { zend_sigaction(SIGSEGV, &signal_struct, &PHPDBG_G(old_sigsegv_signal)); } zend_end_try(); + zend_try { zend_sigaction(SIGBUS, &signal_struct, &PHPDBG_G(old_sigsegv_signal)); } zend_end_try(); #elif !defined(_WIN32) sigaction(SIGSEGV, &signal_struct, &PHPDBG_G(old_sigsegv_signal)); sigaction(SIGBUS, &signal_struct, &PHPDBG_G(old_sigsegv_signal)); #endif - if (php_request_startup(TSRMLS_C) == SUCCESS) { + PHPDBG_G(sapi_name_ptr) = sapi_name; + + if (exec) { /* set execution context */ + PHPDBG_G(exec) = phpdbg_resolve_path(exec); + PHPDBG_G(exec_len) = PHPDBG_G(exec) ? strlen(PHPDBG_G(exec)) : 0; + + free(exec); + exec = NULL; + } + + php_output_activate(); + php_output_deactivate(); + + if (SG(sapi_headers).mimetype) { + efree(SG(sapi_headers).mimetype); + SG(sapi_headers).mimetype = NULL; + } + + php_output_activate(); + + { int i; - - SG(request_info).argc = argc - php_optind + 1; + + SG(request_info).argc = argc - php_optind + 1; SG(request_info).argv = emalloc(SG(request_info).argc * sizeof(char *)); for (i = SG(request_info).argc; --i;) { SG(request_info).argv[i] = estrdup(argv[php_optind - 1 + i]); } - SG(request_info).argv[i] = exec ? estrndup(exec, exec_len) : estrdup(""); + SG(request_info).argv[0] = PHPDBG_G(exec) ? estrdup(PHPDBG_G(exec)) : estrdup(""); + } - php_hash_environment(TSRMLS_C); + if (php_request_startup() == FAILURE) { + PUTS("Could not startup"); + return 1; } - /* make sure to turn off buffer for ev command */ - php_output_activate(TSRMLS_C); - php_output_deactivate(TSRMLS_C); - /* do not install sigint handlers for remote consoles */ /* sending SIGINT then provides a decent way of shutting down the server */ #ifndef _WIN32 - if (listen[0] < 0) { + if (listen < 0) { #endif #if defined(ZEND_SIGNALS) && !defined(_WIN32) - zend_try { zend_signal(SIGINT, phpdbg_sigint_handler TSRMLS_CC); } zend_end_try(); + zend_try { zend_signal(SIGINT, phpdbg_sigint_handler); } zend_end_try(); #else signal(SIGINT, phpdbg_sigint_handler); #endif #ifndef _WIN32 } -#endif - - PG(modules_activated) = 0; - /* set flags from command line */ - PHPDBG_G(flags) = flags; - -#ifndef _WIN32 /* setup io here */ - if (streams[0] && streams[1]) { + if (remote) { PHPDBG_G(flags) |= PHPDBG_IS_REMOTE; signal(SIGPIPE, SIG_IGN); } + PHPDBG_G(io)[PHPDBG_STDIN].ptr = stdin; + PHPDBG_G(io)[PHPDBG_STDIN].fd = fileno(stdin); + PHPDBG_G(io)[PHPDBG_STDOUT].ptr = stdout; + PHPDBG_G(io)[PHPDBG_STDOUT].fd = fileno(stdout); +#else + /* XXX this is a complete mess here with FILE/fd/SOCKET, + we should let only one to survive probably. Need + a clean separation whether it's a remote or local + prompt. And what is supposed to go as user interaction, + error log, etc. */ + if (remote) { + PHPDBG_G(io)[PHPDBG_STDIN].ptr = stdin; + PHPDBG_G(io)[PHPDBG_STDIN].fd = socket; + PHPDBG_G(io)[PHPDBG_STDOUT].ptr = stdout; + PHPDBG_G(io)[PHPDBG_STDOUT].fd = socket; + } else { + PHPDBG_G(io)[PHPDBG_STDIN].ptr = stdin; + PHPDBG_G(io)[PHPDBG_STDIN].fd = fileno(stdin); + PHPDBG_G(io)[PHPDBG_STDOUT].ptr = stdout; + PHPDBG_G(io)[PHPDBG_STDOUT].fd = fileno(stdout); + } #endif + PHPDBG_G(io)[PHPDBG_STDERR].ptr = stderr; + PHPDBG_G(io)[PHPDBG_STDERR].fd = fileno(stderr); - PHPDBG_G(io)[PHPDBG_STDIN] = stdin; - PHPDBG_G(io)[PHPDBG_STDOUT] = stdout; - PHPDBG_G(io)[PHPDBG_STDERR] = stderr; - - if (exec) { /* set execution context */ - PHPDBG_G(exec) = phpdbg_resolve_path(exec TSRMLS_CC); - PHPDBG_G(exec_len) = strlen(PHPDBG_G(exec)); - - free(exec); - } +#ifndef _WIN32 + PHPDBG_G(php_stdiop_write) = php_stream_stdio_ops.write; + php_stream_stdio_ops.write = phpdbg_stdiop_write; +#endif if (oplog_file) { /* open oplog */ PHPDBG_G(oplog) = fopen(oplog_file, "w+"); if (!PHPDBG_G(oplog)) { - phpdbg_error( - "Failed to open oplog %s", oplog_file); + phpdbg_error("oplog", "path=\"%s\"", "Failed to open oplog %s", oplog_file); } free(oplog_file); + oplog_file = NULL; } /* set default colors */ - phpdbg_set_color_ex(PHPDBG_COLOR_PROMPT, PHPDBG_STRL("white-bold") TSRMLS_CC); - phpdbg_set_color_ex(PHPDBG_COLOR_ERROR, PHPDBG_STRL("red-bold") TSRMLS_CC); - phpdbg_set_color_ex(PHPDBG_COLOR_NOTICE, PHPDBG_STRL("green") TSRMLS_CC); + phpdbg_set_color_ex(PHPDBG_COLOR_PROMPT, PHPDBG_STRL("white-bold")); + phpdbg_set_color_ex(PHPDBG_COLOR_ERROR, PHPDBG_STRL("red-bold")); + phpdbg_set_color_ex(PHPDBG_COLOR_NOTICE, PHPDBG_STRL("green")); /* set default prompt */ - phpdbg_set_prompt(PROMPT TSRMLS_CC); + phpdbg_set_prompt(PHPDBG_DEFAULT_PROMPT); /* Make stdin, stdout and stderr accessible from PHP scripts */ - phpdbg_register_file_handles(TSRMLS_C); + phpdbg_register_file_handles(); - if (show_banner) { + phpdbg_list_update(); + + if (show_banner && cleaning < 2) { /* print blurb */ - phpdbg_welcome((cleaning > 0) TSRMLS_CC); + phpdbg_welcome(cleaning == 1); } - /* auto compile */ - if (PHPDBG_G(exec)) { - phpdbg_compile(TSRMLS_C); + cleaning = -1; + + if (ext_stmt) { + CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO; } /* initialize from file */ PHPDBG_G(flags) |= PHPDBG_IS_INITIALIZING; zend_try { - phpdbg_init(init_file, init_file_len, init_file_default TSRMLS_CC); - phpdbg_try_file_init(bp_tmp_file, strlen(bp_tmp_file), 0 TSRMLS_CC); + phpdbg_init(init_file, init_file_len, init_file_default); + if (bp_tmp) { + PHPDBG_G(flags) |= PHPDBG_DISCARD_OUTPUT; + phpdbg_string_init(bp_tmp); + free(bp_tmp); + bp_tmp = NULL; + PHPDBG_G(flags) &= ~PHPDBG_DISCARD_OUTPUT; + } } zend_end_try(); PHPDBG_G(flags) &= ~PHPDBG_IS_INITIALIZING; - + /* quit if init says so */ if (PHPDBG_G(flags) & PHPDBG_IS_QUITTING) { goto phpdbg_out; } - /* step from here, not through init */ - if (step) { - PHPDBG_G(flags) |= PHPDBG_IS_STEPPING; + /* auto compile */ + if (PHPDBG_G(exec)) { + if (settings || phpdbg_startup_run > 0) { + PHPDBG_G(flags) |= PHPDBG_DISCARD_OUTPUT; + } + + zend_try { + phpdbg_compile(); + } zend_end_try(); + + PHPDBG_G(flags) &= ~PHPDBG_DISCARD_OUTPUT; } - if (run) { - /* no need to try{}, run does it ... */ - PHPDBG_COMMAND_HANDLER(run)(NULL TSRMLS_CC); - if (run > 1) { - /* if -r is on the command line more than once just quit */ - goto phpdbg_out; + if (settings == (void *) 0x1) { + if (PHPDBG_G(ops)) { + phpdbg_print_opcodes(print_opline_func); + } else { + quiet_write(PHPDBG_G(io)[PHPDBG_STDERR].fd, ZEND_STRL("No opcodes could be compiled | No file specified or compilation failed?\n")); } + goto phpdbg_out; } + PG(during_request_startup) = 0; + + phpdbg_fully_started = 1; + /* #ifndef for making compiler shutting up */ #ifndef _WIN32 phpdbg_interact: @@ -1443,12 +1841,37 @@ phpdbg_interact: /* phpdbg main() */ do { zend_try { - phpdbg_interactive(TSRMLS_C); + if (phpdbg_startup_run) { + quit_immediately = phpdbg_startup_run > 1; + phpdbg_startup_run = 0; + if (quit_immediately) { + PHPDBG_G(flags) = (PHPDBG_G(flags) & ~PHPDBG_HAS_PAGINATION) | PHPDBG_IS_INTERACTIVE | PHPDBG_PREVENT_INTERACTIVE; + } else { + PHPDBG_G(flags) |= PHPDBG_IS_INTERACTIVE; + } + zend_try { + PHPDBG_COMMAND_HANDLER(run)(NULL); + } zend_end_try(); + if (quit_immediately) { + /* if -r is on the command line more than once just quit */ + EG(bailout) = __orig_bailout; /* reset zend_try */ + exit_status = EG(exit_status); + break; + } + } + + CG(unclean_shutdown) = 0; + phpdbg_interactive(1); } zend_catch { if ((PHPDBG_G(flags) & PHPDBG_IS_CLEANING)) { - FILE *bp_tmp_fp = fopen(bp_tmp_file, "w"); - phpdbg_export_breakpoints(bp_tmp_fp TSRMLS_CC); - fclose(bp_tmp_fp); + char *bp_tmp_str; + PHPDBG_G(flags) |= PHPDBG_DISCARD_OUTPUT; + phpdbg_export_breakpoints_to_string(&bp_tmp_str); + PHPDBG_G(flags) &= ~PHPDBG_DISCARD_OUTPUT; + if (bp_tmp_str) { + bp_tmp = strdup(bp_tmp_str); + efree(bp_tmp_str); + } cleaning = 1; } else { cleaning = 0; @@ -1458,17 +1881,16 @@ phpdbg_interact: if (!cleaning) { /* remote client disconnected */ if ((PHPDBG_G(flags) & PHPDBG_IS_DISCONNECTED)) { - + if (PHPDBG_G(flags) & PHPDBG_IS_REMOTE) { /* renegociate connections */ - phpdbg_open_sockets( - address, listen, &server, &socket, streams); - + phpdbg_remote_init(address, listen, server, &socket, &stream); + /* set streams */ - if (streams[0] && streams[1]) { + if (stream) { PHPDBG_G(flags) &= ~PHPDBG_IS_QUITTING; } - + /* this must be forced */ CG(unclean_shutdown) = 0; } else { @@ -1479,14 +1901,9 @@ phpdbg_interact: } #endif } zend_end_try(); - } while(!cleaning && !(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)); - - /* this must be forced */ - CG(unclean_shutdown) = 0; - - /* this is just helpful */ - PG(report_memleaks) = 0; - + } while (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)); + + #ifndef _WIN32 phpdbg_out: if ((PHPDBG_G(flags) & PHPDBG_IS_DISCONNECTED)) { @@ -1497,26 +1914,25 @@ phpdbg_out: #ifdef _WIN32 } __except(phpdbg_exception_handler_win32(xp = GetExceptionInformation())) { - phpdbg_error("Access violation (Segmentation fault) encountered\ntrying to abort cleanly..."); + phpdbg_error("segfault", "", "Access violation (Segmentation fault) encountered\ntrying to abort cleanly..."); } phpdbg_out: #endif - + + if (cleaning <= 0) { + PHPDBG_G(flags) &= ~PHPDBG_IS_CLEANING; + cleaning = -1; + } + { int i; /* free argv */ - for (i = SG(request_info).argc; --i;) { + for (i = SG(request_info).argc; i--;) { efree(SG(request_info).argv[i]); } efree(SG(request_info).argv); } -#ifndef ZTS - /* force cleanup of auto and core globals */ - zend_hash_clean(CG(auto_globals)); - memset( - &core_globals, 0, sizeof(php_core_globals)); -#endif if (ini_entries) { free(ini_entries); } @@ -1524,27 +1940,87 @@ phpdbg_out: if (ini_override) { free(ini_override); } - - /* this must be forced */ - CG(unclean_shutdown) = 0; - - /* this is just helpful */ - PG(report_memleaks) = 0; - php_request_shutdown((void*)0); + /* In case we aborted during script execution, we may not reset CG(unclean_shutdown) */ + if (!(PHPDBG_G(flags) & PHPDBG_IS_RUNNING)) { + is_exit = !PHPDBG_G(in_execution); + CG(unclean_shutdown) = is_exit || PHPDBG_G(unclean_eval); + } + + if ((PHPDBG_G(flags) & (PHPDBG_IS_CLEANING | PHPDBG_IS_RUNNING)) == PHPDBG_IS_CLEANING) { + php_free_shutdown_functions(); + zend_objects_store_mark_destructed(&EG(objects_store)); + } + + /* backup globals when cleaning */ + if ((cleaning > 0 || remote) && !quit_immediately) { + settings = calloc(1, sizeof(zend_phpdbg_globals)); + + php_phpdbg_globals_ctor(settings); + + if (PHPDBG_G(exec)) { + settings->exec = zend_strndup(PHPDBG_G(exec), PHPDBG_G(exec_len)); + settings->exec_len = PHPDBG_G(exec_len); + } + settings->oplog = PHPDBG_G(oplog); + settings->prompt[0] = PHPDBG_G(prompt)[0]; + settings->prompt[1] = PHPDBG_G(prompt)[1]; + memcpy(settings->colors, PHPDBG_G(colors), sizeof(settings->colors)); + settings->eol = PHPDBG_G(eol); + settings->input_buflen = PHPDBG_G(input_buflen); + memcpy(settings->input_buffer, PHPDBG_G(input_buffer), settings->input_buflen); + settings->flags = PHPDBG_G(flags) & PHPDBG_PRESERVE_FLAGS_MASK; + } else { + if (PHPDBG_G(prompt)[0]) { + free(PHPDBG_G(prompt)[0]); + } + if (PHPDBG_G(prompt)[1]) { + free(PHPDBG_G(prompt)[1]); + } + } + + /* hack to restore mm_heap->use_custom_heap in order to receive memory leak info */ + if (use_mm_wrappers) { + /* ASSUMING that mm_heap->use_custom_heap is the first element of the struct ... */ + *(int *) mm_heap = 0; + } + zend_try { + php_request_shutdown(NULL); + } zend_end_try(); + + if (exit_status == 0) { + exit_status = EG(exit_status); + } + + if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) { + if (PHPDBG_G(in_execution) || is_exit) { + if (!quit_immediately && !phpdbg_startup_run) { + phpdbg_notice("stop", "type=\"normal\"", "Script ended normally"); + cleaning++; + } + } + } + php_output_deactivate(); zend_try { - php_module_shutdown(TSRMLS_C); + php_module_shutdown(); } zend_end_try(); - sapi_shutdown(); +#ifndef _WIN32 + /* reset it... else we risk a stack overflow upon next run (when clean'ing) */ + php_stream_stdio_ops.write = PHPDBG_G(php_stdiop_write); +#endif + sapi_shutdown(); } - if (cleaning || remote) { + if ((cleaning > 0 || remote) && !quit_immediately) { + /* reset internal php_getopt state */ + php_getopt(-1, argv, OPTIONS, NULL, &php_optind, 0, 0); + goto phpdbg_main; } - + #ifdef ZTS /* bugggy */ /* tsrm_shutdown(); */ @@ -1556,15 +2032,10 @@ phpdbg_out: } #endif - if (sapi_name) { - free(sapi_name); + if (PHPDBG_G(sapi_name_ptr)) { + free(PHPDBG_G(sapi_name_ptr)); } - -#ifdef _WIN32 - free(bp_tmp_file); -#else - unlink(bp_tmp_file); -#endif - return 0; + /* usually 0; just for -rr */ + return exit_status; } /* }}} */ diff --git a/sapi/phpdbg/phpdbg.h b/sapi/phpdbg/phpdbg.h index 42f5feac39..c77bc1c530 100644 --- a/sapi/phpdbg/phpdbg.h +++ b/sapi/phpdbg/phpdbg.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -29,6 +29,12 @@ # define PHPDBG_API #endif +#ifndef PHP_WIN32 +# include <stdint.h> +# include <stddef.h> +#else +# include "main/php_stdint.h" +#endif #include "php.h" #include "php_globals.h" #include "php_variables.h" @@ -40,20 +46,20 @@ #include "zend_ini_scanner.h" #include "zend_stream.h" #ifndef _WIN32 -# include "zend_signal.h" +# include "zend_signal.h" #endif #include "SAPI.h" #include <fcntl.h> #include <sys/types.h> #if defined(_WIN32) && !defined(__MINGW32__) -# include <windows.h> -# include "config.w32.h" -# undef strcasecmp -# undef strncasecmp -# define strcasecmp _stricmp -# define strncasecmp _strnicmp +# include <windows.h> +# include "config.w32.h" +# undef strcasecmp +# undef strncasecmp +# define strcasecmp _stricmp +# define strncasecmp _strnicmp #else -# include "php_config.h" +# include "php_config.h" #endif #ifndef O_BINARY # define O_BINARY 0 @@ -64,21 +70,52 @@ # include "TSRM.h" #endif -#ifdef LIBREADLINE -# include <readline/readline.h> -# include <readline/history.h> +#undef zend_hash_str_add +#ifdef PHP_WIN32 +#define zend_hash_str_add(...) \ + _zend_hash_str_add(__VA_ARGS__ ZEND_FILE_LINE_CC) +#else +#define zend_hash_str_add_tmp(ht, key, len, pData) \ + _zend_hash_str_add(ht, key, len, pData ZEND_FILE_LINE_CC) +#define zend_hash_str_add(...) zend_hash_str_add_tmp(__VA_ARGS__) +#endif + +#ifdef HAVE_LIBREADLINE +# include <readline/readline.h> +# include <readline/history.h> #endif #ifdef HAVE_LIBEDIT -# include <editline/readline.h> +# include <editline/readline.h> #endif -#include "phpdbg_lexer.h" -#include "phpdbg_cmd.h" -#include "phpdbg_utils.h" -#include "phpdbg_btree.h" -#include "phpdbg_watch.h" +/* {{{ remote console headers */ +#ifndef _WIN32 +# include <sys/socket.h> +# include <sys/un.h> +# include <sys/select.h> +# include <sys/types.h> +# include <netdb.h> +#endif /* }}} */ -int phpdbg_do_parse(phpdbg_param_t *stack, char *input TSRMLS_DC); +/* {{{ strings */ +#define PHPDBG_NAME "phpdbg" +#define PHPDBG_AUTHORS "Felipe Pena, Joe Watkins and Bob Weinand" /* Ordered by last name */ +#define PHPDBG_ISSUES "http://bugs.php.net/report.php" +#define PHPDBG_VERSION "0.5.0" +#define PHPDBG_INIT_FILENAME ".phpdbginit" +#define PHPDBG_DEFAULT_PROMPT "prompt>" +/* }}} */ + +/* Hey, apple. One shouldn't define *functions* from the standard C library as marcos. */ +#ifdef memcpy +#define memcpy_tmp(...) memcpy(__VA_ARGS__) +#undef memcpy +#define memcpy(...) memcpy_tmp(__VA_ARGS__) +#endif + +#define quiet_write(...) ZEND_IGNORE_VALUE(write(__VA_ARGS__)) + +#if !defined(PHPDBG_WEBDATA_TRANSFER_H) && !defined(PHPDBG_WEBHELPER_H) #ifdef ZTS # define PHPDBG_G(v) TSRMG(phpdbg_globals_id, zend_phpdbg_globals *, v) @@ -86,6 +123,21 @@ int phpdbg_do_parse(phpdbg_param_t *stack, char *input TSRMLS_DC); # define PHPDBG_G(v) (phpdbg_globals.v) #endif +#include "phpdbg_sigsafe.h" +#include "phpdbg_out.h" +#include "phpdbg_lexer.h" +#include "phpdbg_cmd.h" +#include "phpdbg_utils.h" +#include "phpdbg_btree.h" +#include "phpdbg_watch.h" +#include "phpdbg_bp.h" +#include "phpdbg_opcode.h" +#ifdef PHP_WIN32 +# include "phpdbg_sigio_win32.h" +#endif + +int phpdbg_do_parse(phpdbg_param_t *stack, char *input); + #define PHPDBG_NEXT 2 #define PHPDBG_UNTIL 3 #define PHPDBG_FINISH 4 @@ -95,92 +147,100 @@ int phpdbg_do_parse(phpdbg_param_t *stack, char *input TSRMLS_DC); BEGIN: DO NOT CHANGE DO NOT CHANGE DO NOT CHANGE */ -/* {{{ tables */ -#define PHPDBG_BREAK_FILE 0 -#define PHPDBG_BREAK_SYM 1 -#define PHPDBG_BREAK_OPLINE 2 -#define PHPDBG_BREAK_METHOD 3 -#define PHPDBG_BREAK_COND 4 -#define PHPDBG_BREAK_OPCODE 5 -#define PHPDBG_BREAK_FUNCTION_OPLINE 6 -#define PHPDBG_BREAK_METHOD_OPLINE 7 -#define PHPDBG_BREAK_FILE_OPLINE 8 -#define PHPDBG_BREAK_MAP 9 -#define PHPDBG_BREAK_TABLES 10 /* }}} */ - /* {{{ flags */ -#define PHPDBG_HAS_FILE_BP (1<<1) -#define PHPDBG_HAS_SYM_BP (1<<2) -#define PHPDBG_HAS_OPLINE_BP (1<<3) -#define PHPDBG_HAS_METHOD_BP (1<<4) -#define PHPDBG_HAS_COND_BP (1<<5) -#define PHPDBG_HAS_OPCODE_BP (1<<6) -#define PHPDBG_HAS_FUNCTION_OPLINE_BP (1<<7) -#define PHPDBG_HAS_METHOD_OPLINE_BP (1<<8) -#define PHPDBG_HAS_FILE_OPLINE_BP (1<<9) /* }}} */ +#define PHPDBG_HAS_FILE_BP (1ULL<<1) +#define PHPDBG_HAS_PENDING_FILE_BP (1ULL<<2) +#define PHPDBG_HAS_SYM_BP (1ULL<<3) +#define PHPDBG_HAS_OPLINE_BP (1ULL<<4) +#define PHPDBG_HAS_METHOD_BP (1ULL<<5) +#define PHPDBG_HAS_COND_BP (1ULL<<6) +#define PHPDBG_HAS_OPCODE_BP (1ULL<<7) +#define PHPDBG_HAS_FUNCTION_OPLINE_BP (1ULL<<8) +#define PHPDBG_HAS_METHOD_OPLINE_BP (1ULL<<9) +#define PHPDBG_HAS_FILE_OPLINE_BP (1ULL<<10) /* }}} */ /* END: DO NOT CHANGE DO NOT CHANGE DO NOT CHANGE */ -#define PHPDBG_IN_COND_BP (1<<10) -#define PHPDBG_IN_EVAL (1<<11) +#define PHPDBG_IN_COND_BP (1ULL<<11) +#define PHPDBG_IN_EVAL (1ULL<<12) -#define PHPDBG_IS_STEPPING (1<<12) -#define PHPDBG_STEP_OPCODE (1<<13) -#define PHPDBG_IS_QUIET (1<<14) -#define PHPDBG_IS_QUITTING (1<<15) -#define PHPDBG_IS_COLOURED (1<<16) -#define PHPDBG_IS_CLEANING (1<<17) +#define PHPDBG_IS_STEPPING (1ULL<<13) +#define PHPDBG_STEP_OPCODE (1ULL<<14) +#define PHPDBG_IS_QUIET (1ULL<<15) +#define PHPDBG_IS_QUITTING (1ULL<<16) +#define PHPDBG_IS_COLOURED (1ULL<<17) +#define PHPDBG_IS_CLEANING (1ULL<<18) +#define PHPDBG_IS_RUNNING (1ULL<<19) -#define PHPDBG_IN_UNTIL (1<<18) -#define PHPDBG_IN_FINISH (1<<19) -#define PHPDBG_IN_LEAVE (1<<20) +#define PHPDBG_IN_UNTIL (1ULL<<20) +#define PHPDBG_IN_FINISH (1ULL<<21) +#define PHPDBG_IN_LEAVE (1ULL<<22) -#define PHPDBG_IS_REGISTERED (1<<21) -#define PHPDBG_IS_STEPONEVAL (1<<22) -#define PHPDBG_IS_INITIALIZING (1<<23) -#define PHPDBG_IS_SIGNALED (1<<24) -#define PHPDBG_IS_INTERACTIVE (1<<25) -#define PHPDBG_IS_BP_ENABLED (1<<26) -#define PHPDBG_IS_REMOTE (1<<27) -#define PHPDBG_IS_DISCONNECTED (1<<28) +#define PHPDBG_IS_REGISTERED (1ULL<<23) +#define PHPDBG_IS_STEPONEVAL (1ULL<<24) +#define PHPDBG_IS_INITIALIZING (1ULL<<25) +#define PHPDBG_IS_SIGNALED (1ULL<<26) +#define PHPDBG_IS_INTERACTIVE (1ULL<<27) +#define PHPDBG_PREVENT_INTERACTIVE (1ULL<<28) +#define PHPDBG_IS_BP_ENABLED (1ULL<<29) +#define PHPDBG_IS_REMOTE (1ULL<<30) +#define PHPDBG_IS_DISCONNECTED (1ULL<<31) +#define PHPDBG_WRITE_XML (1ULL<<32) -#define PHPDBG_SHOW_REFCOUNTS (1<<29) +#define PHPDBG_SHOW_REFCOUNTS (1ULL<<33) -#define PHPDBG_SEEK_MASK (PHPDBG_IN_UNTIL|PHPDBG_IN_FINISH|PHPDBG_IN_LEAVE) -#define PHPDBG_BP_RESOLVE_MASK (PHPDBG_HAS_FUNCTION_OPLINE_BP|PHPDBG_HAS_METHOD_OPLINE_BP|PHPDBG_HAS_FILE_OPLINE_BP) -#define PHPDBG_BP_MASK (PHPDBG_HAS_FILE_BP|PHPDBG_HAS_SYM_BP|PHPDBG_HAS_METHOD_BP|PHPDBG_HAS_OPLINE_BP|PHPDBG_HAS_COND_BP|PHPDBG_HAS_OPCODE_BP|PHPDBG_HAS_FUNCTION_OPLINE_BP|PHPDBG_HAS_METHOD_OPLINE_BP|PHPDBG_HAS_FILE_OPLINE_BP) +#define PHPDBG_IN_SIGNAL_HANDLER (1ULL<<34) + +#define PHPDBG_DISCARD_OUTPUT (1ULL<<35) + +#define PHPDBG_HAS_PAGINATION (1ULL<<36) + +#define PHPDBG_SEEK_MASK (PHPDBG_IN_UNTIL | PHPDBG_IN_FINISH | PHPDBG_IN_LEAVE) +#define PHPDBG_BP_RESOLVE_MASK (PHPDBG_HAS_FUNCTION_OPLINE_BP | PHPDBG_HAS_METHOD_OPLINE_BP | PHPDBG_HAS_FILE_OPLINE_BP) +#define PHPDBG_BP_MASK (PHPDBG_HAS_FILE_BP | PHPDBG_HAS_SYM_BP | PHPDBG_HAS_METHOD_BP | PHPDBG_HAS_OPLINE_BP | PHPDBG_HAS_COND_BP | PHPDBG_HAS_OPCODE_BP | PHPDBG_HAS_FUNCTION_OPLINE_BP | PHPDBG_HAS_METHOD_OPLINE_BP | PHPDBG_HAS_FILE_OPLINE_BP) +#define PHPDBG_IS_STOPPING (PHPDBG_IS_QUITTING | PHPDBG_IS_CLEANING) + +#define PHPDBG_PRESERVE_FLAGS_MASK (PHPDBG_SHOW_REFCOUNTS | PHPDBG_IS_STEPONEVAL | PHPDBG_IS_BP_ENABLED | PHPDBG_STEP_OPCODE | PHPDBG_IS_QUIET | PHPDBG_IS_COLOURED | PHPDBG_IS_REMOTE | PHPDBG_WRITE_XML | PHPDBG_IS_DISCONNECTED | PHPDBG_HAS_PAGINATION) #ifndef _WIN32 -# define PHPDBG_DEFAULT_FLAGS (PHPDBG_IS_QUIET|PHPDBG_IS_COLOURED|PHPDBG_IS_BP_ENABLED) +# define PHPDBG_DEFAULT_FLAGS (PHPDBG_IS_QUIET | PHPDBG_IS_COLOURED | PHPDBG_IS_BP_ENABLED | PHPDBG_HAS_PAGINATION) #else -# define PHPDBG_DEFAULT_FLAGS (PHPDBG_IS_QUIET|PHPDBG_IS_BP_ENABLED) +# define PHPDBG_DEFAULT_FLAGS (PHPDBG_IS_QUIET | PHPDBG_IS_BP_ENABLED | PHPDBG_HAS_PAGINATION) #endif /* }}} */ -/* {{{ strings */ -#define PHPDBG_NAME "phpdbg" -#define PHPDBG_AUTHORS "Felipe Pena, Joe Watkins and Bob Weinand" /* Ordered by last name */ -#define PHPDBG_URL "http://phpdbg.com" -#define PHPDBG_ISSUES "http://github.com/krakjoe/phpdbg/issues" -#define PHPDBG_VERSION "0.4.0" -#define PHPDBG_INIT_FILENAME ".phpdbginit" -/* }}} */ - /* {{{ output descriptors */ #define PHPDBG_STDIN 0 #define PHPDBG_STDOUT 1 #define PHPDBG_STDERR 2 #define PHPDBG_IO_FDS 3 /* }}} */ +#define phpdbg_try_access \ + { \ + JMP_BUF *__orig_bailout = PHPDBG_G(sigsegv_bailout); \ + JMP_BUF __bailout; \ + \ + PHPDBG_G(sigsegv_bailout) = &__bailout; \ + if (SETJMP(__bailout) == 0) { +#define phpdbg_catch_access \ + } else { \ + PHPDBG_G(sigsegv_bailout) = __orig_bailout; +#define phpdbg_end_try_access() \ + } \ + PHPDBG_G(sigsegv_bailout) = __orig_bailout; \ + } + /* {{{ structs */ ZEND_BEGIN_MODULE_GLOBALS(phpdbg) HashTable bp[PHPDBG_BREAK_TABLES]; /* break points */ HashTable registered; /* registered */ HashTable seek; /* seek oplines */ + zend_execute_data *seek_ex; /* call frame of oplines to seek to */ + zend_object *handled_exception; /* last handled exception (prevent multiple handling of same exception) */ phpdbg_frame_t frame; /* frame */ - zend_uint last_line; /* last executed line */ + uint32_t last_line; /* last executed line */ phpdbg_lexer_data lexer; /* lexer data */ phpdbg_param_t *parser_stack; /* param stack during lexer / parser phase */ @@ -191,40 +251,74 @@ ZEND_BEGIN_MODULE_GLOBALS(phpdbg) phpdbg_btree watchpoint_tree; /* tree with watchpoints */ phpdbg_btree watch_HashTables; /* tree with original dtors of watchpoints */ HashTable watchpoints; /* watchpoints */ + HashTable watch_collisions; /* collision table to check if multiple watches share the same recursive watchpoint */ zend_llist watchlist_mem; /* triggered watchpoints */ zend_bool watchpoint_hit; /* a watchpoint was hit */ void (*original_free_function)(void *); /* the original AG(mm_heap)->_free function */ + phpdbg_watchpoint_t *watch_tmp; /* temporary pointer for a watchpoint */ char *exec; /* file to execute */ size_t exec_len; /* size of exec */ zend_op_array *ops; /* op_array */ - zval *retval; /* return value */ + zval retval; /* return value */ int bp_count; /* breakpoint count */ int vmret; /* return from last opcode handler execution */ + zend_bool in_execution; /* in execution? */ + zend_bool unclean_eval; /* do not check for memory leaks when we needed to bail out during eval */ + + zend_op_array *(*compile_file)(zend_file_handle *file_handle, int type); + zend_op_array *(*init_compile_file)(zend_file_handle *file_handle, int type); + zend_op_array *(*compile_string)(zval *source_string, char *filename); + HashTable file_sources; FILE *oplog; /* opline log */ - FILE *io[PHPDBG_IO_FDS]; /* io */ + zend_arena *oplog_arena; /* arena for storing oplog */ + phpdbg_oplog_list *oplog_list; /* list of oplog starts */ + phpdbg_oplog_entry *oplog_cur; /* current oplog entry */ + + struct { + FILE *ptr; + int fd; + } io[PHPDBG_IO_FDS]; /* io */ + int eol; /* type of line ending to use */ + size_t (*php_stdiop_write)(php_stream *, const char *, size_t); + int in_script_xml; /* in <stream> output mode */ + struct { + zend_bool active; + int type; + int fd; + char *tag; + char *msg; + int msglen; + char *xml; + int xmllen; + } err_buf; /* error buffer */ + zend_ulong req_id; /* "request id" to keep track of commands */ char *prompt[2]; /* prompt */ const phpdbg_color_t *colors[PHPDBG_COLORS]; /* colors */ char *buffer; /* buffer */ + zend_bool last_was_newline; /* check if we don't need to output a newline upon next phpdbg_error or phpdbg_notice */ - zend_ulong flags; /* phpdbg flags */ + char input_buffer[PHPDBG_MAX_CMD]; /* stdin input buffer */ + int input_buflen; /* length of stdin input buffer */ + phpdbg_signal_safe_mem sigsafe_mem; /* memory to use in async safe environment (only once!) */ + + JMP_BUF *sigsegv_bailout; /* bailout address for accesibility probing */ + + uint64_t flags; /* phpdbg flags */ + + char *socket_path; /* phpdbg.path ini setting */ + char *sapi_name_ptr; /* store sapi name to free it if necessary to not leak memory */ + int socket_fd; /* file descriptor to socket (wait command) (-1 if unused) */ + int socket_server_fd; /* file descriptor to master socket (wait command) (-1 if unused) */ +#ifdef PHP_WIN32 + HANDLE sigio_watcher_thread; /* sigio watcher thread handle */ + struct win32_sigio_watcher_data swd; +#endif + long lines; /* max number of lines to display */ ZEND_END_MODULE_GLOBALS(phpdbg) /* }}} */ -/* the beginning (= the important part) of the _zend_mm_heap struct defined in Zend/zend_alloc.c - Needed for realizing watchpoints */ -struct _zend_mm_heap { - int use_zend_alloc; - void *(*_malloc)(size_t); - void (*_free)(void *); - void *(*_realloc)(void *, size_t); - size_t free_bitmap; - size_t large_free_bitmap; - size_t block_size; - size_t compact_size; - zend_mm_segment *segments_list; - zend_mm_storage *storage; -}; +#endif #endif /* PHPDBG_H */ diff --git a/sapi/phpdbg/phpdbg_bp.c b/sapi/phpdbg/phpdbg_bp.c index 06a6ad72be..4cb1dae42c 100644 --- a/sapi/phpdbg/phpdbg_bp.c +++ b/sapi/phpdbg/phpdbg_bp.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -26,28 +26,28 @@ #include "phpdbg_opcode.h" #include "zend_globals.h" -ZEND_EXTERN_MODULE_GLOBALS(phpdbg); +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) /* {{{ private api functions */ -static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_file(zend_op_array* TSRMLS_DC); -static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_symbol(zend_function* TSRMLS_DC); -static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_method(zend_op_array* TSRMLS_DC); -static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_opline(phpdbg_opline_ptr_t TSRMLS_DC); -static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_opcode(zend_uchar TSRMLS_DC); -static inline phpdbg_breakbase_t *phpdbg_find_conditional_breakpoint(zend_execute_data *execute_data TSRMLS_DC); /* }}} */ +static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_file(zend_op_array*); +static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_symbol(zend_function*); +static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_method(zend_op_array*); +static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_opline(phpdbg_opline_ptr_t); +static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_opcode(zend_uchar); +static inline phpdbg_breakbase_t *phpdbg_find_conditional_breakpoint(zend_execute_data *execute_data); /* }}} */ /* * Note: * A break point must always set the correct id and type * A set breakpoint function must always map new points */ -static inline void _phpdbg_break_mapping(int id, HashTable *table TSRMLS_DC) +static inline void _phpdbg_break_mapping(int id, HashTable *table) /* {{{ */ { - zend_hash_index_update( - &PHPDBG_G(bp)[PHPDBG_BREAK_MAP], (id), (void**) &table, sizeof(void*), NULL); + zend_hash_index_update_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], id, table); } +/* }}} */ -#define PHPDBG_BREAK_MAPPING(id, table) _phpdbg_break_mapping(id, table TSRMLS_CC) +#define PHPDBG_BREAK_MAPPING(id, table) _phpdbg_break_mapping(id, table) #define PHPDBG_BREAK_UNMAPPING(id) \ zend_hash_index_del(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], (id)) @@ -58,29 +58,32 @@ static inline void _phpdbg_break_mapping(int id, HashTable *table TSRMLS_DC) b.hits = 0; \ } while(0) -static void phpdbg_file_breaks_dtor(void *data) /* {{{ */ +static void phpdbg_file_breaks_dtor(zval *data) /* {{{ */ { - phpdbg_breakfile_t *bp = (phpdbg_breakfile_t*) data; + phpdbg_breakfile_t *bp = (phpdbg_breakfile_t*) Z_PTR_P(data); efree((char*)bp->filename); + efree(bp); } /* }}} */ -static void phpdbg_class_breaks_dtor(void *data) /* {{{ */ +static void phpdbg_class_breaks_dtor(zval *data) /* {{{ */ { - phpdbg_breakmethod_t *bp = (phpdbg_breakmethod_t*) data; + phpdbg_breakmethod_t *bp = (phpdbg_breakmethod_t *) Z_PTR_P(data); efree((char*)bp->class_name); efree((char*)bp->func_name); + efree(bp); } /* }}} */ -static void phpdbg_opline_class_breaks_dtor(void *data) /* {{{ */ +static void phpdbg_opline_class_breaks_dtor(zval *data) /* {{{ */ { - zend_hash_destroy((HashTable *)data); + zend_hash_destroy(Z_ARRVAL_P(data)); + efree(Z_ARRVAL_P(data)); } /* }}} */ -static void phpdbg_opline_breaks_dtor(void *data) /* {{{ */ +static void phpdbg_opline_breaks_dtor(zval *data) /* {{{ */ { - phpdbg_breakopline_t *bp = (phpdbg_breakopline_t *) data; + phpdbg_breakopline_t *bp = (phpdbg_breakopline_t *) Z_PTR_P(data); if (bp->class_name) { efree((char*)bp->class_name); @@ -88,96 +91,94 @@ static void phpdbg_opline_breaks_dtor(void *data) /* {{{ */ if (bp->func_name) { efree((char*)bp->func_name); } + efree(bp); } /* }}} */ -PHPDBG_API void phpdbg_reset_breakpoints(TSRMLS_D) /* {{{ */ +PHPDBG_API void phpdbg_reset_breakpoints(void) /* {{{ */ { - if (zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP])) { - HashPosition position[2]; - HashTable **table = NULL; + HashTable *table; - for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], &position[0]); - zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], (void**)&table, &position[0]) == SUCCESS; - zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], &position[0])) { - phpdbg_breakbase_t *brake; + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], table) { + phpdbg_breakbase_t *brake; - for (zend_hash_internal_pointer_reset_ex((*table), &position[1]); - zend_hash_get_current_data_ex((*table), (void**)&brake, &position[1]) == SUCCESS; - zend_hash_move_forward_ex((*table), &position[1])) { - brake->hits = 0; - } - } - } + ZEND_HASH_FOREACH_PTR(table, brake) { + brake->hits = 0; + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); } /* }}} */ -PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_export_breakpoints(FILE *handle) /* {{{ */ { - HashPosition position[2]; - HashTable **table = NULL; + char *string; + phpdbg_export_breakpoints_to_string(&string); + fputs(string, handle); +} +/* }}} */ + +PHPDBG_API void phpdbg_export_breakpoints_to_string(char **str) /* {{{ */ +{ + HashTable *table; zend_ulong id = 0L; + *str = ""; + if (zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP])) { - phpdbg_notice( - "Exporting %d breakpoints", - zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP])); + phpdbg_notice("exportbreakpoint", "count=\"%d\"", "Exporting %d breakpoints", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP])); + /* this only looks like magic, it isn't */ - for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], &position[0]); - zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], (void**)&table, &position[0]) == SUCCESS; - zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], &position[0])) { + ZEND_HASH_FOREACH_NUM_KEY_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], id, table) { phpdbg_breakbase_t *brake; - zend_hash_get_current_key_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], NULL, NULL, &id, 0, &position[0]); - - for (zend_hash_internal_pointer_reset_ex((*table), &position[1]); - zend_hash_get_current_data_ex((*table), (void**)&brake, &position[1]) == SUCCESS; - zend_hash_move_forward_ex((*table), &position[1])) { + ZEND_HASH_FOREACH_PTR(table, brake) { if (brake->id == id) { + char *new_str = NULL; + switch (brake->type) { case PHPDBG_BREAK_FILE: { - fprintf(handle, - "break %s:%lu\n", + phpdbg_asprintf(&new_str, + "%sbreak %s:%lu\n", *str, ((phpdbg_breakfile_t*)brake)->filename, ((phpdbg_breakfile_t*)brake)->line); } break; case PHPDBG_BREAK_SYM: { - fprintf(handle, - "break %s\n", + phpdbg_asprintf(&new_str, + "%sbreak %s\n", *str, ((phpdbg_breaksymbol_t*)brake)->symbol); } break; case PHPDBG_BREAK_METHOD: { - fprintf(handle, - "break %s::%s\n", + phpdbg_asprintf(&new_str, + "%sbreak %s::%s\n", *str, ((phpdbg_breakmethod_t*)brake)->class_name, ((phpdbg_breakmethod_t*)brake)->func_name); } break; case PHPDBG_BREAK_METHOD_OPLINE: { - fprintf(handle, - "break %s::%s#%ld\n", + phpdbg_asprintf(&new_str, + "%sbreak %s::%s#%llu\n", *str, ((phpdbg_breakopline_t*)brake)->class_name, ((phpdbg_breakopline_t*)brake)->func_name, ((phpdbg_breakopline_t*)brake)->opline_num); } break; case PHPDBG_BREAK_FUNCTION_OPLINE: { - fprintf(handle, - "break %s#%ld\n", + phpdbg_asprintf(&new_str, + "%sbreak %s#%llu\n", *str, ((phpdbg_breakopline_t*)brake)->func_name, ((phpdbg_breakopline_t*)brake)->opline_num); } break; case PHPDBG_BREAK_FILE_OPLINE: { - fprintf(handle, - "break %s:#%ld\n", + phpdbg_asprintf(&new_str, + "%sbreak %s:#%llu\n", *str, ((phpdbg_breakopline_t*)brake)->class_name, ((phpdbg_breakopline_t*)brake)->opline_num); } break; case PHPDBG_BREAK_OPCODE: { - fprintf(handle, - "break %s\n", + phpdbg_asprintf(&new_str, + "%sbreak %s\n", *str, ((phpdbg_breakop_t*)brake)->name); } break; @@ -187,20 +188,20 @@ PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC) /* {{{ */ if (conditional->paramed) { switch (conditional->param.type) { case STR_PARAM: - fprintf(handle, - "break at %s if %s\n", conditional->param.str, conditional->code); + phpdbg_asprintf(&new_str, + "%sbreak at %s if %s\n", *str, conditional->param.str, conditional->code); break; case METHOD_PARAM: - fprintf(handle, - "break at %s::%s if %s\n", + phpdbg_asprintf(&new_str, + "%sbreak at %s::%s if %s\n", *str, conditional->param.method.class, conditional->param.method.name, conditional->code); break; case FILE_PARAM: - fprintf(handle, - "break at %s:%lu if %s\n", + phpdbg_asprintf(&new_str, + "%sbreak at %s:%lu if %s\n", *str, conditional->param.file.name, conditional->param.file.line, conditional->code); break; @@ -208,73 +209,186 @@ PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC) /* {{{ */ default: { /* do nothing */ } break; } } else { - fprintf( - handle, "break if %s\n", conditional->code); + phpdbg_asprintf(&new_str, "%sbreak if %s\n", str, conditional->code); } } break; + + default: continue; } + + if ((*str)[0]) { + efree(*str); + } + *str = new_str; } - } - } + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); + } + + if (!(*str)[0]) { + *str = NULL; } } /* }}} */ -PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num) /* {{{ */ { php_stream_statbuf ssb; char realpath[MAXPATHLEN]; - - if (php_stream_stat_path(path, &ssb) != FAILURE) { - if (ssb.sb.st_mode & (S_IFREG|S_IFLNK)) { - HashTable *broken; - phpdbg_breakfile_t new_break; - size_t path_len = 0L; - - if (VCWD_REALPATH(path, realpath)) { - path = realpath; + const char *original_path = path; + zend_bool pending = 0; + zend_string *path_str; + + HashTable *broken, *file_breaks = &PHPDBG_G(bp)[PHPDBG_BREAK_FILE]; + phpdbg_breakfile_t new_break; + size_t path_len = 0L; + + if (VCWD_REALPATH(path, realpath)) { + path = realpath; + } + path_len = strlen(path); + + phpdbg_debug("file path: %s, resolved path: %s, was compiled: %d\n", original_path, path, zend_hash_str_exists(&PHPDBG_G(file_sources), path, path_len)); + + if (!zend_hash_str_exists(&PHPDBG_G(file_sources), path, path_len)) { + if (php_stream_stat_path(path, &ssb) == FAILURE) { + if (original_path[0] == '/') { + phpdbg_error("breakpoint", "type=\"nofile\" add=\"fail\" file=\"%s\"", "Cannot stat %s, it does not exist", original_path); + return; } + + file_breaks = &PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING]; + path = original_path; path_len = strlen(path); - - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], - path, path_len, (void**)&broken) == FAILURE) { - HashTable breaks; + pending = 1; + } else if (!(ssb.sb.st_mode & (S_IFREG|S_IFLNK))) { + phpdbg_error("breakpoint", "type=\"notregular\" add=\"fail\" file=\"%s\"", "Cannot set breakpoint in %s, it is not a regular file", path); + return; + } else { + phpdbg_debug("File exists, but not compiled\n"); + } + } - zend_hash_init(&breaks, 8, NULL, phpdbg_file_breaks_dtor, 0); + path_str = zend_string_init(path, path_len, 0); - zend_hash_update(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], - path, path_len, &breaks, sizeof(HashTable), - (void**)&broken); - } + if (!(broken = zend_hash_find_ptr(file_breaks, path_str))) { + HashTable breaks; + zend_hash_init(&breaks, 8, NULL, phpdbg_file_breaks_dtor, 0); - if (!zend_hash_index_exists(broken, line_num)) { - PHPDBG_G(flags) |= PHPDBG_HAS_FILE_BP; + broken = zend_hash_add_mem(file_breaks, path_str, &breaks, sizeof(HashTable)); + } - PHPDBG_BREAK_INIT(new_break, PHPDBG_BREAK_FILE); - new_break.filename = estrndup(path, path_len); - new_break.line = line_num; + if (!zend_hash_index_exists(broken, line_num)) { + PHPDBG_BREAK_INIT(new_break, PHPDBG_BREAK_FILE); + new_break.filename = estrndup(path, path_len); + new_break.line = line_num; - zend_hash_index_update( - broken, line_num, (void**)&new_break, sizeof(phpdbg_breakfile_t), NULL); + zend_hash_index_update_mem(broken, line_num, &new_break, sizeof(phpdbg_breakfile_t)); - phpdbg_notice("Breakpoint #%d added at %s:%ld", - new_break.id, new_break.filename, new_break.line); + PHPDBG_BREAK_MAPPING(new_break.id, broken); - PHPDBG_BREAK_MAPPING(new_break.id, broken); - } else { - phpdbg_error("Breakpoint at %s:%ld exists", path, line_num); - } + if (pending) { + zend_string *file; + ZEND_HASH_FOREACH_STR_KEY(&PHPDBG_G(file_sources), file) { + HashTable *fileht; + + phpdbg_debug("Compare against loaded %s\n", file); + + if (!(pending = ((fileht = phpdbg_resolve_pending_file_break_ex(ZSTR_VAL(file), ZSTR_LEN(file), path_str, broken)) == NULL))) { + new_break = *(phpdbg_breakfile_t *) zend_hash_index_find_ptr(fileht, line_num); + break; + } + } ZEND_HASH_FOREACH_END(); + } + if (pending) { + PHPDBG_G(flags) |= PHPDBG_HAS_PENDING_FILE_BP; + + phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" file=\"%s\" line=\"%ld\" pending=\"pending\"", "Pending breakpoint #%d added at %s:%ld", new_break.id, new_break.filename, new_break.line); } else { - phpdbg_error("Cannot set breakpoint in %s, it is not a regular file", path); + PHPDBG_G(flags) |= PHPDBG_HAS_FILE_BP; + + phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" file=\"%s\" line=\"%ld\"", "Breakpoint #%d added at %s:%ld", new_break.id, new_break.filename, new_break.line); } } else { - phpdbg_error("Cannot stat %s, it does not exist", path); + phpdbg_error("breakpoint", "type=\"exists\" add=\"fail\" file=\"%s\" line=\"%ld\"", "Breakpoint at %s:%ld exists", path, line_num); } + + zend_string_release(path_str); } /* }}} */ -PHPDBG_API void phpdbg_set_breakpoint_symbol(const char *name, size_t name_len TSRMLS_DC) /* {{{ */ +PHPDBG_API HashTable *phpdbg_resolve_pending_file_break_ex(const char *file, uint filelen, zend_string *cur, HashTable *fileht) /* {{{ */ { - if (!zend_hash_exists(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], name, name_len)) { + phpdbg_debug("file: %s, filelen: %u, cur: %s, curlen %u, pos: %c, memcmp: %d\n", file, filelen, ZSTR_VAL(cur), ZSTR_LEN(cur), filelen > ZSTR_LEN(cur) ? file[filelen - ZSTR_LEN(cur) - 1] : '?', filelen > ZSTR_LEN(cur) ? memcmp(file + filelen - ZSTR_LEN(cur), ZSTR_VAL(cur), ZSTR_LEN(cur)) : 0); + +#ifdef _WIN32 +# define WIN32_PATH_CHECK file[filelen - ZSTR_LEN(cur) - 1] == '\\' +#else +# define WIN32_PATH_CHECK 0 +#endif + + if (((ZSTR_LEN(cur) < filelen && (file[filelen - ZSTR_LEN(cur) - 1] == '/' || WIN32_PATH_CHECK)) || filelen == ZSTR_LEN(cur)) && !memcmp(file + filelen - ZSTR_LEN(cur), ZSTR_VAL(cur), ZSTR_LEN(cur))) { + phpdbg_breakfile_t *brake, new_brake; + HashTable *master; + + PHPDBG_G(flags) |= PHPDBG_HAS_FILE_BP; + + if (!(master = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], file, filelen))) { + HashTable new_ht; + zend_hash_init(&new_ht, 8, NULL, phpdbg_file_breaks_dtor, 0); + master = zend_hash_str_add_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], file, filelen, &new_ht, sizeof(HashTable)); + } + + ZEND_HASH_FOREACH_PTR(fileht, brake) { + new_brake = *brake; + new_brake.filename = estrndup(file, filelen); + PHPDBG_BREAK_UNMAPPING(brake->id); + + if (zend_hash_index_add_mem(master, brake->line, &new_brake, sizeof(phpdbg_breakfile_t))) { + PHPDBG_BREAK_MAPPING(brake->id, master); + } + } ZEND_HASH_FOREACH_END(); + + zend_hash_del(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], cur); + + if (!zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING])) { + PHPDBG_G(flags) &= ~PHPDBG_HAS_PENDING_FILE_BP; + } + + phpdbg_debug("compiled file: %s, cur bp file: %s\n", file, cur); + + return master; + } + + return NULL; +} /* }}} */ + +PHPDBG_API void phpdbg_resolve_pending_file_break(const char *file) /* {{{ */ +{ + HashTable *fileht; + uint filelen = strlen(file); + zend_string *cur; + + phpdbg_debug("was compiled: %s\n", file); + + ZEND_HASH_FOREACH_STR_KEY_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], cur, fileht) { + phpdbg_debug("check bp: %s\n", cur); + + phpdbg_resolve_pending_file_break_ex(file, filelen, cur, fileht); + } ZEND_HASH_FOREACH_END(); +} /* }}} */ + +PHPDBG_API void phpdbg_set_breakpoint_symbol(const char *name, size_t name_len) /* {{{ */ +{ + char *lcname; + + if (*name == '\\') { + name++; + name_len--; + } + + lcname = zend_str_tolower_dup(name, name_len); + + if (!zend_hash_str_exists(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], name, name_len)) { phpdbg_breaksymbol_t new_break; PHPDBG_G(flags) |= PHPDBG_HAS_SYM_BP; @@ -282,35 +396,39 @@ PHPDBG_API void phpdbg_set_breakpoint_symbol(const char *name, size_t name_len T PHPDBG_BREAK_INIT(new_break, PHPDBG_BREAK_SYM); new_break.symbol = estrndup(name, name_len); - zend_hash_update(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], new_break.symbol, - name_len, &new_break, sizeof(phpdbg_breaksymbol_t), NULL); + zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], lcname, name_len, &new_break, sizeof(phpdbg_breaksymbol_t)); - phpdbg_notice("Breakpoint #%d added at %s", - new_break.id, new_break.symbol); + phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" function=\"%s\"", "Breakpoint #%d added at %s", new_break.id, new_break.symbol); PHPDBG_BREAK_MAPPING(new_break.id, &PHPDBG_G(bp)[PHPDBG_BREAK_SYM]); } else { - phpdbg_notice("Breakpoint exists at %s", name); + phpdbg_error("breakpoint", "type=\"exists\" add=\"fail\" function=\"%s\"", "Breakpoint exists at %s", name); } + + efree(lcname); } /* }}} */ -PHPDBG_API void phpdbg_set_breakpoint_method(const char *class_name, const char *func_name TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_set_breakpoint_method(const char *class_name, const char *func_name) /* {{{ */ { HashTable class_breaks, *class_table; size_t class_len = strlen(class_name); size_t func_len = strlen(func_name); - char *lcname = zend_str_tolower_dup(func_name, func_len); + char *func_lcname, *class_lcname; - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], class_name, - class_len, (void**)&class_table) != SUCCESS) { + if (*class_name == '\\') { + class_name++; + class_len--; + } + + func_lcname = zend_str_tolower_dup(func_name, func_len); + class_lcname = zend_str_tolower_dup(class_name, class_len); + + if (!(class_table = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], class_lcname, class_len))) { zend_hash_init(&class_breaks, 8, NULL, phpdbg_class_breaks_dtor, 0); - zend_hash_update( - &PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], - class_name, class_len, - (void**)&class_breaks, sizeof(HashTable), (void**)&class_table); + class_table = zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], class_lcname, class_len, &class_breaks, sizeof(HashTable)); } - if (!zend_hash_exists(class_table, lcname, func_len)) { + if (!zend_hash_str_exists(class_table, func_lcname, func_len)) { phpdbg_breakmethod_t new_break; PHPDBG_G(flags) |= PHPDBG_HAS_METHOD_BP; @@ -321,21 +439,20 @@ PHPDBG_API void phpdbg_set_breakpoint_method(const char *class_name, const char new_break.func_name = estrndup(func_name, func_len); new_break.func_len = func_len; - zend_hash_update(class_table, lcname, func_len, - &new_break, sizeof(phpdbg_breakmethod_t), NULL); + zend_hash_str_update_mem(class_table, func_lcname, func_len, &new_break, sizeof(phpdbg_breakmethod_t)); - phpdbg_notice("Breakpoint #%d added at %s::%s", - new_break.id, class_name, func_name); + phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" method=\"%s::%s\"", "Breakpoint #%d added at %s::%s", new_break.id, class_name, func_name); PHPDBG_BREAK_MAPPING(new_break.id, class_table); } else { - phpdbg_notice("Breakpoint exists at %s::%s", class_name, func_name); + phpdbg_error("breakpoint", "type=\"exists\" add=\"fail\" method=\"%s::%s\"", "Breakpoint exists at %s::%s", class_name, func_name); } - efree(lcname); + efree(func_lcname); + efree(class_lcname); } /* }}} */ -PHPDBG_API void phpdbg_set_breakpoint_opline(zend_ulong opline TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_set_breakpoint_opline(zend_ulong opline) /* {{{ */ { if (!zend_hash_index_exists(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], opline)) { phpdbg_breakline_t new_break; @@ -347,27 +464,25 @@ PHPDBG_API void phpdbg_set_breakpoint_opline(zend_ulong opline TSRMLS_DC) /* {{{ new_break.opline = opline; new_break.base = NULL; - zend_hash_index_update(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], opline, - &new_break, sizeof(phpdbg_breakline_t), NULL); + zend_hash_index_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], opline, &new_break, sizeof(phpdbg_breakline_t)); - phpdbg_notice("Breakpoint #%d added at %#lx", - new_break.id, new_break.opline); + phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" opline=\"%#lx\"", "Breakpoint #%d added at %#lx", new_break.id, new_break.opline); PHPDBG_BREAK_MAPPING(new_break.id, &PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]); } else { - phpdbg_notice("Breakpoint exists at %#lx", opline); + phpdbg_error("breakpoint", "type=\"exists\" add=\"fail\" opline=\"%#lx\"", "Breakpoint exists at %#lx", opline); } } /* }}} */ -PHPDBG_API int phpdbg_resolve_op_array_break(phpdbg_breakopline_t *brake, zend_op_array *op_array TSRMLS_DC) /* {{{ */ +PHPDBG_API int phpdbg_resolve_op_array_break(phpdbg_breakopline_t *brake, zend_op_array *op_array) /* {{{ */ { phpdbg_breakline_t opline_break; if (op_array->last <= brake->opline_num) { if (brake->class_name == NULL) { - phpdbg_error("There are only %d oplines in function %s (breaking at opline %ld impossible)", op_array->last, brake->func_name, brake->opline_num); + phpdbg_error("breakpoint", "type=\"maxoplines\" add=\"fail\" maxoplinenum=\"%d\" function=\"%s\" usedoplinenum=\"%ld\"", "There are only %d oplines in function %s (breaking at opline %ld impossible)", op_array->last, brake->func_name, brake->opline_num); } else if (brake->func_name == NULL) { - phpdbg_error("There are only %d oplines in file %s (breaking at opline %ld impossible)", op_array->last, brake->class_name, brake->opline_num); + phpdbg_error("breakpoint", "type=\"maxoplines\" add=\"fail\" maxoplinenum=\"%d\" file=\"%s\" usedoplinenum=\"%ld\"", "There are only %d oplines in file %s (breaking at opline %ld impossible)", op_array->last, brake->class_name, brake->opline_num); } else { - phpdbg_error("There are only %d oplines in method %s::%s (breaking at opline %ld impossible)", op_array->last, brake->class_name, brake->func_name, brake->opline_num); + phpdbg_error("breakpoint", "type=\"maxoplines\" add=\"fail\" maxoplinenum=\"%d\" method=\"%s::%s\" usedoplinenum=\"%ld\"", "There are only %d oplines in method %s::%s (breaking at opline %ld impossible)", op_array->last, brake->class_name, brake->func_name, brake->opline_num); } return FAILURE; @@ -389,52 +504,48 @@ PHPDBG_API int phpdbg_resolve_op_array_break(phpdbg_breakopline_t *brake, zend_o PHPDBG_G(flags) |= PHPDBG_HAS_OPLINE_BP; - zend_hash_index_update(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], opline_break.opline, &opline_break, sizeof(phpdbg_breakline_t), NULL); + zend_hash_index_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], opline_break.opline, &opline_break, sizeof(phpdbg_breakline_t)); return SUCCESS; } /* }}} */ -PHPDBG_API void phpdbg_resolve_op_array_breaks(zend_op_array *op_array TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_resolve_op_array_breaks(zend_op_array *op_array) /* {{{ */ { HashTable *func_table = &PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE]; HashTable *oplines_table; - HashPosition position; phpdbg_breakopline_t *brake; - if (op_array->scope != NULL && - zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], op_array->scope->name, op_array->scope->name_length, (void **)&func_table) == FAILURE) { + if (op_array->scope != NULL && !(func_table = zend_hash_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], op_array->scope->name))) { return; } if (op_array->function_name == NULL) { - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], op_array->filename, strlen(op_array->filename), (void **)&oplines_table) == FAILURE) { + if (!(oplines_table = zend_hash_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], op_array->filename))) { return; } - } else if (zend_hash_find(func_table, op_array->function_name?op_array->function_name:"", op_array->function_name?strlen(op_array->function_name):0, (void **)&oplines_table) == FAILURE) { + } else if (!op_array->function_name || !(oplines_table = zend_hash_find_ptr(func_table, op_array->function_name))) { return; } - for (zend_hash_internal_pointer_reset_ex(oplines_table, &position); - zend_hash_get_current_data_ex(oplines_table, (void**) &brake, &position) == SUCCESS; - zend_hash_move_forward_ex(oplines_table, &position)) { - if (phpdbg_resolve_op_array_break(brake, op_array TSRMLS_CC) == SUCCESS) { + ZEND_HASH_FOREACH_PTR(oplines_table, brake) { + if (phpdbg_resolve_op_array_break(brake, op_array) == SUCCESS) { phpdbg_breakline_t *opline_break; zend_hash_internal_pointer_end(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]); - zend_hash_get_current_data(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], (void **)&opline_break); + opline_break = zend_hash_get_current_data_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]); - phpdbg_notice("Breakpoint #%d resolved at %s%s%s#%ld (opline %#lx)", - brake->id, - brake->class_name?brake->class_name:"", - brake->class_name&&brake->func_name?"::":"", - brake->func_name?brake->func_name:"", + phpdbg_notice("breakpoint", "add=\"success\" id=\"%d\" symbol=\"%s\" num=\"%ld\" opline=\"%#lx\"", "Breakpoint #%d resolved at %s%s%s#%ld (opline %#lx)", + opline_break->id, + brake->class_name ? brake->class_name : "", + brake->class_name && brake->func_name ? "::" : "", + brake->func_name ? brake->func_name : "", brake->opline_num, - brake->opline); + opline_break->opline); } - } + } ZEND_HASH_FOREACH_END(); } /* }}} */ -PHPDBG_API int phpdbg_resolve_opline_break(phpdbg_breakopline_t *new_break TSRMLS_DC) /* {{{ */ +PHPDBG_API int phpdbg_resolve_opline_break(phpdbg_breakopline_t *new_break) /* {{{ */ { HashTable *func_table = EG(function_table); zend_function *func; @@ -442,7 +553,7 @@ PHPDBG_API int phpdbg_resolve_opline_break(phpdbg_breakopline_t *new_break TSRML if (new_break->func_name == NULL) { if (EG(current_execute_data) == NULL) { if (PHPDBG_G(ops) != NULL && !memcmp(PHPDBG_G(ops)->filename, new_break->class_name, new_break->class_len)) { - if (phpdbg_resolve_op_array_break(new_break, PHPDBG_G(ops) TSRMLS_CC) == SUCCESS) { + if (phpdbg_resolve_op_array_break(new_break, PHPDBG_G(ops)) == SUCCESS) { return SUCCESS; } else { return 2; @@ -452,11 +563,14 @@ PHPDBG_API int phpdbg_resolve_opline_break(phpdbg_breakopline_t *new_break TSRML } else { zend_execute_data *execute_data = EG(current_execute_data); do { - if (execute_data->op_array->function_name == NULL && execute_data->op_array->scope == NULL && !memcmp(execute_data->op_array->filename, new_break->class_name, new_break->class_len)) { - if (phpdbg_resolve_op_array_break(new_break, execute_data->op_array TSRMLS_CC) == SUCCESS) { - return SUCCESS; - } else { - return 2; + if (ZEND_USER_CODE(execute_data->func->common.type)) { + zend_op_array *op_array = &execute_data->func->op_array; + if (op_array->function_name == NULL && op_array->scope == NULL && new_break->class_len == ZSTR_LEN(op_array->filename) && !memcmp(ZSTR_VAL(op_array->filename), new_break->class_name, new_break->class_len)) { + if (phpdbg_resolve_op_array_break(new_break, op_array) == SUCCESS) { + return SUCCESS; + } else { + return 2; + } } } } while ((execute_data = execute_data->prev_execute_data) != NULL); @@ -465,16 +579,16 @@ PHPDBG_API int phpdbg_resolve_opline_break(phpdbg_breakopline_t *new_break TSRML } if (new_break->class_name != NULL) { - zend_class_entry **ce; - if (zend_hash_find(EG(class_table), zend_str_tolower_dup(new_break->class_name, new_break->class_len), new_break->class_len + 1, (void **)&ce) == FAILURE) { + zend_class_entry *ce; + if (!(ce = zend_hash_str_find_ptr(EG(class_table), zend_str_tolower_dup(new_break->class_name, new_break->class_len), new_break->class_len))) { return FAILURE; } - func_table = &(*ce)->function_table; + func_table = &ce->function_table; } - if (zend_hash_find(func_table, zend_str_tolower_dup(new_break->func_name, new_break->func_len), new_break->func_len + 1, (void **)&func) == FAILURE) { + if (!(func = zend_hash_str_find_ptr(func_table, zend_str_tolower_dup(new_break->func_name, new_break->func_len), new_break->func_len))) { if (new_break->class_name != NULL && new_break->func_name != NULL) { - phpdbg_error("Method %s doesn't exist in class %s", new_break->func_name, new_break->class_name); + phpdbg_error("breakpoint", "type=\"nomethod\" method=\"%s::%s\"", "Method %s doesn't exist in class %s", new_break->func_name, new_break->class_name); return 2; } return FAILURE; @@ -482,21 +596,23 @@ PHPDBG_API int phpdbg_resolve_opline_break(phpdbg_breakopline_t *new_break TSRML if (func->type != ZEND_USER_FUNCTION) { if (new_break->class_name == NULL) { - phpdbg_error("%s is not an user defined function, no oplines exist", new_break->func_name); + phpdbg_error("breakpoint", "type=\"internalfunction\" function=\"%s\"", "%s is not a user defined function, no oplines exist", new_break->func_name); } else { - phpdbg_error("%s::%s is not an user defined method, no oplines exist", new_break->class_name, new_break->func_name); + phpdbg_error("breakpoint", "type=\"internalfunction\" method=\"%s::%s\"", "%s::%s is not a user defined method, no oplines exist", new_break->class_name, new_break->func_name); } return 2; } - if (phpdbg_resolve_op_array_break(new_break, &func->op_array TSRMLS_CC) == FAILURE) { + if (phpdbg_resolve_op_array_break(new_break, &func->op_array) == FAILURE) { return 2; } return SUCCESS; } /* }}} */ -PHPDBG_API void phpdbg_set_breakpoint_method_opline(const char *class, const char *method, zend_ulong opline TSRMLS_DC) /* {{{ */ +/* TODO ... method/function oplines need to be normalized (leading backslash, lowercase) and file oplines need to be resolved properly */ + +PHPDBG_API void phpdbg_set_breakpoint_method_opline(const char *class, const char *method, zend_ulong opline) /* {{{ */ { phpdbg_breakopline_t new_break; HashTable class_breaks, *class_table; @@ -510,39 +626,31 @@ PHPDBG_API void phpdbg_set_breakpoint_method_opline(const char *class, const cha new_break.opline_num = opline; new_break.opline = 0; - switch (phpdbg_resolve_opline_break(&new_break TSRMLS_CC)) { + switch (phpdbg_resolve_opline_break(&new_break)) { case FAILURE: - phpdbg_notice("Pending breakpoint #%d at %s::%s#%ld", new_break.id, new_break.class_name, new_break.func_name, opline); + phpdbg_notice("breakpoint", "pending=\"pending\" id=\"%d\" method=\"%::%s\" num=\"%ld\"", "Pending breakpoint #%d at %s::%s#%ld", new_break.id, new_break.class_name, new_break.func_name, opline); break; case SUCCESS: - phpdbg_notice("Breakpoint #%d added at %s::%s#%ld", new_break.id, new_break.class_name, new_break.func_name, opline); + phpdbg_notice("breakpoint", "id=\"%d\" method=\"%::%s\" num=\"%ld\"", "Breakpoint #%d added at %s::%s#%ld", new_break.id, new_break.class_name, new_break.func_name, opline); break; case 2: return; } - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], new_break.class_name, new_break.class_len, (void **)&class_table) == FAILURE) { + if (!(class_table = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], new_break.class_name, new_break.class_len))) { zend_hash_init(&class_breaks, 8, NULL, phpdbg_opline_class_breaks_dtor, 0); - zend_hash_update( - &PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], - new_break.class_name, - new_break.class_len, - (void **)&class_breaks, sizeof(HashTable), (void **)&class_table); + class_table = zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], new_break.class_name, new_break.class_len, &class_breaks, sizeof(HashTable)); } - if (zend_hash_find(class_table, new_break.func_name, new_break.func_len, (void **)&method_table) == FAILURE) { + if (!(method_table = zend_hash_str_find_ptr(class_table, new_break.func_name, new_break.func_len))) { zend_hash_init(&method_breaks, 8, NULL, phpdbg_opline_breaks_dtor, 0); - zend_hash_update( - class_table, - new_break.func_name, - new_break.func_len, - (void **)&method_breaks, sizeof(HashTable), (void **)&method_table); + method_table = zend_hash_str_update_mem(class_table, new_break.func_name, new_break.func_len, &method_breaks, sizeof(HashTable)); } if (zend_hash_index_exists(method_table, opline)) { - phpdbg_notice("Breakpoint already exists for %s::%s#%ld", new_break.class_name, new_break.func_name, opline); + phpdbg_error("breakpoint", "type=\"exists\" method=\"%s\" num=\"%ld\"", "Breakpoint already exists for %s::%s#%ld", new_break.class_name, new_break.func_name, opline); efree((char*)new_break.func_name); efree((char*)new_break.class_name); PHPDBG_G(bp_count)--; @@ -553,10 +661,11 @@ PHPDBG_API void phpdbg_set_breakpoint_method_opline(const char *class, const cha PHPDBG_BREAK_MAPPING(new_break.id, method_table); - zend_hash_index_update(method_table, opline, &new_break, sizeof(phpdbg_breakopline_t), NULL); + zend_hash_index_update_mem(method_table, opline, &new_break, sizeof(phpdbg_breakopline_t)); } +/* }}} */ -PHPDBG_API void phpdbg_set_breakpoint_function_opline(const char *function, zend_ulong opline TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_set_breakpoint_function_opline(const char *function, zend_ulong opline) /* {{{ */ { phpdbg_breakopline_t new_break; HashTable func_breaks, *func_table; @@ -569,30 +678,26 @@ PHPDBG_API void phpdbg_set_breakpoint_function_opline(const char *function, zend new_break.opline_num = opline; new_break.opline = 0; - switch (phpdbg_resolve_opline_break(&new_break TSRMLS_CC)) { + switch (phpdbg_resolve_opline_break(&new_break)) { case FAILURE: - phpdbg_notice("Pending breakpoint #%d at %s#%ld", new_break.id, new_break.func_name, opline); + phpdbg_notice("breakpoint", "pending=\"pending\" id=\"%d\" function=\"%s\" num=\"%ld\"", "Pending breakpoint #%d at %s#%ld", new_break.id, new_break.func_name, opline); break; case SUCCESS: - phpdbg_notice("Breakpoint #%d added at %s#%ld", new_break.id, new_break.func_name, opline); + phpdbg_notice("breakpoint", "id=\"%d\" function=\"%s\" num=\"%ld\"", "Breakpoint #%d added at %s#%ld", new_break.id, new_break.func_name, opline); break; case 2: return; } - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], new_break.func_name, new_break.func_len, (void **)&func_table) == FAILURE) { + if (!(func_table = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], new_break.func_name, new_break.func_len))) { zend_hash_init(&func_breaks, 8, NULL, phpdbg_opline_breaks_dtor, 0); - zend_hash_update( - &PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], - new_break.func_name, - new_break.func_len, - (void **)&func_breaks, sizeof(HashTable), (void **)&func_table); + func_table = zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], new_break.func_name, new_break.func_len, &func_breaks, sizeof(HashTable)); } if (zend_hash_index_exists(func_table, opline)) { - phpdbg_notice("Breakpoint already exists for %s#%ld", new_break.func_name, opline); + phpdbg_error("breakpoint", "type=\"exists\" function=\"%s\" num=\"%ld\"", "Breakpoint already exists for %s#%ld", new_break.func_name, opline); efree((char*)new_break.func_name); PHPDBG_G(bp_count)--; return; @@ -602,10 +707,11 @@ PHPDBG_API void phpdbg_set_breakpoint_function_opline(const char *function, zend PHPDBG_G(flags) |= PHPDBG_HAS_FUNCTION_OPLINE_BP; - zend_hash_index_update(func_table, opline, &new_break, sizeof(phpdbg_breakopline_t), NULL); + zend_hash_index_update_mem(func_table, opline, &new_break, sizeof(phpdbg_breakopline_t)); } +/* }}} */ -PHPDBG_API void phpdbg_set_breakpoint_file_opline(const char *file, zend_ulong opline TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_set_breakpoint_file_opline(const char *file, zend_ulong opline) /* {{{ */ { phpdbg_breakopline_t new_break; HashTable file_breaks, *file_table; @@ -618,30 +724,26 @@ PHPDBG_API void phpdbg_set_breakpoint_file_opline(const char *file, zend_ulong o new_break.opline_num = opline; new_break.opline = 0; - switch (phpdbg_resolve_opline_break(&new_break TSRMLS_CC)) { + switch (phpdbg_resolve_opline_break(&new_break)) { case FAILURE: - phpdbg_notice("Pending breakpoint #%d at %s:%ld", new_break.id, new_break.class_name, opline); + phpdbg_notice("breakpoint", "pending=\"pending\" id=\"%d\" file=\"%s\" num=\"%ld\"", "Pending breakpoint #%d at %s:%ld", new_break.id, new_break.class_name, opline); break; case SUCCESS: - phpdbg_notice("Breakpoint #%d added at %s:%ld", new_break.id, new_break.class_name, opline); + phpdbg_notice("breakpoint", "id=\"%d\" file=\"%s\" num=\"%ld\"", "Breakpoint #%d added at %s:%ld", new_break.id, new_break.class_name, opline); break; case 2: return; } - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], new_break.class_name, new_break.class_len, (void **)&file_table) == FAILURE) { + if (!(file_table = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], new_break.class_name, new_break.class_len))) { zend_hash_init(&file_breaks, 8, NULL, phpdbg_opline_breaks_dtor, 0); - zend_hash_update( - &PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], - new_break.class_name, - new_break.class_len, - (void **)&file_breaks, sizeof(HashTable), (void **)&file_table); + file_table = zend_hash_str_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], new_break.class_name, new_break.class_len, &file_breaks, sizeof(HashTable)); } if (zend_hash_index_exists(file_table, opline)) { - phpdbg_notice("Breakpoint already exists for %s:%ld", new_break.class_name, opline); + phpdbg_error("breakpoint", "type=\"exists\" file=\"%s\" num=\"%d\"", "Breakpoint already exists for %s:%ld", new_break.class_name, opline); efree((char*)new_break.class_name); PHPDBG_G(bp_count)--; return; @@ -651,17 +753,17 @@ PHPDBG_API void phpdbg_set_breakpoint_file_opline(const char *file, zend_ulong o PHPDBG_G(flags) |= PHPDBG_HAS_FILE_OPLINE_BP; - zend_hash_index_update(file_table, opline, &new_break, sizeof(phpdbg_breakopline_t), NULL); + zend_hash_index_update_mem(file_table, opline, &new_break, sizeof(phpdbg_breakopline_t)); } +/* }}} */ -PHPDBG_API void phpdbg_set_breakpoint_opcode(const char *name, size_t name_len TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_set_breakpoint_opcode(const char *name, size_t name_len) /* {{{ */ { phpdbg_breakop_t new_break; zend_ulong hash = zend_hash_func(name, name_len); if (zend_hash_index_exists(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], hash)) { - phpdbg_notice( - "Breakpoint exists for %s", name); + phpdbg_error("breakpoint", "type=\"exists\" opcode=\"%s\"", "Breakpoint exists for %s", name); return; } @@ -669,16 +771,15 @@ PHPDBG_API void phpdbg_set_breakpoint_opcode(const char *name, size_t name_len T new_break.hash = hash; new_break.name = estrndup(name, name_len); - zend_hash_index_update(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], hash, - &new_break, sizeof(phpdbg_breakop_t), NULL); + zend_hash_index_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], hash, &new_break, sizeof(phpdbg_breakop_t)); PHPDBG_G(flags) |= PHPDBG_HAS_OPCODE_BP; - phpdbg_notice("Breakpoint #%d added at %s", new_break.id, name); + phpdbg_notice("breakpoint", "id=\"%d\" opcode=\"%s\"", "Breakpoint #%d added at %s", new_break.id, name); PHPDBG_BREAK_MAPPING(new_break.id, &PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE]); } /* }}} */ -PHPDBG_API void phpdbg_set_breakpoint_opline_ex(phpdbg_opline_ptr_t opline TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_set_breakpoint_opline_ex(phpdbg_opline_ptr_t opline) /* {{{ */ { if (!zend_hash_index_exists(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], (zend_ulong) opline)) { phpdbg_breakline_t new_break; @@ -689,19 +790,19 @@ PHPDBG_API void phpdbg_set_breakpoint_opline_ex(phpdbg_opline_ptr_t opline TSRML new_break.opline = (zend_ulong) opline; new_break.base = NULL; - zend_hash_index_update(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], - (zend_ulong) opline, &new_break, sizeof(phpdbg_breakline_t), NULL); + zend_hash_index_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], (zend_ulong) opline, &new_break, sizeof(phpdbg_breakline_t)); - phpdbg_notice("Breakpoint #%d added at %#lx", - new_break.id, new_break.opline); + phpdbg_notice("breakpoint", "id=\"%d\" opline=\"%#lx\"", "Breakpoint #%d added at %#lx", new_break.id, new_break.opline); PHPDBG_BREAK_MAPPING(new_break.id, &PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]); + } else { + phpdbg_error("breakpoint", "type=\"exists\" opline=\"%#lx\"", "Breakpoint exists for opline %#lx", (zend_ulong) opline); } } /* }}} */ -static inline void phpdbg_create_conditional_break(phpdbg_breakcond_t *brake, const phpdbg_param_t *param, const char *expr, size_t expr_len, zend_ulong hash TSRMLS_DC) /* {{{ */ +static inline void phpdbg_create_conditional_break(phpdbg_breakcond_t *brake, const phpdbg_param_t *param, const char *expr, size_t expr_len, zend_ulong hash) /* {{{ */ { phpdbg_breakcond_t new_break; - zend_uint cops = CG(compiler_options); + uint32_t cops = CG(compiler_options); zval pv; PHPDBG_BREAK_INIT(new_break, PHPDBG_BREAK_COND); @@ -710,7 +811,7 @@ static inline void phpdbg_create_conditional_break(phpdbg_breakcond_t *brake, co if (param) { new_break.paramed = 1; phpdbg_copy_param( - param, &new_break.param TSRMLS_CC); + param, &new_break.param); } else { new_break.paramed = 0; } @@ -722,176 +823,165 @@ static inline void phpdbg_create_conditional_break(phpdbg_breakcond_t *brake, co new_break.code = estrndup(expr, expr_len); new_break.code_len = expr_len; - Z_STRLEN(pv) = expr_len + sizeof("return ;") - 1; - Z_STRVAL(pv) = emalloc(Z_STRLEN(pv) + 1); + Z_STR(pv) = zend_string_alloc(expr_len + sizeof("return ;") - 1, 0); memcpy(Z_STRVAL(pv), "return ", sizeof("return ") - 1); memcpy(Z_STRVAL(pv) + sizeof("return ") - 1, expr, expr_len); Z_STRVAL(pv)[Z_STRLEN(pv) - 1] = ';'; Z_STRVAL(pv)[Z_STRLEN(pv)] = '\0'; - Z_TYPE(pv) = IS_STRING; + Z_TYPE_INFO(pv) = IS_STRING; - new_break.ops = zend_compile_string( - &pv, "Conditional Breakpoint Code" TSRMLS_CC); + new_break.ops = zend_compile_string(&pv, "Conditional Breakpoint Code"); zval_dtor(&pv); if (new_break.ops) { - zend_hash_index_update( - &PHPDBG_G(bp)[PHPDBG_BREAK_COND], hash, &new_break, - sizeof(phpdbg_breakcond_t), (void**)&brake); + brake = zend_hash_index_update_mem(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], hash, &new_break, sizeof(phpdbg_breakcond_t)); - phpdbg_notice("Conditional breakpoint #%d added %s/%p", - brake->id, brake->code, brake->ops); + phpdbg_notice("breakpoint", "id=\"%d\" expression=\"%s\" ptr=\"%p\"", "Conditional breakpoint #%d added %s/%p", brake->id, brake->code, brake->ops); PHPDBG_G(flags) |= PHPDBG_HAS_COND_BP; PHPDBG_BREAK_MAPPING(new_break.id, &PHPDBG_G(bp)[PHPDBG_BREAK_COND]); } else { - phpdbg_error( - "Failed to compile code for expression %s", expr); + phpdbg_error("compile", "expression=\"%s\"", "Failed to compile code for expression %s", expr); efree((char*)new_break.code); PHPDBG_G(bp_count)--; } + CG(compiler_options) = cops; } /* }}} */ -PHPDBG_API void phpdbg_set_breakpoint_expression(const char *expr, size_t expr_len TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_set_breakpoint_expression(const char *expr, size_t expr_len) /* {{{ */ { zend_ulong expr_hash = zend_inline_hash_func(expr, expr_len); phpdbg_breakcond_t new_break; if (!zend_hash_index_exists(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], expr_hash)) { phpdbg_create_conditional_break( - &new_break, NULL, expr, expr_len, expr_hash TSRMLS_CC); + &new_break, NULL, expr, expr_len, expr_hash); } else { - phpdbg_notice("Conditional break %s exists", expr); + phpdbg_error("breakpoint", "type=\"exists\" expression=\"%s\"", "Conditional break %s exists", expr); } } /* }}} */ -PHPDBG_API void phpdbg_set_breakpoint_at(const phpdbg_param_t *param TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_set_breakpoint_at(const phpdbg_param_t *param) /* {{{ */ { phpdbg_breakcond_t new_break; phpdbg_param_t *condition; zend_ulong hash = 0L; - + if (param->next) { condition = param->next; hash = zend_inline_hash_func(condition->str, condition->len); - + if (!zend_hash_index_exists(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], hash)) { - phpdbg_create_conditional_break( - &new_break, param, - condition->str, condition->len, hash TSRMLS_CC); + phpdbg_create_conditional_break(&new_break, param, condition->str, condition->len, hash); } else { - phpdbg_notice( - "Conditional break %s exists at the specified location", condition->str); - } + phpdbg_notice("breakpoint", "type=\"exists\" arg=\"%s\"", "Conditional break %s exists at the specified location", condition->str); + } } - + } /* }}} */ -static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_file(zend_op_array *op_array TSRMLS_DC) /* {{{ */ +static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_file(zend_op_array *op_array) /* {{{ */ { HashTable *breaks; phpdbg_breakbase_t *brake; - size_t name_len = strlen(op_array->filename); + size_t path_len; + char realpath[MAXPATHLEN]; + const char *path = ZSTR_VAL(op_array->filename); + + if (VCWD_REALPATH(path, realpath)) { + path = realpath; + } + + path_len = strlen(path); - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], op_array->filename, - name_len, (void**)&breaks) == FAILURE) { +#if 0 + phpdbg_debug("Op at: %.*s %d\n", path_len, path, (*EG(opline_ptr))->lineno); +#endif + + if (!(breaks = zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], path, path_len))) { return NULL; } - if (zend_hash_index_find(breaks, (*EG(opline_ptr))->lineno, (void**)&brake) == SUCCESS) { + if (EG(current_execute_data) && (brake = zend_hash_index_find_ptr(breaks, EG(current_execute_data)->opline->lineno))) { return brake; } return NULL; } /* }}} */ -static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_symbol(zend_function *fbc TSRMLS_DC) /* {{{ */ +static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_symbol(zend_function *fbc) /* {{{ */ { - const char *fname; zend_op_array *ops; - phpdbg_breakbase_t *brake; if (fbc->type != ZEND_USER_FUNCTION) { return NULL; } - ops = (zend_op_array*)fbc; + ops = (zend_op_array *) fbc; if (ops->scope) { /* find method breaks here */ - return phpdbg_find_breakpoint_method(ops TSRMLS_CC); + return phpdbg_find_breakpoint_method(ops); } - fname = ops->function_name; + if (ops->function_name) { + phpdbg_breakbase_t *brake; + zend_string *fname = zend_string_tolower(ops->function_name); - if (!fname) { - fname = "main"; - } + brake = zend_hash_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], fname); - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], fname, strlen(fname), (void**)&brake) == SUCCESS) { + zend_string_release(fname); return brake; + } else { + return zend_hash_str_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], ZEND_STRL("main")); } - - return NULL; } /* }}} */ -static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_method(zend_op_array *ops TSRMLS_DC) /* {{{ */ +static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_method(zend_op_array *ops) /* {{{ */ { HashTable *class_table; - phpdbg_breakbase_t *brake; + phpdbg_breakbase_t *brake = NULL; + zend_string *class_lcname = zend_string_tolower(ops->scope->name); - if (zend_hash_find(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], ops->scope->name, - ops->scope->name_length, (void**)&class_table) == SUCCESS) { - char *lcname = zend_str_tolower_dup(ops->function_name, strlen(ops->function_name)); - size_t lcname_len = strlen(lcname); - - if (zend_hash_find( - class_table, - lcname, - lcname_len, (void**)&brake) == SUCCESS) { - efree(lcname); - return brake; - } + if ((class_table = zend_hash_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], class_lcname))) { + zend_string *lcname = zend_string_tolower(ops->function_name); - efree(lcname); + brake = zend_hash_find_ptr(class_table, lcname); + + zend_string_release(lcname); } - return NULL; + zend_string_release(class_lcname); + return brake; } /* }}} */ -static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_opline(phpdbg_opline_ptr_t opline TSRMLS_DC) /* {{{ */ +static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_opline(phpdbg_opline_ptr_t opline) /* {{{ */ { phpdbg_breakline_t *brake; - if (zend_hash_index_find(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], - (zend_ulong) opline, (void**)&brake) == SUCCESS) { - return (brake->base?(phpdbg_breakbase_t *)brake->base:(phpdbg_breakbase_t *)brake); + if ((brake = zend_hash_index_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], (zend_ulong) opline)) && brake->base) { + return (phpdbg_breakbase_t *)brake->base; } - return NULL; + return (phpdbg_breakbase_t *) brake; } /* }}} */ -static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_opcode(zend_uchar opcode TSRMLS_DC) /* {{{ */ +static inline phpdbg_breakbase_t *phpdbg_find_breakpoint_opcode(zend_uchar opcode) /* {{{ */ { - phpdbg_breakbase_t *brake; - const char *opname = phpdbg_decode_opcode(opcode); + const char *opname = zend_get_opcode_name(opcode); - if (memcmp(opname, PHPDBG_STRL("UNKNOWN")) == 0) { + if (!opname) { return NULL; } - if (zend_hash_index_find(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], - zend_hash_func(opname, strlen(opname)), (void**)&brake) == SUCCESS) { - return brake; - } - return NULL; + return zend_hash_index_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], zend_hash_func(opname, strlen(opname))); } /* }}} */ -static inline zend_bool phpdbg_find_breakpoint_param(phpdbg_param_t *param, zend_execute_data *execute_data TSRMLS_DC) /* {{{ */ +static inline zend_bool phpdbg_find_breakpoint_param(phpdbg_param_t *param, zend_execute_data *execute_data) /* {{{ */ { - zend_function *function = (zend_function*) execute_data->function_state.function; + zend_function *function = execute_data->func; switch (param->type) { case NUMERIC_FUNCTION_PARAM: @@ -906,8 +996,8 @@ static inline zend_bool phpdbg_find_breakpoint_param(phpdbg_param_t *param, zend const char *str = NULL; size_t len = 0L; zend_op_array *ops = (zend_op_array*)function; - str = ops->function_name ? ops->function_name : "main"; - len = strlen(str); + str = ops->function_name ? ZSTR_VAL(ops->function_name) : "main"; + len = ops->function_name ? ZSTR_LEN(ops->function_name) : strlen(str); if (len == param->len && memcmp(param->str, str, len) == SUCCESS) { return param->type == STR_PARAM || execute_data->opline - ops->opcodes == param->num; @@ -916,8 +1006,8 @@ static inline zend_bool phpdbg_find_breakpoint_param(phpdbg_param_t *param, zend } break; case FILE_PARAM: { - if (param->file.line == zend_get_executed_lineno(TSRMLS_C)) { - const char *str = zend_get_executed_filename(TSRMLS_C); + if (param->file.line == zend_get_executed_lineno()) { + const char *str = zend_get_executed_filename(); size_t lengths[2] = {strlen(param->file.name), strlen(str)}; if (lengths[0] == lengths[1]) { @@ -937,10 +1027,10 @@ static inline zend_bool phpdbg_find_breakpoint_param(phpdbg_param_t *param, zend zend_op_array *ops = (zend_op_array*) function; if (ops->scope) { - size_t lengths[2] = {strlen(param->method.class), ops->scope->name_length}; + size_t lengths[2] = { strlen(param->method.class), ZSTR_LEN(ops->scope->name) }; if (lengths[0] == lengths[1] && memcmp(param->method.class, ops->scope->name, lengths[0]) == SUCCESS) { lengths[0] = strlen(param->method.name); - lengths[1] = strlen(ops->function_name); + lengths[1] = ZSTR_LEN(ops->function_name); if (lengths[0] == lengths[1] && memcmp(param->method.name, ops->function_name, lengths[0]) == SUCCESS) { return param->type == METHOD_PARAM || (execute_data->opline - ops->opcodes) == param->num; @@ -961,80 +1051,54 @@ static inline zend_bool phpdbg_find_breakpoint_param(phpdbg_param_t *param, zend return 0; } /* }}} */ -static inline phpdbg_breakbase_t *phpdbg_find_conditional_breakpoint(zend_execute_data *execute_data TSRMLS_DC) /* {{{ */ +static inline phpdbg_breakbase_t *phpdbg_find_conditional_breakpoint(zend_execute_data *execute_data) /* {{{ */ { phpdbg_breakcond_t *bp; - HashPosition position; int breakpoint = FAILURE; - for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], &position); - zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], (void*)&bp, &position) == SUCCESS; - zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], &position)) { - zval *retval = NULL; - int orig_interactive = CG(interactive); - zval **orig_retval = EG(return_value_ptr_ptr); - zend_op_array *orig_ops = EG(active_op_array); - zend_op **orig_opline = EG(opline_ptr); + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], bp) { + zval retval; + const zend_op *orig_opline = EG(current_execute_data)->opline; + zend_function *orig_func = EG(current_execute_data)->func; + zval *orig_retval = EG(current_execute_data)->return_value; if (((phpdbg_breakbase_t*)bp)->disabled) { continue; } if (bp->paramed) { - if (!phpdbg_find_breakpoint_param(&bp->param, execute_data TSRMLS_CC)) { + if (!phpdbg_find_breakpoint_param(&bp->param, execute_data)) { continue; } } - ALLOC_INIT_ZVAL(retval); - - EG(return_value_ptr_ptr) = &retval; - EG(active_op_array) = bp->ops; EG(no_extensions) = 1; - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); - } - - CG(interactive) = 0; + zend_rebuild_symbol_table(); zend_try { PHPDBG_G(flags) |= PHPDBG_IN_COND_BP; - zend_execute(EG(active_op_array) TSRMLS_CC); -#if PHP_VERSION_ID >= 50700 - if (zend_is_true(retval TSRMLS_CC)) { -#else - if (zend_is_true(retval)) { -#endif + zend_execute(bp->ops, &retval); + if (zend_is_true(&retval)) { breakpoint = SUCCESS; } - } zend_catch { - CG(interactive) = orig_interactive; - - EG(no_extensions)=1; - EG(return_value_ptr_ptr) = orig_retval; - EG(active_op_array) = orig_ops; - EG(opline_ptr) = orig_opline; - PHPDBG_G(flags) &= ~PHPDBG_IN_COND_BP; } zend_end_try(); - CG(interactive) = orig_interactive; - - EG(no_extensions)=1; - EG(return_value_ptr_ptr) = orig_retval; - EG(active_op_array) = orig_ops; - EG(opline_ptr) = orig_opline; + EG(no_extensions) = 1; + EG(current_execute_data)->opline = orig_opline; + EG(current_execute_data)->func = orig_func; + EG(current_execute_data)->return_value = orig_retval; PHPDBG_G(flags) &= ~PHPDBG_IN_COND_BP; if (breakpoint == SUCCESS) { break; } - } + } ZEND_HASH_FOREACH_END(); - return (breakpoint == SUCCESS) ? ((phpdbg_breakbase_t*)bp) : NULL; + return (breakpoint == SUCCESS) ? ((phpdbg_breakbase_t *) bp) : NULL; } /* }}} */ -PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakpoint(zend_execute_data* execute_data TSRMLS_DC) /* {{{ */ +PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakpoint(zend_execute_data *execute_data) /* {{{ */ { phpdbg_breakbase_t *base = NULL; @@ -1045,32 +1109,29 @@ PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakpoint(zend_execute_data* execute /* conditions cannot be executed by eval()'d code */ if (!(PHPDBG_G(flags) & PHPDBG_IN_EVAL) && (PHPDBG_G(flags) & PHPDBG_HAS_COND_BP) && - (base = phpdbg_find_conditional_breakpoint(execute_data TSRMLS_CC))) { + (base = phpdbg_find_conditional_breakpoint(execute_data))) { goto result; } - if ((PHPDBG_G(flags) & PHPDBG_HAS_FILE_BP) && - (base = phpdbg_find_breakpoint_file(execute_data->op_array TSRMLS_CC))) { + if ((PHPDBG_G(flags) & PHPDBG_HAS_FILE_BP) && (base = phpdbg_find_breakpoint_file(&execute_data->func->op_array))) { goto result; } if (PHPDBG_G(flags) & (PHPDBG_HAS_METHOD_BP|PHPDBG_HAS_SYM_BP)) { - /* check we are at the beginning of the stack */ - if (execute_data->opline == EG(active_op_array)->opcodes) { - if ((base = phpdbg_find_breakpoint_symbol( - execute_data->function_state.function TSRMLS_CC))) { + zend_op_array *op_array = &execute_data->func->op_array; + /* check we are at the beginning of the stack, but after argument RECV */ + if (execute_data->opline == op_array->opcodes + op_array->num_args + !!(op_array->fn_flags & ZEND_ACC_VARIADIC)) { + if ((base = phpdbg_find_breakpoint_symbol(execute_data->func))) { goto result; } } } - if ((PHPDBG_G(flags) & PHPDBG_HAS_OPLINE_BP) && - (base = phpdbg_find_breakpoint_opline(execute_data->opline TSRMLS_CC))) { + if ((PHPDBG_G(flags) & PHPDBG_HAS_OPLINE_BP) && (base = phpdbg_find_breakpoint_opline((phpdbg_opline_ptr_t) execute_data->opline))) { goto result; } - if ((PHPDBG_G(flags) & PHPDBG_HAS_OPCODE_BP) && - (base = phpdbg_find_breakpoint_opcode(execute_data->opline->opcode TSRMLS_CC))) { + if ((PHPDBG_G(flags) & PHPDBG_HAS_OPCODE_BP) && (base = phpdbg_find_breakpoint_opcode(execute_data->opline->opcode))) { goto result; } @@ -1085,16 +1146,14 @@ result: return base; } /* }}} */ -PHPDBG_API void phpdbg_delete_breakpoint(zend_ulong num TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_delete_breakpoint(zend_ulong num) /* {{{ */ { - HashTable **table; - HashPosition position; + HashTable *table; phpdbg_breakbase_t *brake; + zend_string *strkey; + zend_ulong numkey; - if ((brake = phpdbg_find_breakbase_ex(num, &table, &position TSRMLS_CC))) { - char *key; - zend_uint klen; - zend_ulong idx; + if ((brake = phpdbg_find_breakbase_ex(num, &table, &numkey, &strkey))) { int type = brake->type; char *name = NULL; size_t name_len = 0L; @@ -1102,7 +1161,7 @@ PHPDBG_API void phpdbg_delete_breakpoint(zend_ulong num TSRMLS_DC) /* {{{ */ switch (type) { case PHPDBG_BREAK_FILE: case PHPDBG_BREAK_METHOD: - if (zend_hash_num_elements((*table)) == 1) { + if (zend_hash_num_elements(table) == 1) { name = estrdup(brake->name); name_len = strlen(name); if (zend_hash_num_elements(&PHPDBG_G(bp)[type]) == 1) { @@ -1112,7 +1171,7 @@ PHPDBG_API void phpdbg_delete_breakpoint(zend_ulong num TSRMLS_DC) /* {{{ */ break; default: { - if (zend_hash_num_elements((*table)) == 1) { + if (zend_hash_num_elements(table) == 1) { PHPDBG_G(flags) &= ~(1<<(brake->type+1)); } } @@ -1125,40 +1184,36 @@ PHPDBG_API void phpdbg_delete_breakpoint(zend_ulong num TSRMLS_DC) /* {{{ */ if (zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]) == 1) { PHPDBG_G(flags) &= PHPDBG_HAS_OPLINE_BP; } - zend_hash_index_del(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], ((phpdbg_breakopline_t*)brake)->opline); + zend_hash_index_del(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], ((phpdbg_breakopline_t *) brake)->opline); } - switch (zend_hash_get_current_key_ex( - (*table), &key, &klen, &idx, 0, &position)) { - - case HASH_KEY_IS_STRING: - zend_hash_del((*table), key, klen); - break; - - default: - zend_hash_index_del((*table), idx); + if (strkey) { + zend_hash_del(table, strkey); + } else { + zend_hash_index_del(table, numkey); } switch (type) { case PHPDBG_BREAK_FILE: case PHPDBG_BREAK_METHOD: if (name) { - zend_hash_del(&PHPDBG_G(bp)[type], name, name_len); + zend_hash_str_del(&PHPDBG_G(bp)[type], name, name_len); efree(name); } break; } - phpdbg_notice("Deleted breakpoint #%ld", num); + phpdbg_notice("breakpoint", "deleted=\"success\" id=\"%ld\"", "Deleted breakpoint #%ld", num); PHPDBG_BREAK_UNMAPPING(num); } else { - phpdbg_error("Failed to find breakpoint #%ld", num); + phpdbg_error("breakpoint", "type=\"nobreakpoint\" deleted=\"fail\" id=\"%ld\"", "Failed to find breakpoint #%ld", num); } } /* }}} */ -PHPDBG_API void phpdbg_clear_breakpoints(TSRMLS_D) /* {{{ */ +PHPDBG_API void phpdbg_clear_breakpoints(void) /* {{{ */ { zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE]); + zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING]); zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM]); zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]); zend_hash_clean(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE]); @@ -1174,23 +1229,23 @@ PHPDBG_API void phpdbg_clear_breakpoints(TSRMLS_D) /* {{{ */ PHPDBG_G(bp_count) = 0; } /* }}} */ -PHPDBG_API void phpdbg_hit_breakpoint(phpdbg_breakbase_t *brake, zend_bool output TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_hit_breakpoint(phpdbg_breakbase_t *brake, zend_bool output) /* {{{ */ { brake->hits++; if (output) { - phpdbg_print_breakpoint(brake TSRMLS_CC); + phpdbg_print_breakpoint(brake); } } /* }}} */ -PHPDBG_API void phpdbg_print_breakpoint(phpdbg_breakbase_t *brake TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_print_breakpoint(phpdbg_breakbase_t *brake) /* {{{ */ { if (!brake) goto unknown; switch (brake->type) { case PHPDBG_BREAK_FILE: { - phpdbg_notice("Breakpoint #%d at %s:%ld, hits: %lu", + phpdbg_notice("breakpoint", "id=\"%d\" file=\"%s\" line=\"%ld\" hits=\"%lu\"", "Breakpoint #%d at %s:%ld, hits: %lu", ((phpdbg_breakfile_t*)brake)->id, ((phpdbg_breakfile_t*)brake)->filename, ((phpdbg_breakfile_t*)brake)->line, @@ -1198,91 +1253,90 @@ PHPDBG_API void phpdbg_print_breakpoint(phpdbg_breakbase_t *brake TSRMLS_DC) /* } break; case PHPDBG_BREAK_SYM: { - phpdbg_notice("Breakpoint #%d in %s() at %s:%u, hits: %lu", + phpdbg_notice("breakpoint", "id=\"%d\" function=\"%s\" file=\"%s\" line=\"%ld\" hits=\"%lu\"", "Breakpoint #%d in %s() at %s:%u, hits: %lu", ((phpdbg_breaksymbol_t*)brake)->id, ((phpdbg_breaksymbol_t*)brake)->symbol, - zend_get_executed_filename(TSRMLS_C), - zend_get_executed_lineno(TSRMLS_C), + zend_get_executed_filename(), + zend_get_executed_lineno(), ((phpdbg_breakfile_t*)brake)->hits); } break; case PHPDBG_BREAK_OPLINE: { - phpdbg_notice("Breakpoint #%d in %#lx at %s:%u, hits: %lu", + phpdbg_notice("breakpoint", "id=\"%d\" opline=\"%#lx\" file=\"%s\" line=\"%ld\" hits=\"%lu\"", "Breakpoint #%d in %#lx at %s:%u, hits: %lu", ((phpdbg_breakline_t*)brake)->id, ((phpdbg_breakline_t*)brake)->opline, - zend_get_executed_filename(TSRMLS_C), - zend_get_executed_lineno(TSRMLS_C), + zend_get_executed_filename(), + zend_get_executed_lineno(), ((phpdbg_breakline_t*)brake)->hits); } break; case PHPDBG_BREAK_METHOD_OPLINE: { - phpdbg_notice("Breakpoint #%d in %s::%s()#%lu at %s:%u, hits: %lu", + phpdbg_notice("breakpoint", "id=\"%d\" method=\"%s::%s\" num=\"%lu\" file=\"%s\" line=\"%ld\" hits=\"%lu\"", "Breakpoint #%d in %s::%s()#%lu at %s:%u, hits: %lu", ((phpdbg_breakopline_t*)brake)->id, ((phpdbg_breakopline_t*)brake)->class_name, ((phpdbg_breakopline_t*)brake)->func_name, ((phpdbg_breakopline_t*)brake)->opline_num, - zend_get_executed_filename(TSRMLS_C), - zend_get_executed_lineno(TSRMLS_C), + zend_get_executed_filename(), + zend_get_executed_lineno(), ((phpdbg_breakopline_t*)brake)->hits); } break; case PHPDBG_BREAK_FUNCTION_OPLINE: { - phpdbg_notice("Breakpoint #%d in %s()#%lu at %s:%u, hits: %lu", + phpdbg_notice("breakpoint", "id=\"%d\" num=\"%lu\" function=\"%s\" file=\"%s\" line=\"%ld\" hits=\"%lu\"", "Breakpoint #%d in %s()#%lu at %s:%u, hits: %lu", ((phpdbg_breakopline_t*)brake)->id, ((phpdbg_breakopline_t*)brake)->func_name, ((phpdbg_breakopline_t*)brake)->opline_num, - zend_get_executed_filename(TSRMLS_C), - zend_get_executed_lineno(TSRMLS_C), + zend_get_executed_filename(), + zend_get_executed_lineno(), ((phpdbg_breakopline_t*)brake)->hits); } break; case PHPDBG_BREAK_FILE_OPLINE: { - phpdbg_notice("Breakpoint #%d in %s:%lu at %s:%u, hits: %lu", + phpdbg_notice("breakpoint", "id=\"%d\" num=\"%lu\" file=\"%s\" line=\"%ld\" hits=\"%lu\"", "Breakpoint #%d in #%lu at %s:%u, hits: %lu", ((phpdbg_breakopline_t*)brake)->id, - ((phpdbg_breakopline_t*)brake)->class_name, ((phpdbg_breakopline_t*)brake)->opline_num, - zend_get_executed_filename(TSRMLS_C), - zend_get_executed_lineno(TSRMLS_C), + zend_get_executed_filename(), + zend_get_executed_lineno(), ((phpdbg_breakopline_t*)brake)->hits); } break; case PHPDBG_BREAK_OPCODE: { - phpdbg_notice("Breakpoint #%d in %s at %s:%u, hits: %lu", + phpdbg_notice("breakpoint", "id=\"%d\" opcode=\"%s\" file=\"%s\" line=\"%ld\" hits=\"%lu\"", "Breakpoint #%d in %s at %s:%u, hits: %lu", ((phpdbg_breakop_t*)brake)->id, ((phpdbg_breakop_t*)brake)->name, - zend_get_executed_filename(TSRMLS_C), - zend_get_executed_lineno(TSRMLS_C), + zend_get_executed_filename(), + zend_get_executed_lineno(), ((phpdbg_breakop_t*)brake)->hits); } break; case PHPDBG_BREAK_METHOD: { - phpdbg_notice("Breakpoint #%d in %s::%s() at %s:%u, hits: %lu", + phpdbg_notice("breakpoint", "id=\"%d\" method=\"%s::%s\" file=\"%s\" line=\"%ld\" hits=\"%lu\"", "Breakpoint #%d in %s::%s() at %s:%u, hits: %lu", ((phpdbg_breakmethod_t*)brake)->id, ((phpdbg_breakmethod_t*)brake)->class_name, ((phpdbg_breakmethod_t*)brake)->func_name, - zend_get_executed_filename(TSRMLS_C), - zend_get_executed_lineno(TSRMLS_C), + zend_get_executed_filename(), + zend_get_executed_lineno(), ((phpdbg_breakmethod_t*)brake)->hits); } break; case PHPDBG_BREAK_COND: { if (((phpdbg_breakcond_t*)brake)->paramed) { char *param; - phpdbg_notice("Conditional breakpoint #%d: at %s if %s %s:%u, hits: %lu", + phpdbg_notice("breakpoint", "id=\"%d\" location=\"%s\" eval=\"%s\" file=\"%s\" line=\"%ld\" hits=\"%lu\"", "Conditional breakpoint #%d: at %s if %s at %s:%u, hits: %lu", ((phpdbg_breakcond_t*)brake)->id, - phpdbg_param_tostring(&((phpdbg_breakcond_t*)brake)->param, ¶m TSRMLS_CC), + phpdbg_param_tostring(&((phpdbg_breakcond_t*)brake)->param, ¶m), ((phpdbg_breakcond_t*)brake)->code, - zend_get_executed_filename(TSRMLS_C), - zend_get_executed_lineno(TSRMLS_C), + zend_get_executed_filename(), + zend_get_executed_lineno(), ((phpdbg_breakcond_t*)brake)->hits); if (param) free(param); } else { - phpdbg_notice("Conditional breakpoint #%d: on %s == true %s:%u, hits: %lu", + phpdbg_notice("breakpoint", "id=\"%d\" eval=\"%s\" file=\"%s\" line=\"%ld\" hits=\"%lu\"", "Conditional breakpoint #%d: on %s == true at %s:%u, hits: %lu", ((phpdbg_breakcond_t*)brake)->id, ((phpdbg_breakcond_t*)brake)->code, - zend_get_executed_filename(TSRMLS_C), - zend_get_executed_lineno(TSRMLS_C), + zend_get_executed_filename(), + zend_get_executed_lineno(), ((phpdbg_breakcond_t*)brake)->hits); } @@ -1290,349 +1344,285 @@ PHPDBG_API void phpdbg_print_breakpoint(phpdbg_breakbase_t *brake TSRMLS_DC) /* default: { unknown: - phpdbg_notice("Unknown breakpoint at %s:%u", - zend_get_executed_filename(TSRMLS_C), - zend_get_executed_lineno(TSRMLS_C)); + phpdbg_notice("breakpoint", "id=\"\" file=\"%s\" line=\"%ld\" hits=\"%lu\"", "Unknown breakpoint at %s:%u", + zend_get_executed_filename(), + zend_get_executed_lineno()); } } } /* }}} */ -PHPDBG_API void phpdbg_enable_breakpoint(zend_ulong id TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_enable_breakpoint(zend_ulong id) /* {{{ */ { - phpdbg_breakbase_t *brake = phpdbg_find_breakbase(id TSRMLS_CC); + phpdbg_breakbase_t *brake = phpdbg_find_breakbase(id); if (brake) { brake->disabled = 0; } } /* }}} */ -PHPDBG_API void phpdbg_disable_breakpoint(zend_ulong id TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_disable_breakpoint(zend_ulong id) /* {{{ */ { - phpdbg_breakbase_t *brake = phpdbg_find_breakbase(id TSRMLS_CC); + phpdbg_breakbase_t *brake = phpdbg_find_breakbase(id); if (brake) { brake->disabled = 1; } } /* }}} */ -PHPDBG_API void phpdbg_enable_breakpoints(TSRMLS_D) /* {{{ */ +PHPDBG_API void phpdbg_enable_breakpoints(void) /* {{{ */ { PHPDBG_G(flags) |= PHPDBG_IS_BP_ENABLED; } /* }}} */ -PHPDBG_API void phpdbg_disable_breakpoints(TSRMLS_D) { /* {{{ */ +PHPDBG_API void phpdbg_disable_breakpoints(void) { /* {{{ */ PHPDBG_G(flags) &= ~PHPDBG_IS_BP_ENABLED; } /* }}} */ -PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakbase(zend_ulong id TSRMLS_DC) /* {{{ */ +PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakbase(zend_ulong id) /* {{{ */ { - HashTable **table; - HashPosition position; + HashTable *table; + zend_string *strkey; + zend_ulong numkey; - return phpdbg_find_breakbase_ex(id, &table, &position TSRMLS_CC); + return phpdbg_find_breakbase_ex(id, &table, &numkey, &strkey); } /* }}} */ -PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakbase_ex(zend_ulong id, HashTable ***table, HashPosition *position TSRMLS_DC) /* {{{ */ +PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakbase_ex(zend_ulong id, HashTable **table, zend_ulong *numkey, zend_string **strkey) /* {{{ */ { - if (zend_hash_index_find(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], id, (void**)table) == SUCCESS) { + if ((*table = zend_hash_index_find_ptr(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], id))) { phpdbg_breakbase_t *brake; - for (zend_hash_internal_pointer_reset_ex((**table), position); - zend_hash_get_current_data_ex((**table), (void**)&brake, position) == SUCCESS; - zend_hash_move_forward_ex((**table), position)) { - + ZEND_HASH_FOREACH_KEY_PTR(*table, *numkey, *strkey, brake) { if (brake->id == id) { return brake; } - } + } ZEND_HASH_FOREACH_END(); } + return NULL; } /* }}} */ -PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type) /* {{{ */ { + phpdbg_xml("<breakpoints %r>"); + switch (type) { case PHPDBG_BREAK_SYM: if ((PHPDBG_G(flags) & PHPDBG_HAS_SYM_BP)) { - HashPosition position; phpdbg_breaksymbol_t *brake; - phpdbg_writeln(SEPARATE); - phpdbg_writeln("Function Breakpoints:"); - for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], &position); - zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], (void**) &brake, &position) == SUCCESS; - zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], &position)) { - phpdbg_writeln("#%d\t\t%s%s", + phpdbg_out(SEPARATE "\n"); + phpdbg_out("Function Breakpoints:\n"); + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], brake) { + phpdbg_writeln("function", "id=\"%d\" name=\"%s\" disabled=\"%s\"", "#%d\t\t%s%s", brake->id, brake->symbol, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); - } + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); + } ZEND_HASH_FOREACH_END(); } break; case PHPDBG_BREAK_METHOD: if ((PHPDBG_G(flags) & PHPDBG_HAS_METHOD_BP)) { - HashPosition position[2]; HashTable *class_table; - char *class_name = NULL; - zend_uint class_len = 0; - zend_ulong class_idx = 0L; - - phpdbg_writeln(SEPARATE); - phpdbg_writeln("Method Breakpoints:"); - for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], &position[0]); - zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], (void**) &class_table, &position[0]) == SUCCESS; - zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], &position[0])) { - - if (zend_hash_get_current_key_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], - &class_name, &class_len, &class_idx, 0, &position[0]) == HASH_KEY_IS_STRING) { - phpdbg_breakmethod_t *brake; - - for (zend_hash_internal_pointer_reset_ex(class_table, &position[1]); - zend_hash_get_current_data_ex(class_table, (void**)&brake, &position[1]) == SUCCESS; - zend_hash_move_forward_ex(class_table, &position[1])) { - phpdbg_writeln("#%d\t\t%s::%s%s", - brake->id, brake->class_name, brake->func_name, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); - } - } - } + phpdbg_out(SEPARATE "\n"); + phpdbg_out("Method Breakpoints:\n"); + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], class_table) { + phpdbg_breakmethod_t *brake; + + ZEND_HASH_FOREACH_PTR(class_table, brake) { + phpdbg_writeln("method", "id=\"%d\" name=\"%s::%s\" disabled=\"%s\"", "#%d\t\t%s::%s%s", + brake->id, brake->class_name, brake->func_name, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); } break; case PHPDBG_BREAK_FILE: if ((PHPDBG_G(flags) & PHPDBG_HAS_FILE_BP)) { - HashPosition position[2]; HashTable *points; - phpdbg_writeln(SEPARATE); - phpdbg_writeln("File Breakpoints:"); - for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], &position[0]); - zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], (void**) &points, &position[0]) == SUCCESS; - zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], &position[0])) { + phpdbg_out(SEPARATE "\n"); + phpdbg_out("File Breakpoints:\n"); + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], points) { phpdbg_breakfile_t *brake; - for (zend_hash_internal_pointer_reset_ex(points, &position[1]); - zend_hash_get_current_data_ex(points, (void**)&brake, &position[1]) == SUCCESS; - zend_hash_move_forward_ex(points, &position[1])) { - phpdbg_writeln("#%d\t\t%s:%lu%s", + ZEND_HASH_FOREACH_PTR(points, brake) { + phpdbg_writeln("file", "id=\"%d\" name=\"%s\" line=\"%lu\" disabled=\"%s\"", "#%d\t\t%s:%lu%s", brake->id, brake->filename, brake->line, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); - } - } + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); + } if ((PHPDBG_G(flags) & PHPDBG_HAS_PENDING_FILE_BP)) { + HashTable *points; + phpdbg_out(SEPARATE "\n"); + phpdbg_out("Pending File Breakpoints:\n"); + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], points) { + phpdbg_breakfile_t *brake; + + ZEND_HASH_FOREACH_PTR(points, brake) { + phpdbg_writeln("file", "id=\"%d\" name=\"%s\" line=\"%lu\" disabled=\"%s\" pending=\"pending\"", "#%d\t\t%s:%lu%s", + brake->id, brake->filename, brake->line, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); } break; case PHPDBG_BREAK_OPLINE: if ((PHPDBG_G(flags) & PHPDBG_HAS_OPLINE_BP)) { - HashPosition position; phpdbg_breakline_t *brake; - phpdbg_writeln(SEPARATE); - phpdbg_writeln("Opline Breakpoints:"); - for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], &position); - zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], (void**) &brake, &position) == SUCCESS; - zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], &position)) { + phpdbg_out(SEPARATE "\n"); + phpdbg_out("Opline Breakpoints:\n"); + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], brake) { + const char *type; switch (brake->type) { case PHPDBG_BREAK_METHOD_OPLINE: + type = "method"; + goto print_opline; case PHPDBG_BREAK_FUNCTION_OPLINE: + type = "function"; + goto print_opline; case PHPDBG_BREAK_FILE_OPLINE: - phpdbg_writeln("#%d\t\t%#lx\t\t(%s breakpoint)%s", brake->id, brake->opline, - brake->type == PHPDBG_BREAK_METHOD_OPLINE?"method": - brake->type == PHPDBG_BREAK_FUNCTION_OPLINE?"function": - brake->type == PHPDBG_BREAK_FILE_OPLINE?"file": - "--- error ---", - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); - break; + type = "method"; + + print_opline: { + if (brake->type == PHPDBG_BREAK_METHOD_OPLINE) { + type = "method"; + } else if (brake->type == PHPDBG_BREAK_FUNCTION_OPLINE) { + type = "function"; + } else if (brake->type == PHPDBG_BREAK_FILE_OPLINE) { + type = "file"; + } + + phpdbg_writeln("opline", "id=\"%d\" num=\"%#lx\" type=\"%s\" disabled=\"%s\"", "#%d\t\t%#lx\t\t(%s breakpoint)%s", + brake->id, brake->opline, type, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); + } break; default: - phpdbg_writeln("#%d\t\t%#lx", brake->id, brake->opline); + phpdbg_writeln("opline", "id=\"%d\" num=\"%#lx\" disabled=\"%s\"", "#%d\t\t%#lx%s", + brake->id, brake->opline, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); break; } - } + } ZEND_HASH_FOREACH_END(); } break; case PHPDBG_BREAK_METHOD_OPLINE: if ((PHPDBG_G(flags) & PHPDBG_HAS_METHOD_OPLINE_BP)) { - HashPosition position[3]; HashTable *class_table, *method_table; - char *class_name = NULL, *method_name = NULL; - zend_uint class_len = 0, method_len = 0; - zend_ulong class_idx = 0L, method_idx = 0L; - - phpdbg_writeln(SEPARATE); - phpdbg_writeln("Method opline Breakpoints:"); - for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], &position[0]); - zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], (void**) &class_table, &position[0]) == SUCCESS; - zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], &position[0])) { - - if (zend_hash_get_current_key_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], - &class_name, &class_len, &class_idx, 0, &position[0]) == HASH_KEY_IS_STRING) { - - for (zend_hash_internal_pointer_reset_ex(class_table, &position[1]); - zend_hash_get_current_data_ex(class_table, (void**) &method_table, &position[1]) == SUCCESS; - zend_hash_move_forward_ex(class_table, &position[1])) { - - if (zend_hash_get_current_key_ex(class_table, - &method_name, &method_len, &method_idx, 0, &position[0]) == HASH_KEY_IS_STRING) { - - phpdbg_breakopline_t *brake; - - for (zend_hash_internal_pointer_reset_ex(method_table, &position[2]); - zend_hash_get_current_data_ex(method_table, (void**)&brake, &position[2]) == SUCCESS; - zend_hash_move_forward_ex(method_table, &position[2])) { - phpdbg_writeln("#%d\t\t%s::%s opline %ld%s", - brake->id, brake->class_name, brake->func_name, brake->opline_num, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); - } - } - } - } - } + phpdbg_out(SEPARATE "\n"); + phpdbg_out("Method opline Breakpoints:\n"); + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], class_table) { + ZEND_HASH_FOREACH_PTR(class_table, method_table) { + phpdbg_breakopline_t *brake; + + ZEND_HASH_FOREACH_PTR(method_table, brake) { + phpdbg_writeln("methodopline", "id=\"%d\" name=\"%s::%s\" num=\"%ld\" disabled=\"%s\"", "#%d\t\t%s::%s opline %ld%s", + brake->id, brake->class_name, brake->func_name, brake->opline_num, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); } break; case PHPDBG_BREAK_FUNCTION_OPLINE: if ((PHPDBG_G(flags) & PHPDBG_HAS_FUNCTION_OPLINE_BP)) { - HashPosition position[2]; HashTable *function_table; - char *function_name = NULL; - zend_uint function_len = 0; - zend_ulong function_idx = 0L; - - phpdbg_writeln(SEPARATE); - phpdbg_writeln("Function opline Breakpoints:"); - for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], &position[0]); - zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], (void**) &function_table, &position[0]) == SUCCESS; - zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], &position[0])) { - - if (zend_hash_get_current_key_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], - &function_name, &function_len, &function_idx, 0, &position[0]) == HASH_KEY_IS_STRING) { - phpdbg_breakopline_t *brake; - - for (zend_hash_internal_pointer_reset_ex(function_table, &position[1]); - zend_hash_get_current_data_ex(function_table, (void**)&brake, &position[1]) == SUCCESS; - zend_hash_move_forward_ex(function_table, &position[1])) { - phpdbg_writeln("#%d\t\t%s opline %ld%s", - brake->id, brake->func_name, brake->opline_num, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); - } - } - - } + phpdbg_out(SEPARATE "\n"); + phpdbg_out("Function opline Breakpoints:\n"); + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], function_table) { + phpdbg_breakopline_t *brake; + + ZEND_HASH_FOREACH_PTR(function_table, brake) { + phpdbg_writeln("functionopline", "id=\"%d\" name=\"%s\" num=\"%ld\" disabled=\"%s\"", "#%d\t\t%s opline %ld%s", + brake->id, brake->func_name, brake->opline_num, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); } break; case PHPDBG_BREAK_FILE_OPLINE: if ((PHPDBG_G(flags) & PHPDBG_HAS_FILE_OPLINE_BP)) { - HashPosition position[2]; HashTable *file_table; - char *file_name = NULL; - zend_uint file_len = 0; - zend_ulong file_idx = 0L; - phpdbg_writeln(SEPARATE); - phpdbg_writeln("File opline Breakpoints:"); - for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], &position[0]); - zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], (void**) &file_table, &position[0]) == SUCCESS; - zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], &position[0])) { - - if (zend_hash_get_current_key_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], - &file_name, &file_len, &file_idx, 0, &position[0]) == HASH_KEY_IS_STRING) { - - phpdbg_breakopline_t *brake; - - for (zend_hash_internal_pointer_reset_ex(file_table, &position[1]); - zend_hash_get_current_data_ex(file_table, (void**)&brake, &position[1]) == SUCCESS; - zend_hash_move_forward_ex(file_table, &position[1])) { - phpdbg_writeln("#%d\t\t%s opline %ld%s", - brake->id, brake->class_name, brake->opline_num, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); - } - } - } + phpdbg_out(SEPARATE "\n"); + phpdbg_out("File opline Breakpoints:\n"); + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], file_table) { + phpdbg_breakopline_t *brake; + + ZEND_HASH_FOREACH_PTR(file_table, brake) { + phpdbg_writeln("fileopline", "id=\"%d\" name=\"%s\" num=\"%ld\" disabled=\"%s\"", "#%d\t\t%s opline %ld%s", + brake->id, brake->class_name, brake->opline_num, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); + } ZEND_HASH_FOREACH_END(); + } ZEND_HASH_FOREACH_END(); } break; case PHPDBG_BREAK_COND: if ((PHPDBG_G(flags) & PHPDBG_HAS_COND_BP)) { - HashPosition position; phpdbg_breakcond_t *brake; - phpdbg_writeln(SEPARATE); - phpdbg_writeln("Conditional Breakpoints:"); - for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], &position); - zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], (void**) &brake, &position) == SUCCESS; - zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], &position)) { + phpdbg_out(SEPARATE "\n"); + phpdbg_out("Conditional Breakpoints:\n"); + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], brake) { if (brake->paramed) { switch (brake->param.type) { case STR_PARAM: - phpdbg_writeln("#%d\t\tat %s if %s%s", - brake->id, - brake->param.str, - brake->code, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); + phpdbg_writeln("evalfunction", "id=\"%d\" name=\"%s\" eval=\"%s\" disabled=\"%s\"", "#%d\t\tat %s if %s%s", + brake->id, brake->param.str, brake->code, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); break; case NUMERIC_FUNCTION_PARAM: - phpdbg_writeln("#%d\t\tat %s#%ld if %s%s", - brake->id, - brake->param.str, - brake->param.num, - brake->code, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); + phpdbg_writeln("evalfunctionopline", "id=\"%d\" name=\"%s\" num=\"%ld\" eval=\"%s\" disabled=\"%s\"", "#%d\t\tat %s#%ld if %s%s", + brake->id, brake->param.str, brake->param.num, brake->code, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); break; case METHOD_PARAM: - phpdbg_writeln("#%d\t\tat %s::%s if %s%s", - brake->id, - brake->param.method.class, - brake->param.method.name, - brake->code, + phpdbg_writeln("evalmethod", "id=\"%d\" name=\"%s::%s\" eval=\"%s\" disabled=\"%s\"", "#%d\t\tat %s::%s if %s%s", + brake->id, brake->param.method.class, brake->param.method.name, brake->code, ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); break; case NUMERIC_METHOD_PARAM: - phpdbg_writeln("#%d\t\tat %s::%s#%ld if %s%s", - brake->id, - brake->param.method.class, - brake->param.method.name, - brake->param.num, - brake->code, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); + phpdbg_writeln("evalmethodopline", "id=\"%d\" name=\"%s::%s\" num=\"%d\" eval=\"%s\" disabled=\"%s\"", "#%d\t\tat %s::%s#%ld if %s%s", + brake->id, brake->param.method.class, brake->param.method.name, brake->param.num, brake->code, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); break; case FILE_PARAM: - phpdbg_writeln("#%d\t\tat %s:%lu if %s%s", - brake->id, - brake->param.file.name, - brake->param.file.line, - brake->code, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); + phpdbg_writeln("evalfile", "id=\"%d\" name=\"%s\" line=\"%d\" eval=\"%s\" disabled=\"%s\"", "#%d\t\tat %s:%lu if %s%s", + brake->id, brake->param.file.name, brake->param.file.line, brake->code, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); break; case ADDR_PARAM: - phpdbg_writeln("#%d\t\tat #%lx if %s%s", - brake->id, - brake->param.addr, - brake->code, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); + phpdbg_writeln("evalopline", "id=\"%d\" opline=\"%#lx\" eval=\"%s\" disabled=\"%s\"", "#%d\t\tat #%lx if %s%s", + brake->id, brake->param.addr, brake->code, + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); break; default: - phpdbg_error("Invalid parameter type for conditional breakpoint"); + phpdbg_error("eval", "type=\"invalidparameter\"", "Invalid parameter type for conditional breakpoint"); return; } } else { - phpdbg_writeln("#%d\t\tif %s%s", + phpdbg_writeln("eval", "id=\"%d\" eval=\"%s\" disabled=\"%s\"", "#%d\t\tif %s%s", brake->id, brake->code, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); } - } + } ZEND_HASH_FOREACH_END(); } break; case PHPDBG_BREAK_OPCODE: if (PHPDBG_G(flags) & PHPDBG_HAS_OPCODE_BP) { - HashPosition position; phpdbg_breakop_t *brake; - phpdbg_writeln(SEPARATE); - phpdbg_writeln("Opcode Breakpoints:"); - for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], &position); - zend_hash_get_current_data_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], (void**) &brake, &position) == SUCCESS; - zend_hash_move_forward_ex(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], &position)) { - phpdbg_writeln("#%d\t\t%s%s", + phpdbg_out(SEPARATE "\n"); + phpdbg_out("Opcode Breakpoints:\n"); + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], brake) { + phpdbg_writeln("opcode", "id=\"%d\" name=\"%s\" disabled=\"%s\"", "#%d\t\t%s%s", brake->id, brake->name, - ((phpdbg_breakbase_t*)brake)->disabled ? " [disabled]" : ""); - } + ((phpdbg_breakbase_t *) brake)->disabled ? " [disabled]" : ""); + } ZEND_HASH_FOREACH_END(); } break; } + + phpdbg_xml("</breakpoints>"); } /* }}} */ diff --git a/sapi/phpdbg/phpdbg_bp.h b/sapi/phpdbg/phpdbg_bp.h index bbd108398f..abbcc4d5df 100644 --- a/sapi/phpdbg/phpdbg_bp.h +++ b/sapi/phpdbg/phpdbg_bp.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -21,6 +21,20 @@ #ifndef PHPDBG_BP_H #define PHPDBG_BP_H +/* {{{ defines */ +#define PHPDBG_BREAK_FILE 0 +#define PHPDBG_BREAK_FILE_PENDING 1 +#define PHPDBG_BREAK_SYM 2 +#define PHPDBG_BREAK_OPLINE 3 +#define PHPDBG_BREAK_METHOD 4 +#define PHPDBG_BREAK_COND 5 +#define PHPDBG_BREAK_OPCODE 6 +#define PHPDBG_BREAK_FUNCTION_OPLINE 7 +#define PHPDBG_BREAK_METHOD_OPLINE 8 +#define PHPDBG_BREAK_FILE_OPLINE 9 +#define PHPDBG_BREAK_MAP 10 +#define PHPDBG_BREAK_TABLES 11 /* }}} */ + /* {{{ */ typedef struct _zend_op *phpdbg_opline_ptr_t; /* }}} */ @@ -103,44 +117,47 @@ typedef struct _phpdbg_breakcond_t { zend_op_array *ops; } phpdbg_breakcond_t; -/* {{{ Opline breaks API */ -PHPDBG_API void phpdbg_resolve_op_array_breaks(zend_op_array *op_array TSRMLS_DC); -PHPDBG_API int phpdbg_resolve_op_array_break(phpdbg_breakopline_t *brake, zend_op_array *op_array TSRMLS_DC); -PHPDBG_API int phpdbg_resolve_opline_break(phpdbg_breakopline_t *new_break TSRMLS_DC); /* }}} */ +/* {{{ Resolving breaks API */ +PHPDBG_API void phpdbg_resolve_op_array_breaks(zend_op_array *op_array); +PHPDBG_API int phpdbg_resolve_op_array_break(phpdbg_breakopline_t *brake, zend_op_array *op_array); +PHPDBG_API int phpdbg_resolve_opline_break(phpdbg_breakopline_t *new_break); +PHPDBG_API HashTable *phpdbg_resolve_pending_file_break_ex(const char *file, uint filelen, zend_string *cur, HashTable *fileht); +PHPDBG_API void phpdbg_resolve_pending_file_break(const char *file); /* }}} */ /* {{{ Breakpoint Creation API */ -PHPDBG_API void phpdbg_set_breakpoint_file(const char* filename, long lineno TSRMLS_DC); -PHPDBG_API void phpdbg_set_breakpoint_symbol(const char* func_name, size_t func_name_len TSRMLS_DC); -PHPDBG_API void phpdbg_set_breakpoint_method(const char* class_name, const char* func_name TSRMLS_DC); -PHPDBG_API void phpdbg_set_breakpoint_opcode(const char* opname, size_t opname_len TSRMLS_DC); -PHPDBG_API void phpdbg_set_breakpoint_opline(zend_ulong opline TSRMLS_DC); -PHPDBG_API void phpdbg_set_breakpoint_opline_ex(phpdbg_opline_ptr_t opline TSRMLS_DC); -PHPDBG_API void phpdbg_set_breakpoint_method_opline(const char *class, const char *method, zend_ulong opline TSRMLS_DC); -PHPDBG_API void phpdbg_set_breakpoint_function_opline(const char *function, zend_ulong opline TSRMLS_DC); -PHPDBG_API void phpdbg_set_breakpoint_file_opline(const char *file, zend_ulong opline TSRMLS_DC); -PHPDBG_API void phpdbg_set_breakpoint_expression(const char* expression, size_t expression_len TSRMLS_DC); -PHPDBG_API void phpdbg_set_breakpoint_at(const phpdbg_param_t *param TSRMLS_DC); /* }}} */ +PHPDBG_API void phpdbg_set_breakpoint_file(const char* filename, long lineno); +PHPDBG_API void phpdbg_set_breakpoint_symbol(const char* func_name, size_t func_name_len); +PHPDBG_API void phpdbg_set_breakpoint_method(const char* class_name, const char* func_name); +PHPDBG_API void phpdbg_set_breakpoint_opcode(const char* opname, size_t opname_len); +PHPDBG_API void phpdbg_set_breakpoint_opline(zend_ulong opline); +PHPDBG_API void phpdbg_set_breakpoint_opline_ex(phpdbg_opline_ptr_t opline); +PHPDBG_API void phpdbg_set_breakpoint_method_opline(const char *class, const char *method, zend_ulong opline); +PHPDBG_API void phpdbg_set_breakpoint_function_opline(const char *function, zend_ulong opline); +PHPDBG_API void phpdbg_set_breakpoint_file_opline(const char *file, zend_ulong opline); +PHPDBG_API void phpdbg_set_breakpoint_expression(const char* expression, size_t expression_len); +PHPDBG_API void phpdbg_set_breakpoint_at(const phpdbg_param_t *param); /* }}} */ /* {{{ Breakpoint Detection API */ -PHPDBG_API phpdbg_breakbase_t* phpdbg_find_breakpoint(zend_execute_data* TSRMLS_DC); /* }}} */ +PHPDBG_API phpdbg_breakbase_t* phpdbg_find_breakpoint(zend_execute_data*); /* }}} */ /* {{{ Misc Breakpoint API */ -PHPDBG_API void phpdbg_hit_breakpoint(phpdbg_breakbase_t* brake, zend_bool output TSRMLS_DC); -PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type TSRMLS_DC); -PHPDBG_API void phpdbg_print_breakpoint(phpdbg_breakbase_t* brake TSRMLS_DC); -PHPDBG_API void phpdbg_reset_breakpoints(TSRMLS_D); -PHPDBG_API void phpdbg_clear_breakpoints(TSRMLS_D); -PHPDBG_API void phpdbg_delete_breakpoint(zend_ulong num TSRMLS_DC); -PHPDBG_API void phpdbg_enable_breakpoints(TSRMLS_D); -PHPDBG_API void phpdbg_enable_breakpoint(zend_ulong id TSRMLS_DC); -PHPDBG_API void phpdbg_disable_breakpoint(zend_ulong id TSRMLS_DC); -PHPDBG_API void phpdbg_disable_breakpoints(TSRMLS_D); /* }}} */ +PHPDBG_API void phpdbg_hit_breakpoint(phpdbg_breakbase_t* brake, zend_bool output); +PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type); +PHPDBG_API void phpdbg_print_breakpoint(phpdbg_breakbase_t* brake); +PHPDBG_API void phpdbg_reset_breakpoints(void); +PHPDBG_API void phpdbg_clear_breakpoints(void); +PHPDBG_API void phpdbg_delete_breakpoint(zend_ulong num); +PHPDBG_API void phpdbg_enable_breakpoints(void); +PHPDBG_API void phpdbg_enable_breakpoint(zend_ulong id); +PHPDBG_API void phpdbg_disable_breakpoint(zend_ulong id); +PHPDBG_API void phpdbg_disable_breakpoints(void); /* }}} */ /* {{{ Breakbase API */ -PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakbase(zend_ulong id TSRMLS_DC); -PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakbase_ex(zend_ulong id, HashTable ***table, HashPosition *position TSRMLS_DC); /* }}} */ +PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakbase(zend_ulong id); +PHPDBG_API phpdbg_breakbase_t *phpdbg_find_breakbase_ex(zend_ulong id, HashTable **table, zend_ulong *numkey, zend_string **strkey); /* }}} */ /* {{{ Breakpoint Exportation API */ -PHPDBG_API void phpdbg_export_breakpoints(FILE *handle TSRMLS_DC); /* }}} */ +PHPDBG_API void phpdbg_export_breakpoints(FILE *handle); +PHPDBG_API void phpdbg_export_breakpoints_to_string(char **str); /* }}} */ #endif /* PHPDBG_BP_H */ diff --git a/sapi/phpdbg/phpdbg_break.c b/sapi/phpdbg/phpdbg_break.c index eb79ab0f3d..0640d96fd8 100644 --- a/sapi/phpdbg/phpdbg_break.c +++ b/sapi/phpdbg/phpdbg_break.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -26,30 +26,30 @@ #include "phpdbg_bp.h" #include "phpdbg_prompt.h" -ZEND_EXTERN_MODULE_GLOBALS(phpdbg); +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) -#define PHPDBG_BREAK_COMMAND_D(f, h, a, m, l, s) \ - PHPDBG_COMMAND_D_EXP(f, h, a, m, l, s, &phpdbg_prompt_commands[10]) +#define PHPDBG_BREAK_COMMAND_D(f, h, a, m, l, s, flags) \ + PHPDBG_COMMAND_D_EXP(f, h, a, m, l, s, &phpdbg_prompt_commands[9], flags) /** * Commands */ const phpdbg_command_t phpdbg_break_commands[] = { - PHPDBG_BREAK_COMMAND_D(at, "specify breakpoint by location and condition", '@', break_at, NULL, "*c"), - PHPDBG_BREAK_COMMAND_D(del, "delete breakpoint by identifier number", '~', break_del, NULL, "n"), + PHPDBG_BREAK_COMMAND_D(at, "specify breakpoint by location and condition", '@', break_at, NULL, "*c", 0), + PHPDBG_BREAK_COMMAND_D(del, "delete breakpoint by identifier number", '~', break_del, NULL, "n", 0), PHPDBG_END_COMMAND }; PHPDBG_BREAK(at) /* {{{ */ { - phpdbg_set_breakpoint_at(param TSRMLS_CC); + phpdbg_set_breakpoint_at(param); return SUCCESS; } /* }}} */ PHPDBG_BREAK(del) /* {{{ */ { - phpdbg_delete_breakpoint(param->num TSRMLS_CC); + phpdbg_delete_breakpoint(param->num); return SUCCESS; } /* }}} */ diff --git a/sapi/phpdbg/phpdbg_break.h b/sapi/phpdbg/phpdbg_break.h index bcb3da0677..4a74028c0e 100644 --- a/sapi/phpdbg/phpdbg_break.h +++ b/sapi/phpdbg/phpdbg_break.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ diff --git a/sapi/phpdbg/phpdbg_btree.c b/sapi/phpdbg/phpdbg_btree.c index 2c56ab2417..9e7dc86e8e 100644 --- a/sapi/phpdbg/phpdbg_btree.c +++ b/sapi/phpdbg/phpdbg_btree.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -66,7 +66,6 @@ phpdbg_btree_result *phpdbg_btree_find(phpdbg_btree *tree, zend_ulong idx) { phpdbg_btree_result *phpdbg_btree_find_closest(phpdbg_btree *tree, zend_ulong idx) { phpdbg_btree_branch *branch = tree->branch; int i = tree->depth - 1, last_superior_i = -1; - zend_bool had_alternative_branch = 0; if (branch == NULL) { return NULL; @@ -74,30 +73,33 @@ phpdbg_btree_result *phpdbg_btree_find_closest(phpdbg_btree *tree, zend_ulong id /* find nearest watchpoint */ do { - /* an impossible branch was found if: */ - if (!had_alternative_branch && (idx >> i) % 2 == 0 && !branch->branches[0]) { - /* there's no lower branch than idx */ - if (last_superior_i == -1) { - /* failure */ - return NULL; - } - /* reset state */ - branch = tree->branch; - i = tree->depth - 1; - /* follow branch according to bits in idx until the last lower branch before the impossible branch */ - do { - CHOOSE_BRANCH((idx >> i) % 2 == 1 && branch->branches[1]); - } while (--i > last_superior_i); - /* use now the lower branch of which we can be sure that it contains only branches lower than idx */ - CHOOSE_BRANCH(0); - /* and choose the highest possible branch in the branch containing only branches lower than idx */ - while (i--) { - CHOOSE_BRANCH(branch->branches[1]); + if ((idx >> i) % 2 == 0) { + if (branch->branches[0]) { + CHOOSE_BRANCH(0); + /* an impossible branch was found if: */ + } else { + /* there's no lower branch than idx */ + if (last_superior_i == -1) { + /* failure */ + return NULL; + } + /* reset state */ + branch = tree->branch; + i = tree->depth - 1; + /* follow branch according to bits in idx until the last lower branch before the impossible branch */ + do { + CHOOSE_BRANCH((idx >> i) % 2 == 1 && branch->branches[1]); + } while (--i > last_superior_i); + /* use now the lower branch of which we can be sure that it contains only branches lower than idx */ + CHOOSE_BRANCH(0); + /* and choose the highest possible branch in the branch containing only branches lower than idx */ + while (i--) { + CHOOSE_BRANCH(branch->branches[1]); + } + break; } - break; - } /* follow branch according to bits in idx until having found an impossible branch */ - if (had_alternative_branch || (idx >> i) % 2 == 1) { + } else { if (branch->branches[1]) { if (branch->branches[0]) { last_superior_i = i; @@ -105,10 +107,11 @@ phpdbg_btree_result *phpdbg_btree_find_closest(phpdbg_btree *tree, zend_ulong id CHOOSE_BRANCH(1); } else { CHOOSE_BRANCH(0); - had_alternative_branch = 1; + while (i--) { + CHOOSE_BRANCH(branch->branches[1]); + } + break; } - } else { - CHOOSE_BRANCH(0); } } while (i--); @@ -219,3 +222,18 @@ check_branch_existence: return SUCCESS; } + +void phpdbg_btree_branch_dump(phpdbg_btree_branch *branch, zend_ulong depth) { + if (branch) { + if (depth--) { + phpdbg_btree_branch_dump(branch->branches[0], depth); + phpdbg_btree_branch_dump(branch->branches[1], depth); + } else { + fprintf(stderr, "%p: %p\n", (void *) branch->result.idx, branch->result.ptr); + } + } +} + +void phpdbg_btree_dump(phpdbg_btree *tree) { + phpdbg_btree_branch_dump(tree->branch, tree->depth); +} diff --git a/sapi/phpdbg/phpdbg_btree.h b/sapi/phpdbg/phpdbg_btree.h index b9e0d99d81..05fb6b833a 100644 --- a/sapi/phpdbg/phpdbg_btree.h +++ b/sapi/phpdbg/phpdbg_btree.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -62,4 +62,9 @@ int phpdbg_btree_insert_or_update(phpdbg_btree *tree, zend_ulong idx, void *ptr, #define phpdbg_btree_update(tree, idx, ptr) phpdbg_btree_insert_or_update(tree, idx, ptr, PHPDBG_BTREE_UPDATE) #define phpdbg_btree_overwrite(tree, idx, ptr) phpdbg_btree_insert_or_update(tree, idx, ptr, PHPDBG_BTREE_OWERWRITE) + +/* debugging functions */ +void phpdbg_btree_branch_dump(phpdbg_btree_branch *branch, zend_ulong depth); +void phpdbg_btree_dump(phpdbg_btree *tree); + #endif diff --git a/sapi/phpdbg/phpdbg_cmd.c b/sapi/phpdbg/phpdbg_cmd.c index 7af18309f9..f89e58a13c 100644 --- a/sapi/phpdbg/phpdbg_cmd.c +++ b/sapi/phpdbg/phpdbg_cmd.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -23,8 +23,9 @@ #include "phpdbg_utils.h" #include "phpdbg_set.h" #include "phpdbg_prompt.h" +#include "phpdbg_io.h" -ZEND_EXTERN_MODULE_GLOBALS(phpdbg); +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) static inline const char *phpdbg_command_name(const phpdbg_command_t *command, char *buffer) { size_t pos = 0; @@ -39,11 +40,11 @@ static inline const char *phpdbg_command_name(const phpdbg_command_t *command, c memcpy(&buffer[pos], command->name, command->name_len); pos += command->name_len; buffer[pos] = 0; - + return buffer; } -PHPDBG_API const char *phpdbg_get_param_type(const phpdbg_param_t *param TSRMLS_DC) /* {{{ */ +PHPDBG_API const char *phpdbg_get_param_type(const phpdbg_param_t *param) /* {{{ */ { switch (param->type) { case STACK_PARAM: @@ -69,7 +70,7 @@ PHPDBG_API const char *phpdbg_get_param_type(const phpdbg_param_t *param TSRMLS_ } } -PHPDBG_API void phpdbg_clear_param(phpdbg_param_t *param TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_clear_param(phpdbg_param_t *param) /* {{{ */ { if (param) { switch (param->type) { @@ -90,80 +91,60 @@ PHPDBG_API void phpdbg_clear_param(phpdbg_param_t *param TSRMLS_DC) /* {{{ */ } /* }}} */ -PHPDBG_API char* phpdbg_param_tostring(const phpdbg_param_t *param, char **pointer TSRMLS_DC) /* {{{ */ +PHPDBG_API char* phpdbg_param_tostring(const phpdbg_param_t *param, char **pointer) /* {{{ */ { switch (param->type) { case STR_PARAM: - asprintf(pointer, - "%s", param->str); + ZEND_IGNORE_VALUE(asprintf(pointer, "%s", param->str)); break; case ADDR_PARAM: - asprintf(pointer, - "%#lx", param->addr); + ZEND_IGNORE_VALUE(asprintf(pointer, ZEND_ULONG_FMT, param->addr)); break; case NUMERIC_PARAM: - asprintf(pointer, - "%li", - param->num); + ZEND_IGNORE_VALUE(asprintf(pointer, "%li", param->num)); break; case METHOD_PARAM: - asprintf(pointer, - "%s::%s", - param->method.class, - param->method.name); + ZEND_IGNORE_VALUE(asprintf(pointer, "%s::%s", param->method.class, param->method.name)); break; case FILE_PARAM: if (param->num) { - asprintf(pointer, - "%s:%lu#%lu", - param->file.name, - param->file.line, - param->num); + ZEND_IGNORE_VALUE(asprintf(pointer, "%s:%lu#%lu", param->file.name, param->file.line, param->num)); } else { - asprintf(pointer, - "%s:%lu", - param->file.name, - param->file.line); + ZEND_IGNORE_VALUE(asprintf(pointer, "%s:%lu", param->file.name, param->file.line)); } break; case NUMERIC_FUNCTION_PARAM: - asprintf(pointer, - "%s#%lu", param->str, param->num); + ZEND_IGNORE_VALUE(asprintf(pointer, "%s#%lu", param->str, param->num)); break; case NUMERIC_METHOD_PARAM: - asprintf(pointer, - "%s::%s#%lu", - param->method.class, - param->method.name, - param->num); + ZEND_IGNORE_VALUE(asprintf(pointer, "%s::%s#%lu", param->method.class, param->method.name, param->num)); break; default: - asprintf(pointer, - "%s", "unknown"); + *pointer = strdup("unknown"); } return *pointer; } /* }}} */ -PHPDBG_API void phpdbg_copy_param(const phpdbg_param_t* src, phpdbg_param_t* dest TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_copy_param(const phpdbg_param_t* src, phpdbg_param_t* dest) /* {{{ */ { switch ((dest->type = src->type)) { case STACK_PARAM: /* nope */ break; - + case STR_PARAM: dest->str = estrndup(src->str, src->len); dest->len = src->len; break; - + case OP_PARAM: dest->str = estrndup(src->str, src->len); dest->len = src->len; @@ -203,14 +184,14 @@ PHPDBG_API void phpdbg_copy_param(const phpdbg_param_t* src, phpdbg_param_t* des break; case EMPTY_PARAM: { /* do nothing */ } break; - + default: { /* not yet */ } } } /* }}} */ -PHPDBG_API zend_ulong phpdbg_hash_param(const phpdbg_param_t *param TSRMLS_DC) /* {{{ */ +PHPDBG_API zend_ulong phpdbg_hash_param(const phpdbg_param_t *param) /* {{{ */ { zend_ulong hash = param->type; @@ -218,7 +199,7 @@ PHPDBG_API zend_ulong phpdbg_hash_param(const phpdbg_param_t *param TSRMLS_DC) / case STACK_PARAM: /* nope */ break; - + case STR_PARAM: hash += zend_inline_hash_func(param->str, param->len); break; @@ -256,7 +237,7 @@ PHPDBG_API zend_ulong phpdbg_hash_param(const phpdbg_param_t *param TSRMLS_DC) / break; case EMPTY_PARAM: { /* do nothing */ } break; - + default: { /* not yet */ } @@ -265,7 +246,7 @@ PHPDBG_API zend_ulong phpdbg_hash_param(const phpdbg_param_t *param TSRMLS_DC) / return hash; } /* }}} */ -PHPDBG_API zend_bool phpdbg_match_param(const phpdbg_param_t *l, const phpdbg_param_t *r TSRMLS_DC) /* {{{ */ +PHPDBG_API zend_bool phpdbg_match_param(const phpdbg_param_t *l, const phpdbg_param_t *r) /* {{{ */ { if (l && r) { if (l->type == r->type) { @@ -274,7 +255,7 @@ PHPDBG_API zend_bool phpdbg_match_param(const phpdbg_param_t *l, const phpdbg_pa /* nope, or yep */ return 1; break; - + case NUMERIC_FUNCTION_PARAM: if (l->num != r->num) { break; @@ -329,7 +310,7 @@ PHPDBG_API zend_bool phpdbg_match_param(const phpdbg_param_t *l, const phpdbg_pa case EMPTY_PARAM: return 1; - + default: { /* not yet */ } @@ -344,45 +325,45 @@ PHPDBG_API void phpdbg_param_debug(const phpdbg_param_t *param, const char *msg) if (param && param->type) { switch (param->type) { case STR_PARAM: - fprintf(stderr, "%s STR_PARAM(%s=%lu)\n", msg, param->str, param->len); + fprintf(stderr, "%s STR_PARAM(%s=%zu)\n", msg, param->str, param->len); break; - + case ADDR_PARAM: - fprintf(stderr, "%s ADDR_PARAM(%lu)\n", msg, param->addr); + fprintf(stderr, "%s ADDR_PARAM(" ZEND_ULONG_FMT ")\n", msg, param->addr); break; - + case NUMERIC_FILE_PARAM: fprintf(stderr, "%s NUMERIC_FILE_PARAM(%s:#%lu)\n", msg, param->file.name, param->file.line); break; - + case FILE_PARAM: fprintf(stderr, "%s FILE_PARAM(%s:%lu)\n", msg, param->file.name, param->file.line); break; - + case METHOD_PARAM: fprintf(stderr, "%s METHOD_PARAM(%s::%s)\n", msg, param->method.class, param->method.name); break; - + case NUMERIC_METHOD_PARAM: fprintf(stderr, "%s NUMERIC_METHOD_PARAM(%s::%s)\n", msg, param->method.class, param->method.name); break; - + case NUMERIC_FUNCTION_PARAM: fprintf(stderr, "%s NUMERIC_FUNCTION_PARAM(%s::%ld)\n", msg, param->str, param->num); break; - + case NUMERIC_PARAM: fprintf(stderr, "%s NUMERIC_PARAM(%ld)\n", msg, param->num); break; - + case COND_PARAM: - fprintf(stderr, "%s COND_PARAM(%s=%lu)\n", msg, param->str, param->len); + fprintf(stderr, "%s COND_PARAM(%s=%zu)\n", msg, param->str, param->len); break; - + case OP_PARAM: - fprintf(stderr, "%s OP_PARAM(%s=%lu)\n", msg, param->str, param->len); + fprintf(stderr, "%s OP_PARAM(%s=%zu)\n", msg, param->str, param->len); break; - + default: { /* not yet */ } @@ -394,49 +375,58 @@ PHPDBG_API void phpdbg_param_debug(const phpdbg_param_t *param, const char *msg) PHPDBG_API void phpdbg_stack_free(phpdbg_param_t *stack) { if (stack && stack->next) { phpdbg_param_t *remove = stack->next; - + while (remove) { phpdbg_param_t *next = NULL; - + if (remove->next) next = remove->next; - + switch (remove->type) { case NUMERIC_METHOD_PARAM: case METHOD_PARAM: - if (remove->method.class) - free(remove->method.class); - if (remove->method.name) - free(remove->method.name); + if (remove->method.class) { + efree(remove->method.class); + } + if (remove->method.name) { + efree(remove->method.name); + } break; case NUMERIC_FUNCTION_PARAM: case STR_PARAM: case OP_PARAM: - if (remove->str) - free(remove->str); + case EVAL_PARAM: + case SHELL_PARAM: + case COND_PARAM: + case RUN_PARAM: + if (remove->str) { + efree(remove->str); + } break; - + case NUMERIC_FILE_PARAM: case FILE_PARAM: - if (remove->file.name) - free(remove->file.name); + if (remove->file.name) { + efree(remove->file.name); + } break; - + default: { /* nothing */ } } - + free(remove); remove = NULL; - + if (next) - remove = next; + remove = next; else break; } } - + + stack->next = NULL; } /* }}} */ @@ -444,8 +434,9 @@ PHPDBG_API void phpdbg_stack_free(phpdbg_param_t *stack) { PHPDBG_API void phpdbg_stack_push(phpdbg_param_t *stack, phpdbg_param_t *param) { phpdbg_param_t *next = calloc(1, sizeof(phpdbg_param_t)); - if (!next) + if (!next) { return; + } *(next) = *(param); @@ -464,30 +455,39 @@ PHPDBG_API void phpdbg_stack_push(phpdbg_param_t *stack, phpdbg_param_t *param) stack->len++; } /* }}} */ -PHPDBG_API int phpdbg_stack_verify(const phpdbg_command_t *command, phpdbg_param_t **stack, char **why TSRMLS_DC) { +/* {{{ */ +PHPDBG_API void phpdbg_stack_separate(phpdbg_param_t *param) { + phpdbg_param_t *stack = calloc(1, sizeof(phpdbg_param_t)); + + stack->type = STACK_PARAM; + stack->next = param->next; + param->next = stack; + stack->top = param->top; +} /* }}} */ + +PHPDBG_API int phpdbg_stack_verify(const phpdbg_command_t *command, phpdbg_param_t **stack) { if (command) { char buffer[128] = {0,}; const phpdbg_param_t *top = (stack != NULL) ? *stack : NULL; const char *arg = command->args; size_t least = 0L, - received = 0L, - current = 0L; + received = 0L, + current = 0L; zend_bool optional = 0; - + /* check for arg spec */ if (!(arg) || !(*arg)) { - if (!top) { + if (!top || top->type == STACK_PARAM) { return SUCCESS; } - - asprintf(why, - "The command \"%s\" expected no arguments", + + phpdbg_error("command", "type=\"toomanyargs\" command=\"%s\" expected=\"0\"", "The command \"%s\" expected no arguments", phpdbg_command_name(command, buffer)); return FAILURE; } - + least = 0L; - + /* count least amount of arguments */ while (arg && *arg) { if (arg[0] == '|') { @@ -496,38 +496,40 @@ PHPDBG_API int phpdbg_stack_verify(const phpdbg_command_t *command, phpdbg_param least++; arg++; } - + arg = command->args; #define verify_arg(e, a, t) if (!(a)) { \ if (!optional) { \ - asprintf(why, \ - "The command \"%s\" expected %s and got nothing at parameter %lu", \ + phpdbg_error("command", "type=\"noarg\" command=\"%s\" expected=\"%s\" num=\"%lu\"", "The command \"%s\" expected %s and got nothing at parameter %lu", \ phpdbg_command_name(command, buffer), \ (e), \ current); \ return FAILURE;\ } \ } else if ((a)->type != (t)) { \ - asprintf(why, \ - "The command \"%s\" expected %s and got %s at parameter %lu", \ + phpdbg_error("command", "type=\"wrongarg\" command=\"%s\" expected=\"%s\" got=\"%s\" num=\"%lu\"", "The command \"%s\" expected %s and got %s at parameter %lu", \ phpdbg_command_name(command, buffer), \ (e),\ - phpdbg_get_param_type((a) TSRMLS_CC), \ + phpdbg_get_param_type((a)), \ current); \ return FAILURE; \ } while (arg && *arg) { + if (top && top->type == STACK_PARAM) { + break; + } + current++; - + switch (*arg) { case '|': { current--; optional = 1; arg++; } continue; - + case 'i': verify_arg("raw input", top, STR_PARAM); break; case 's': verify_arg("string", top, STR_PARAM); break; case 'n': verify_arg("number", top, NUMERIC_PARAM); break; @@ -537,14 +539,16 @@ PHPDBG_API int phpdbg_stack_verify(const phpdbg_command_t *command, phpdbg_param case 'c': verify_arg("condition", top, COND_PARAM); break; case 'o': verify_arg("opcode", top, OP_PARAM); break; case 'b': verify_arg("boolean", top, NUMERIC_PARAM); break; - + case '*': { /* do nothing */ } break; } - - if (top ) { + + if (top) { top = top->next; - } else break; - + } else { + break; + } + received++; arg++; } @@ -552,28 +556,27 @@ PHPDBG_API int phpdbg_stack_verify(const phpdbg_command_t *command, phpdbg_param #undef verify_arg if ((received < least)) { - asprintf(why, - "The command \"%s\" expected at least %lu arguments (%s) and received %lu", + phpdbg_error("command", "type=\"toofewargs\" command=\"%s\" expected=\"%d\" argtypes=\"%s\" got=\"%d\"", "The command \"%s\" expected at least %lu arguments (%s) and received %lu", phpdbg_command_name(command, buffer), least, - command->args, + command->args, received); return FAILURE; } } - + return SUCCESS; } /* {{{ */ -PHPDBG_API const phpdbg_command_t* phpdbg_stack_resolve(const phpdbg_command_t *commands, const phpdbg_command_t *parent, phpdbg_param_t **top, char **why) { +PHPDBG_API const phpdbg_command_t *phpdbg_stack_resolve(const phpdbg_command_t *commands, const phpdbg_command_t *parent, phpdbg_param_t **top) { const phpdbg_command_t *command = commands; phpdbg_param_t *name = *top; const phpdbg_command_t *matched[3] = {NULL, NULL, NULL}; ulong matches = 0L; - + while (command && command->name && command->handler) { - if ((name->len == 1) || (command->name_len >= name->len)) { + if (name->len == 1 || command->name_len >= name->len) { /* match single letter alias */ if (command->alias && (name->len == 1)) { if (command->alias == (*name->str)) { @@ -581,85 +584,76 @@ PHPDBG_API const phpdbg_command_t* phpdbg_stack_resolve(const phpdbg_command_t * matches++; } } else { - /* match full, case insensitive, command name */ if (strncasecmp(command->name, name->str, name->len) == SUCCESS) { if (matches < 3) { - /* only allow abbreviating commands that can be aliased */ - if (((name->len != command->name_len) && command->alias) || - (name->len == command->name_len)) { + if ((name->len != command->name_len && command->alias) || name->len == command->name_len) { matched[matches] = command; matches++; } - - + /* exact match */ - if (name->len == command->name_len) + if (name->len == command->name_len) { break; - } else break; + } + } else { + break; + } } } } - + command++; } - + switch (matches) { - case 0: { + case 0: if (parent) { - asprintf( - why, - "The command \"%s %s\" could not be found", - parent->name, name->str); - } else asprintf( - why, - "The command \"%s\" could not be found", - name->str); - } return parent; - - case 1: { + phpdbg_error("command", "type=\"notfound\" command=\"%s\" subcommand=\"%s\"", "The command \"%s %s\" could not be found", parent->name, name->str); + } else { + phpdbg_error("command", "type=\"notfound\" command=\"%s\"", "The command \"%s\" could not be found", name->str); + } + return parent; + + case 1: (*top) = (*top)->next; command = matched[0]; - } break; - + break; + default: { char *list = NULL; - zend_uint it = 0; + uint32_t it = 0; size_t pos = 0; - + while (it < matches) { if (!list) { - list = malloc( - matched[it]->name_len + 1 + - ((it+1) < matches ? sizeof(", ")-1 : 0)); + list = emalloc(matched[it]->name_len + 1 + (it + 1 < matches ? sizeof(", ") - 1 : 0)); } else { - list = realloc(list, - (pos + matched[it]->name_len) + 1 + - ((it+1) < matches ? sizeof(", ")-1 : 0)); + list = erealloc(list, (pos + matched[it]->name_len) + 1 + (it + 1 < matches ? sizeof(", ") - 1 : 0)); } memcpy(&list[pos], matched[it]->name, matched[it]->name_len); pos += matched[it]->name_len; - if ((it+1) < matches) { - memcpy(&list[pos], ", ", sizeof(", ")-1); + if ((it + 1) < matches) { + memcpy(&list[pos], ", ", sizeof(", ") - 1); pos += (sizeof(", ") - 1); } - + list[pos] = 0; it++; } - - asprintf( - why, - "The command \"%s\" is ambigious, matching %lu commands (%s)", - name->str, matches, list); - free(list); - } return NULL; + + /* ", " separated matches */ + phpdbg_error("command", "type=\"ambiguous\" command=\"%s\" matches=\"%lu\" matched=\"%s\"", "The command \"%s\" is ambigious, matching %lu commands (%s)", name->str, matches, list); + efree(list); + + return NULL; + } } if (command->subs && (*top) && ((*top)->type == STR_PARAM)) { - return phpdbg_stack_resolve(command->subs, command, top, why); + return phpdbg_stack_resolve(command->subs, command, top); } else { return command; } @@ -667,119 +661,126 @@ PHPDBG_API const phpdbg_command_t* phpdbg_stack_resolve(const phpdbg_command_t * return NULL; } /* }}} */ -/* {{{ */ -PHPDBG_API int phpdbg_stack_execute(phpdbg_param_t *stack, char **why TSRMLS_DC) { - phpdbg_param_t *top = NULL; +static int phpdbg_internal_stack_execute(phpdbg_param_t *stack, zend_bool allow_async_unsafe) { const phpdbg_command_t *handler = NULL; - - if (stack->type != STACK_PARAM) { - asprintf( - why, "The passed argument was not a stack !!"); - return FAILURE; - } - - if (!stack->len) { - asprintf( - why, "The stack contains nothing !!"); - return FAILURE; - } - - top = (phpdbg_param_t*) stack->next; - + phpdbg_param_t *top = (phpdbg_param_t *) stack->next; + switch (top->type) { case EVAL_PARAM: - return PHPDBG_COMMAND_HANDLER(ev)(top TSRMLS_CC); + phpdbg_activate_err_buf(0); + phpdbg_free_err_buf(); + return PHPDBG_COMMAND_HANDLER(ev)(top); case RUN_PARAM: - return PHPDBG_COMMAND_HANDLER(run)(top TSRMLS_CC); - + if (!allow_async_unsafe) { + phpdbg_error("signalsegv", "command=\"run\"", "run command is disallowed during hard interrupt"); + } + phpdbg_activate_err_buf(0); + phpdbg_free_err_buf(); + return PHPDBG_COMMAND_HANDLER(run)(top); + case SHELL_PARAM: - return PHPDBG_COMMAND_HANDLER(sh)(top TSRMLS_CC); - + if (!allow_async_unsafe) { + phpdbg_error("signalsegv", "command=\"sh\"", "sh command is disallowed during hard interrupt"); + return FAILURE; + } + phpdbg_activate_err_buf(0); + phpdbg_free_err_buf(); + return PHPDBG_COMMAND_HANDLER(sh)(top); + case STR_PARAM: { - handler = phpdbg_stack_resolve( - phpdbg_prompt_commands, NULL, &top, why); - + handler = phpdbg_stack_resolve(phpdbg_prompt_commands, NULL, &top); + if (handler) { - if (phpdbg_stack_verify(handler, &top, why TSRMLS_CC) == SUCCESS) { - return handler->handler(top TSRMLS_CC); + if (!allow_async_unsafe && !(handler->flags & PHPDBG_ASYNC_SAFE)) { + phpdbg_error("signalsegv", "command=\"%s\"", "%s command is disallowed during hard interrupt", handler->name); + return FAILURE; + } + + if (phpdbg_stack_verify(handler, &top) == SUCCESS) { + phpdbg_activate_err_buf(0); + phpdbg_free_err_buf(); + return handler->handler(top); } } } return FAILURE; - + default: - asprintf( - why, "The first parameter makes no sense !!"); + phpdbg_error("command", "type=\"invalidcommand\"", "The first parameter makes no sense !"); return FAILURE; } - + + return SUCCESS; +} /* }}} */ + +/* {{{ */ +PHPDBG_API int phpdbg_stack_execute(phpdbg_param_t *stack, zend_bool allow_async_unsafe) { + phpdbg_param_t *top = stack; + + if (stack->type != STACK_PARAM) { + phpdbg_error("command", "type=\"nostack\"", "The passed argument was not a stack !"); + return FAILURE; + } + + if (!stack->len) { + phpdbg_error("command", "type=\"emptystack\"", "The stack contains nothing !"); + return FAILURE; + } + + do { + if (top->type == STACK_PARAM) { + int result; + if ((result = phpdbg_internal_stack_execute(top, allow_async_unsafe)) != SUCCESS) { + return result; + } + } + } while ((top = top->next)); + return SUCCESS; } /* }}} */ -PHPDBG_API char* phpdbg_read_input(char *buffered TSRMLS_DC) /* {{{ */ +PHPDBG_API char *phpdbg_read_input(char *buffered) /* {{{ */ { - char *cmd = NULL; -#if !defined(HAVE_LIBREADLINE) && !defined(HAVE_LIBEDIT) char buf[PHPDBG_MAX_CMD]; -#endif + char *cmd = NULL; char *buffer = NULL; - if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) { - if ((PHPDBG_G(flags) & PHPDBG_IS_REMOTE) && - (buffered == NULL)) { - fflush(PHPDBG_G(io)[PHPDBG_STDOUT]); + if ((PHPDBG_G(flags) & (PHPDBG_IS_STOPPING | PHPDBG_IS_RUNNING)) != PHPDBG_IS_STOPPING) { + if ((PHPDBG_G(flags) & PHPDBG_IS_REMOTE) && (buffered == NULL) && !phpdbg_active_sigsafe_mem()) { + fflush(PHPDBG_G(io)[PHPDBG_STDOUT].ptr); } if (buffered == NULL) { -disconnect: - if (0) { - PHPDBG_G(flags) |= (PHPDBG_IS_QUITTING|PHPDBG_IS_DISCONNECTED); - zend_bailout(); - return NULL; +#define USE_LIB_STAR (defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDIT)) + /* note: EOF makes readline write prompt again in local console mode - and ignored if compiled without readline */ +#if USE_LIB_STAR + if ((PHPDBG_G(flags) & PHPDBG_IS_REMOTE) || !isatty(PHPDBG_G(io)[PHPDBG_STDIN].fd)) +#endif + { + phpdbg_write("prompt", "", "%s", phpdbg_get_prompt()); + phpdbg_consume_stdin_line(cmd = buf); } - -#if !defined(HAVE_LIBREADLINE) && !defined(HAVE_LIBEDIT) - if (!(PHPDBG_G(flags) & PHPDBG_IS_REMOTE)) { - if (!phpdbg_write("%s", phpdbg_get_prompt(TSRMLS_C))) { - goto disconnect; +#if USE_LIB_STAR + else { + cmd = readline(phpdbg_get_prompt()); + PHPDBG_G(last_was_newline) = 1; + + if (!cmd) { + PHPDBG_G(flags) |= PHPDBG_IS_QUITTING | PHPDBG_IS_DISCONNECTED; + zend_bailout(); } - } - - /* note: EOF is ignored */ -readline: - if (!fgets(buf, PHPDBG_MAX_CMD, PHPDBG_G(io)[PHPDBG_STDIN])) { - /* the user has gone away */ - if ((PHPDBG_G(flags) & PHPDBG_IS_REMOTE)) { - goto disconnect; - } else goto readline; - } - - cmd = buf; -#else - /* note: EOF makes readline write prompt again in local console mode */ -readline: - if ((PHPDBG_G(flags) & PHPDBG_IS_REMOTE)) { - char buf[PHPDBG_MAX_CMD]; - if (fgets(buf, PHPDBG_MAX_CMD, PHPDBG_G(io)[PHPDBG_STDIN])) { - cmd = buf; - } else goto disconnect; - } else cmd = readline(phpdbg_get_prompt(TSRMLS_C)); - - if (!cmd) { - goto readline; - } - if (!(PHPDBG_G(flags) & PHPDBG_IS_REMOTE)) { add_history(cmd); } #endif - } else cmd = buffered; - + } else { + cmd = buffered; + } + buffer = estrdup(cmd); -#if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDIT) - if (!buffered && cmd && - !(PHPDBG_G(flags) & PHPDBG_IS_REMOTE)) { +#if USE_LIB_STAR + if (!buffered && cmd && !(PHPDBG_G(flags) & PHPDBG_IS_REMOTE) && isatty(PHPDBG_G(io)[PHPDBG_STDIN].fd)) { free(cmd); } #endif @@ -797,20 +798,41 @@ readline: if (buffer && strlen(buffer)) { if (PHPDBG_G(buffer)) { - efree(PHPDBG_G(buffer)); + free(PHPDBG_G(buffer)); } - PHPDBG_G(buffer) = estrdup(buffer); - } else { - if (PHPDBG_G(buffer)) { - buffer = estrdup(PHPDBG_G(buffer)); + PHPDBG_G(buffer) = strdup(buffer); + } else if (PHPDBG_G(buffer)) { + if (buffer) { + efree(buffer); } + buffer = estrdup(PHPDBG_G(buffer)); } - + return buffer; } /* }}} */ -PHPDBG_API void phpdbg_destroy_input(char **input TSRMLS_DC) /*{{{ */ +PHPDBG_API void phpdbg_destroy_input(char **input) /*{{{ */ { efree(*input); } /* }}} */ +PHPDBG_API int phpdbg_ask_user_permission(const char *question) { + if (!(PHPDBG_G(flags) & PHPDBG_WRITE_XML)) { + char buf[PHPDBG_MAX_CMD]; + phpdbg_out("%s", question); + phpdbg_out(" (type y or n): "); + + while (1) { + phpdbg_consume_stdin_line(buf); + if (buf[1] == '\n' && (buf[0] == 'y' || buf[0] == 'n')) { + if (buf[0] == 'y') { + return SUCCESS; + } + return FAILURE; + } + phpdbg_out("Please enter either y (yes) or n (no): "); + } + } + + return SUCCESS; +} diff --git a/sapi/phpdbg/phpdbg_cmd.h b/sapi/phpdbg/phpdbg_cmd.h index 063ff304a9..cbf2a8793d 100644 --- a/sapi/phpdbg/phpdbg_cmd.h +++ b/sapi/phpdbg/phpdbg_cmd.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -86,7 +86,9 @@ struct _phpdbg_param { #define YYSTYPE phpdbg_param_t #endif -typedef int (*phpdbg_command_handler_t)(const phpdbg_param_t* TSRMLS_DC); +#define PHPDBG_ASYNC_SAFE 1 + +typedef int (*phpdbg_command_handler_t)(const phpdbg_param_t*); typedef struct _phpdbg_command_t phpdbg_command_t; struct _phpdbg_command_t { @@ -97,8 +99,9 @@ struct _phpdbg_command_t { char alias; /* Alias */ phpdbg_command_handler_t handler; /* Command handler */ const phpdbg_command_t *subs; /* Sub Commands */ - char *args; /* Argument Spec */ - const phpdbg_command_t *parent; /* Parent Command */ + char *args; /* Argument Spec */ + const phpdbg_command_t *parent; /* Parent Command */ + zend_bool flags; /* General flags */ }; /* }}} */ @@ -106,7 +109,7 @@ struct _phpdbg_command_t { #define PHPDBG_STRL(s) s, sizeof(s)-1 #define PHPDBG_MAX_CMD 500 #define PHPDBG_FRAME(v) (PHPDBG_G(frame).v) -#define PHPDBG_EX(v) (EG(current_execute_data)->v) +#define PHPDBG_EX(v) (EG(current_execute_data)->v) typedef struct { int num; @@ -126,27 +129,29 @@ typedef struct { /* * Input Management */ -PHPDBG_API char* phpdbg_read_input(char *buffered TSRMLS_DC); -PHPDBG_API void phpdbg_destroy_input(char** TSRMLS_DC); +PHPDBG_API char* phpdbg_read_input(char *buffered); +PHPDBG_API void phpdbg_destroy_input(char**); +PHPDBG_API int phpdbg_ask_user_permission(const char *question); /** * Stack Management */ PHPDBG_API void phpdbg_stack_push(phpdbg_param_t *stack, phpdbg_param_t *param); -PHPDBG_API const phpdbg_command_t* phpdbg_stack_resolve(const phpdbg_command_t *commands, const phpdbg_command_t *parent, phpdbg_param_t **top, char **why); -PHPDBG_API int phpdbg_stack_verify(const phpdbg_command_t *command, phpdbg_param_t **stack, char **why TSRMLS_DC); -PHPDBG_API int phpdbg_stack_execute(phpdbg_param_t *stack, char **why TSRMLS_DC); +PHPDBG_API void phpdbg_stack_separate(phpdbg_param_t *param); +PHPDBG_API const phpdbg_command_t *phpdbg_stack_resolve(const phpdbg_command_t *commands, const phpdbg_command_t *parent, phpdbg_param_t **top); +PHPDBG_API int phpdbg_stack_verify(const phpdbg_command_t *command, phpdbg_param_t **stack); +PHPDBG_API int phpdbg_stack_execute(phpdbg_param_t *stack, zend_bool allow_async_unsafe); PHPDBG_API void phpdbg_stack_free(phpdbg_param_t *stack); /* * Parameter Management */ -PHPDBG_API void phpdbg_clear_param(phpdbg_param_t* TSRMLS_DC); -PHPDBG_API void phpdbg_copy_param(const phpdbg_param_t*, phpdbg_param_t* TSRMLS_DC); -PHPDBG_API zend_bool phpdbg_match_param(const phpdbg_param_t *, const phpdbg_param_t * TSRMLS_DC); -PHPDBG_API zend_ulong phpdbg_hash_param(const phpdbg_param_t * TSRMLS_DC); -PHPDBG_API const char* phpdbg_get_param_type(const phpdbg_param_t* TSRMLS_DC); -PHPDBG_API char* phpdbg_param_tostring(const phpdbg_param_t *param, char **pointer TSRMLS_DC); +PHPDBG_API void phpdbg_clear_param(phpdbg_param_t*); +PHPDBG_API void phpdbg_copy_param(const phpdbg_param_t*, phpdbg_param_t*); +PHPDBG_API zend_bool phpdbg_match_param(const phpdbg_param_t *, const phpdbg_param_t *); +PHPDBG_API zend_ulong phpdbg_hash_param(const phpdbg_param_t *); +PHPDBG_API const char* phpdbg_get_param_type(const phpdbg_param_t*); +PHPDBG_API char* phpdbg_param_tostring(const phpdbg_param_t *param, char **pointer); PHPDBG_API void phpdbg_param_debug(const phpdbg_param_t *param, const char *msg); /** @@ -154,27 +159,27 @@ PHPDBG_API void phpdbg_param_debug(const phpdbg_param_t *param, const char *msg) */ #define PHPDBG_COMMAND_HANDLER(name) phpdbg_do_##name -#define PHPDBG_COMMAND_D_EXP(name, tip, alias, handler, children, args, parent) \ - {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_##handler, children, args, parent} +#define PHPDBG_COMMAND_D_EXP(name, tip, alias, handler, children, args, parent, flags) \ + {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_##handler, children, args, parent, flags} -#define PHPDBG_COMMAND_D_EX(name, tip, alias, handler, children, args) \ - {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_##handler, children, args, NULL} +#define PHPDBG_COMMAND_D_EX(name, tip, alias, handler, children, args, flags) \ + {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_##handler, children, args, NULL, flags} -#define PHPDBG_COMMAND_D(name, tip, alias, children, args) \ - {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_##name, children, args, NULL} +#define PHPDBG_COMMAND_D(name, tip, alias, children, args, flags) \ + {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, phpdbg_do_##name, children, args, NULL, flags} -#define PHPDBG_COMMAND(name) int phpdbg_do_##name(const phpdbg_param_t *param TSRMLS_DC) +#define PHPDBG_COMMAND(name) int phpdbg_do_##name(const phpdbg_param_t *param) -#define PHPDBG_COMMAND_ARGS param TSRMLS_CC +#define PHPDBG_COMMAND_ARGS param -#define PHPDBG_END_COMMAND {NULL, 0, NULL, 0, '\0', NULL, NULL, '\0', NULL} +#define PHPDBG_END_COMMAND {NULL, 0, NULL, 0, '\0', NULL, NULL, NULL, NULL, 0} /* * Default Switch Case */ #define phpdbg_default_switch_case() \ default: \ - phpdbg_error("Unsupported parameter type (%s) for command", phpdbg_get_param_type(param TSRMLS_CC)); \ + phpdbg_error("command", "type=\"wrongarg\" got=\"%s\"", "Unsupported parameter type (%s) for command", phpdbg_get_param_type(param)); \ break #endif /* PHPDBG_CMD_H */ diff --git a/sapi/phpdbg/phpdbg_eol.c b/sapi/phpdbg/phpdbg_eol.c new file mode 100644 index 0000000000..eaf9997fb4 --- /dev/null +++ b/sapi/phpdbg/phpdbg_eol.c @@ -0,0 +1,172 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2016 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: Anatol Belski <ab@php.net> | + +----------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "phpdbg.h" +#include "phpdbg_eol.h" + +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) + +#define EOL_LIST_LEN 4 +struct phpdbg_eol_rep phpdbg_eol_list[EOL_LIST_LEN] = { + {"CRLF", "\r\n", PHPDBG_EOL_CRLF}, +/* {"LFCR", "\n\r", PHPDBG_EOL_LFCR},*/ + {"LF", "\n", PHPDBG_EOL_LF}, + {"CR", "\r", PHPDBG_EOL_CR}, +}; + +int phpdbg_eol_global_update(char *name) +{ + + if (0 == memcmp(name, "CRLF", 4) || 0 == memcmp(name, "crlf", 4) || 0 == memcmp(name, "DOS", 3) || 0 == memcmp(name, "dos", 3)) { + PHPDBG_G(eol) = PHPDBG_EOL_CRLF; + } else if (0 == memcmp(name, "LF", 2) || 0 == memcmp(name, "lf", 2) || 0 == memcmp(name, "UNIX", 4) || 0 == memcmp(name, "unix", 4)) { + PHPDBG_G(eol) = PHPDBG_EOL_LF; + } else if (0 == memcmp(name, "CR", 2) || 0 == memcmp(name, "cr", 2) || 0 == memcmp(name, "MAC", 3) || 0 == memcmp(name, "mac", 3)) { + PHPDBG_G(eol) = PHPDBG_EOL_CR; + } else { + return FAILURE; + } + + return SUCCESS; +} + +char *phpdbg_eol_name(int id) +{ + size_t i = 0; + + while (i < EOL_LIST_LEN) { + + if (id == phpdbg_eol_list[i].id) { + return phpdbg_eol_list[i].name; + } + + i++; + } + + return NULL; +} + +char *phpdbg_eol_rep(int id) +{ + size_t i = 0; + + while (i < EOL_LIST_LEN) { + + if (id == phpdbg_eol_list[i].id) { + return phpdbg_eol_list[i].rep; + } + + i++; + } + + return NULL; +} + + +/* Inspired by https://ccrma.stanford.edu/~craig/utility/flip/flip.cpp */ +void phpdbg_eol_convert(char **str, int *len) +{ + char *in = *str, *out ; + int in_len = *len, out_len, cursor, i; + char last, cur; + + if ((PHPDBG_G(flags) & PHPDBG_IS_REMOTE) != PHPDBG_IS_REMOTE) { + return; + } + + out_len = *len; + if (PHPDBG_EOL_CRLF == PHPDBG_G(eol)) { /* XXX add LFCR case if it's gonna be needed */ + /* depending on the source EOL the out str will have all CR/LF duplicated */ + for (i = 0; i < in_len; i++) { + if (0x0a == in[i] || 0x0d == in[i]) { + out_len++; + } + } + out = (char *)emalloc(out_len); + + last = cur = in[0]; + i = cursor = 0; + for (; i < in_len;) { + if (0x0a == cur && last != 0x0d) { + out[cursor] = 0x0d; + cursor++; + out[cursor] = cur; + } else if(0x0d == cur) { + if (i + 1 < in_len && 0x0a != in[i+1]) { + out[cursor] = cur; + cursor++; + out[cursor] = 0x0a; + last = 0x0a; + } else { + out[cursor] = 0x0d; + last = 0x0d; + } + } else { + out[cursor] = cur; + last = cur; + } + + i++; + cursor++; + cur = in[i]; + } + + } else if (PHPDBG_EOL_LF == PHPDBG_G(eol) || PHPDBG_EOL_CR == PHPDBG_G(eol)) { + char want, kick; + + if (PHPDBG_EOL_LF == PHPDBG_G(eol)) { + want = 0x0a; + kick = 0x0d; + } else { + want = 0x0d; + kick = 0x0a; + } + + /* We gonna have a smaller or equally long string, estimation is almost neglecting */ + out = (char *)emalloc(out_len); + + last = cur = in[0]; + i = cursor = 0; + for (; cursor < in_len;) { + if (kick == cur) { + out[cursor] = want; + } else if (want == cur) { + if (kick != last) { + out[cursor] = want; + } + } else { + out[cursor] = cur; + } + + last = cur; + cursor++; + cur = in[cursor]; + } + } else { + return; + } + + efree(*str); + *str = erealloc(out, cursor); + *len = cursor; + in = NULL; +} diff --git a/sapi/thttpd/php_thttpd.h b/sapi/phpdbg/phpdbg_eol.h index 6889439924..29fd74f888 100644 --- a/sapi/thttpd/php_thttpd.h +++ b/sapi/phpdbg/phpdbg_eol.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -12,24 +12,35 @@ | 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> | + | Authors: Anatol Belski <ab@php.net> | +----------------------------------------------------------------------+ */ -#ifndef PHP_THTTPD_H -#define PHP_THTTPD_H +#ifndef PHPDBG_EOL_H +#define PHPDBG_EOL_H -#include <sys/types.h> -#include <sys/stat.h> -#include <libhttpd.h> +#include "phpdbg.h" -void thttpd_php_shutdown(void); -void thttpd_php_init(void); -off_t thttpd_php_request(httpd_conn *hc, int show_source); +struct phpdbg_eol_rep { + char *name; + char *rep; + int id; +}; -void thttpd_register_on_close(void (*)(int)); -void thttpd_closed_conn(int fd); -int thttpd_get_fd(void); -void thttpd_set_dont_close(void); +enum { + PHPDBG_EOL_CRLF, /* DOS */ + /*PHPDBG_EOL_LFCR,*/ /* for Risc OS? */ + PHPDBG_EOL_LF, /* UNIX */ + PHPDBG_EOL_CR /* MAC */ +}; + +int phpdbg_eol_global_update(char *name); + +char *phpdbg_eol_name(int id); + +char *phpdbg_eol_rep(int id); + +void phpdbg_eol_convert(char **str, int *len); + +#endif /* PHPDBG_EOL_H */ -#endif diff --git a/sapi/phpdbg/phpdbg_frame.c b/sapi/phpdbg/phpdbg_frame.c index c600961b97..d6256a84af 100644 --- a/sapi/phpdbg/phpdbg_frame.c +++ b/sapi/phpdbg/phpdbg_frame.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -24,9 +24,9 @@ #include "phpdbg_frame.h" #include "phpdbg_list.h" -ZEND_EXTERN_MODULE_GLOBALS(phpdbg); +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) -void phpdbg_restore_frame(TSRMLS_D) /* {{{ */ +void phpdbg_restore_frame(void) /* {{{ */ { if (PHPDBG_FRAME(num) == 0) { return; @@ -37,41 +37,40 @@ void phpdbg_restore_frame(TSRMLS_D) /* {{{ */ /* move things back */ EG(current_execute_data) = PHPDBG_FRAME(execute_data); - EG(opline_ptr) = &PHPDBG_EX(opline); - EG(active_op_array) = PHPDBG_EX(op_array); - EG(return_value_ptr_ptr) = PHPDBG_EX(original_return_value); - EG(active_symbol_table) = PHPDBG_EX(symbol_table); - EG(This) = PHPDBG_EX(current_this); - EG(scope) = PHPDBG_EX(current_scope); - EG(called_scope) = PHPDBG_EX(current_called_scope); + EG(scope) = PHPDBG_EX(func)->op_array.scope; } /* }}} */ -void phpdbg_switch_frame(int frame TSRMLS_DC) /* {{{ */ +void phpdbg_switch_frame(int frame) /* {{{ */ { zend_execute_data *execute_data = PHPDBG_FRAME(num)?PHPDBG_FRAME(execute_data):EG(current_execute_data); int i = 0; if (PHPDBG_FRAME(num) == frame) { - phpdbg_notice("Already in frame #%d", frame); + phpdbg_notice("frame", "id=\"%d\"", "Already in frame #%d", frame); return; } - while (execute_data) { - if (i++ == frame) { - break; - } + phpdbg_try_access { + while (execute_data) { + if (i++ == frame) { + break; + } - do { - execute_data = execute_data->prev_execute_data; - } while (execute_data && execute_data->opline == NULL); - } + do { + execute_data = execute_data->prev_execute_data; + } while (execute_data && execute_data->opline == NULL); + } + } phpdbg_catch_access { + phpdbg_error("signalsegv", "", "Couldn't switch frames, invalid data source"); + return; + } phpdbg_end_try_access(); if (execute_data == NULL) { - phpdbg_error("No frame #%d", frame); + phpdbg_error("frame", "type=\"maxnum\" id=\"%d\"", "No frame #%d", frame); return; } - phpdbg_restore_frame(TSRMLS_C); + phpdbg_restore_frame(); if (frame > 0) { PHPDBG_FRAME(num) = frame; @@ -80,127 +79,166 @@ void phpdbg_switch_frame(int frame TSRMLS_DC) /* {{{ */ PHPDBG_FRAME(execute_data) = EG(current_execute_data); EG(current_execute_data) = execute_data; - EG(opline_ptr) = &PHPDBG_EX(opline); - EG(active_op_array) = PHPDBG_EX(op_array); - PHPDBG_FRAME(execute_data)->original_return_value = EG(return_value_ptr_ptr); - EG(return_value_ptr_ptr) = PHPDBG_EX(original_return_value); - EG(active_symbol_table) = PHPDBG_EX(symbol_table); - EG(This) = PHPDBG_EX(current_this); - EG(scope) = PHPDBG_EX(current_scope); - EG(called_scope) = PHPDBG_EX(current_called_scope); + EG(scope) = PHPDBG_EX(func)->op_array.scope; } - phpdbg_notice("Switched to frame #%d", frame); - phpdbg_list_file( - zend_get_executed_filename(TSRMLS_C), - 3, - zend_get_executed_lineno(TSRMLS_C)-1, - zend_get_executed_lineno(TSRMLS_C) - TSRMLS_CC - ); + phpdbg_notice("frame", "id=\"%d\"", "Switched to frame #%d", frame); + + { + const char *file_chr = zend_get_executed_filename(); + zend_string *file = zend_string_init(file_chr, strlen(file_chr), 0); + phpdbg_list_file(file, 3, zend_get_executed_lineno() - 1, zend_get_executed_lineno()); + efree(file); + } } /* }}} */ -static void phpdbg_dump_prototype(zval **tmp TSRMLS_DC) /* {{{ */ +static void phpdbg_dump_prototype(zval *tmp) /* {{{ */ { - zval **funcname, **class, **type, **args, **argstmp; - char is_class; + zval *funcname, *class, class_zv, *type, *args, *argstmp; - zend_hash_find(Z_ARRVAL_PP(tmp), "function", sizeof("function"), - (void **)&funcname); + funcname = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("function")); - if ((is_class = zend_hash_find(Z_ARRVAL_PP(tmp), - "object", sizeof("object"), (void **)&class)) == FAILURE) { - is_class = zend_hash_find(Z_ARRVAL_PP(tmp), "class", sizeof("class"), - (void **)&class); + if ((class = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("object")))) { + ZVAL_NEW_STR(&class_zv, Z_OBJCE_P(class)->name); + class = &class_zv; } else { - zend_get_object_classname(*class, (const char **)&Z_STRVAL_PP(class), - (zend_uint *)&Z_STRLEN_PP(class) TSRMLS_CC); + class = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("class")); } - if (is_class == SUCCESS) { - zend_hash_find(Z_ARRVAL_PP(tmp), "type", sizeof("type"), (void **)&type); + if (class) { + type = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("type")); } - phpdbg_write("%s%s%s(", - is_class == FAILURE?"":Z_STRVAL_PP(class), - is_class == FAILURE?"":Z_STRVAL_PP(type), - Z_STRVAL_PP(funcname) - ); - - if (zend_hash_find(Z_ARRVAL_PP(tmp), "args", sizeof("args"), - (void **)&args) == SUCCESS) { - HashPosition iterator; - const zend_function *func = phpdbg_get_function( - Z_STRVAL_PP(funcname), is_class == FAILURE ? NULL : Z_STRVAL_PP(class) TSRMLS_CC); - const zend_arg_info *arginfo = func ? func->common.arg_info : NULL; - int j = 0, m = func ? func->common.num_args : 0; + args = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("args")); + + phpdbg_xml(" symbol=\"%s%s%s\"", class ? Z_STRVAL_P(class) : "", class ? Z_STRVAL_P(type) : "", Z_STRVAL_P(funcname)); + + if (args) { + phpdbg_xml(">"); + } else { + phpdbg_xml(" />"); + } + + phpdbg_out("%s%s%s(", class ? Z_STRVAL_P(class) : "", class ? Z_STRVAL_P(type) : "", Z_STRVAL_P(funcname)); + + if (args) { + const zend_function *func = NULL; + const zend_arg_info *arginfo = NULL; zend_bool is_variadic = 0; + int j = 0, m; + + phpdbg_try_access { + /* assuming no autoloader call is necessary, class should have been loaded if it's in backtrace ... */ + if ((func = phpdbg_get_function(Z_STRVAL_P(funcname), class ? Z_STRVAL_P(class) : NULL))) { + arginfo = func->common.arg_info; + } + } phpdbg_end_try_access(); - zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(args), &iterator); - while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(args), - (void **) &argstmp, &iterator) == SUCCESS) { + m = func ? func->common.num_args : 0; + + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args), argstmp) { if (j) { - phpdbg_write(", "); + phpdbg_out(", "); } + phpdbg_xml("<arg %r"); if (m && j < m) { -#if PHP_VERSION_ID >= 50600 - is_variadic = arginfo[j].is_variadic; -#endif - phpdbg_write("%s=%s", - arginfo[j].name, is_variadic ? "[": ""); + char *arg_name = NULL; + + if (arginfo) { + if (func->type == ZEND_INTERNAL_FUNCTION) { + arg_name = (char *)((zend_internal_arg_info *)&arginfo[j])->name; + } else { + arg_name = ZSTR_VAL(arginfo[j].name); + } + } + + if (!is_variadic) { + is_variadic = arginfo ? arginfo[j].is_variadic : 0; + } + + phpdbg_xml(" variadic=\"%s\" name=\"%s\">", is_variadic ? "variadic" : "", arg_name ? arg_name : ""); + phpdbg_out("%s=%s", arg_name ? arg_name : "?", is_variadic ? "[": ""); + + } else { + phpdbg_xml(">"); } ++j; - zend_print_flat_zval_r(*argstmp TSRMLS_CC); - zend_hash_move_forward_ex(Z_ARRVAL_PP(args), &iterator); - } + { + char *arg_print = phpdbg_short_zval_print(argstmp, 40); + php_printf("%s", arg_print); + efree(arg_print); + } + + phpdbg_xml("</arg>"); + } ZEND_HASH_FOREACH_END(); + if (is_variadic) { - phpdbg_write("]"); + phpdbg_out("]"); } + phpdbg_xml("</frame>"); } - phpdbg_write(")"); + phpdbg_out(")"); } -void phpdbg_dump_backtrace(size_t num TSRMLS_DC) /* {{{ */ +void phpdbg_dump_backtrace(size_t num) /* {{{ */ { - zval zbacktrace; - zval **tmp; - zval **file, **line; HashPosition position; + zval zbacktrace; + zval *tmp; + zval startline, startfile; + const char *startfilename; + zval *file = &startfile, *line = &startline; int i = 0, limit = num; - int user_defined; + + PHPDBG_OUTPUT_BACKUP(); if (limit < 0) { - phpdbg_error("Invalid backtrace size %d", limit); + phpdbg_error("backtrace", "type=\"minnum\"", "Invalid backtrace size %d", limit); + + PHPDBG_OUTPUT_BACKUP_RESTORE(); + return; } - zend_fetch_debug_backtrace( - &zbacktrace, 0, 0, limit TSRMLS_CC); + phpdbg_try_access { + zend_fetch_debug_backtrace(&zbacktrace, 0, 0, limit); + } phpdbg_catch_access { + phpdbg_error("signalsegv", "", "Couldn't fetch backtrace, invalid data source"); + return; + } phpdbg_end_try_access(); - zend_hash_internal_pointer_reset_ex(Z_ARRVAL(zbacktrace), &position); - zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), (void**)&tmp, &position); - while (1) { - user_defined = zend_hash_find(Z_ARRVAL_PP(tmp), "file", sizeof("file"), (void **)&file); - zend_hash_find(Z_ARRVAL_PP(tmp), "line", sizeof("line"), (void **)&line); - zend_hash_move_forward_ex(Z_ARRVAL(zbacktrace), &position); + phpdbg_xml("<backtrace %r>"); - if (zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), - (void**)&tmp, &position) == FAILURE) { - phpdbg_write("frame #%d: {main} at %s:%ld", i, Z_STRVAL_PP(file), Z_LVAL_PP(line)); - break; - } + Z_LVAL(startline) = zend_get_executed_lineno(); + startfilename = zend_get_executed_filename(); + Z_STR(startfile) = zend_string_init(startfilename, strlen(startfilename), 0); - if (user_defined == SUCCESS) { - phpdbg_write("frame #%d: ", i++); - phpdbg_dump_prototype(tmp TSRMLS_CC); - phpdbg_writeln(" at %s:%ld", Z_STRVAL_PP(file), Z_LVAL_PP(line)); + zend_hash_internal_pointer_reset_ex(Z_ARRVAL(zbacktrace), &position); + tmp = zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), &position); + while ((tmp = zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), &position))) { + if (file) { /* userland */ + phpdbg_out("frame #%d: ", i); + phpdbg_xml("<frame %r id=\"%d\" file=\"%s\" line=\"" ZEND_LONG_FMT "\"", i, Z_STRVAL_P(file), Z_LVAL_P(line)); + phpdbg_dump_prototype(tmp); + phpdbg_out(" at %s:%ld\n", Z_STRVAL_P(file), Z_LVAL_P(line)); + i++; } else { - phpdbg_write(" => "); - phpdbg_dump_prototype(tmp TSRMLS_CC); - phpdbg_writeln(" (internal function)"); + phpdbg_out(" => "); + phpdbg_xml("<frame %r id=\"%d\" internal=\"internal\"", i); + phpdbg_dump_prototype(tmp); + phpdbg_out(" (internal function)\n"); } + + file = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("file")); + line = zend_hash_str_find(Z_ARRVAL_P(tmp), ZEND_STRL("line")); + zend_hash_move_forward_ex(Z_ARRVAL(zbacktrace), &position); } - phpdbg_writeln(EMPTY); + phpdbg_writeln("frame", "id=\"%d\" symbol=\"{main}\" file=\"%s\" line=\"%d\"", "frame #%d: {main} at %s:%ld", i, Z_STRVAL_P(file), Z_LVAL_P(line)); + phpdbg_xml("</backtrace>"); + zval_dtor(&zbacktrace); + zend_string_release(Z_STR(startfile)); + + PHPDBG_OUTPUT_BACKUP_RESTORE(); } /* }}} */ diff --git a/sapi/phpdbg/phpdbg_frame.h b/sapi/phpdbg/phpdbg_frame.h index b9d7edadf0..237848c29b 100644 --- a/sapi/phpdbg/phpdbg_frame.h +++ b/sapi/phpdbg/phpdbg_frame.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -23,8 +23,8 @@ #include "TSRM.h" -void phpdbg_restore_frame(TSRMLS_D); -void phpdbg_switch_frame(int TSRMLS_DC); -void phpdbg_dump_backtrace(size_t TSRMLS_DC); +void phpdbg_restore_frame(void); +void phpdbg_switch_frame(int); +void phpdbg_dump_backtrace(size_t); #endif /* PHPDBG_FRAME_H */ diff --git a/sapi/phpdbg/phpdbg_help.c b/sapi/phpdbg/phpdbg_help.c index 443e5c8000..839f19100b 100644 --- a/sapi/phpdbg/phpdbg_help.c +++ b/sapi/phpdbg/phpdbg_help.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -22,13 +22,14 @@ #include "phpdbg.h" #include "phpdbg_help.h" #include "phpdbg_prompt.h" +#include "phpdbg_eol.h" #include "zend.h" -ZEND_EXTERN_MODULE_GLOBALS(phpdbg); +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) /* {{{ Commands Table */ #define PHPDBG_COMMAND_HELP_D(name, tip, alias, action) \ - {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, action, NULL, 0} + {PHPDBG_STRL(#name), tip, sizeof(tip)-1, alias, action, &phpdbg_prompt_commands[16], 0} const phpdbg_command_t phpdbg_help_commands[] = { PHPDBG_COMMAND_HELP_D(aliases, "show alias list", 'a', phpdbg_do_help_aliases), @@ -40,11 +41,11 @@ const phpdbg_command_t phpdbg_help_commands[] = { }; /* }}} */ /* {{{ pretty_print. Formatting escapes and wrapping text in a string before printing it. */ -void pretty_print(char *text TSRMLS_DC) +void pretty_print(char *text) { char *new, *p, *q; - const char *prompt_escape = phpdbg_get_prompt(TSRMLS_C); + const char *prompt_escape = phpdbg_get_prompt(); unsigned int prompt_escape_len = strlen(prompt_escape); unsigned int prompt_len = strlen(PHPDBG_G(prompt)[0]); @@ -52,7 +53,7 @@ void pretty_print(char *text TSRMLS_DC) const char *bold_off_escape = PHPDBG_G(flags) & PHPDBG_IS_COLOURED ? "\033[0m" : ""; unsigned int bold_escape_len = strlen(bold_on_escape); - unsigned int term_width = phpdbg_get_terminal_width(TSRMLS_C); + unsigned int term_width = phpdbg_get_terminal_width(); unsigned int size = 0; int in_bold = 0; @@ -61,6 +62,11 @@ void pretty_print(char *text TSRMLS_DC) unsigned int last_blank_count = 0; /* printable char offset of last blank char */ unsigned int line_count = 0; /* number printable chars on current line */ + if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) { + phpdbg_xml("<help %r msg=\"%s\" />", text); + return; + } + /* First pass calculates a safe size for the pretty print version */ for (p = text; *p; p++) { if (UNEXPECTED(p[0] == '*') && p[1] == '*') { @@ -128,24 +134,24 @@ void pretty_print(char *text TSRMLS_DC) *q++ = '\0'; if ((q-new)>size) { - phpdbg_error("Output overrun of %lu bytes", ((q-new) - size)); + phpdbg_error("help", "overrun=\"%lu\"", "Output overrun of %lu bytes", ((q - new) - size)); } - phpdbg_write("%s\n", new); + phpdbg_out("%s\n", new); efree(new); } /* }}} */ /* {{{ summary_print. Print a summary line giving, the command, its alias and tip */ -void summary_print(phpdbg_command_t const * const cmd TSRMLS_DC) +void summary_print(phpdbg_command_t const * const cmd) { char *summary; spprintf(&summary, 0, "Command: **%s** Alias: **%c** **%s**\n", cmd->name, cmd->alias, cmd->tip); - pretty_print(summary TSRMLS_CC); + pretty_print(summary); efree(summary); } /* {{{ get_help. Retries and formats text from the phpdbg help text table */ -static char *get_help(const char * const key TSRMLS_DC) +static char *get_help(const char * const key) { phpdbg_help_text_t *p; @@ -174,7 +180,7 @@ static int get_command( const char *key, size_t len, /* pointer and length of key */ phpdbg_command_t const **command, /* address of first matching command */ phpdbg_command_t const * commands /* command table to be scanned */ - TSRMLS_DC) + ) { const phpdbg_command_t *c; unsigned int num_matches = 0; @@ -201,7 +207,7 @@ static int get_command( return num_matches; -} /* }}} */ +} /* }}} */ PHPDBG_COMMAND(help) /* {{{ */ { @@ -209,40 +215,40 @@ PHPDBG_COMMAND(help) /* {{{ */ int n; if (!param || param->type == EMPTY_PARAM) { - pretty_print(get_help("overview!" TSRMLS_CC) TSRMLS_CC); + pretty_print(get_help("overview!")); return SUCCESS; } if (param && param->type == STR_PARAM) { - n = get_command(param->str, param->len, &cmd, phpdbg_prompt_commands TSRMLS_CC); + n = get_command(param->str, param->len, &cmd, phpdbg_prompt_commands); if (n==1) { - summary_print(cmd TSRMLS_CC); - pretty_print(get_help(cmd->name TSRMLS_CC) TSRMLS_CC); + summary_print(cmd); + pretty_print(get_help(cmd->name)); return SUCCESS; } else if (n>1) { if (param->len > 1) { for (cmd=phpdbg_prompt_commands; cmd->name; cmd++) { if (!strncmp(cmd->name, param->str, param->len)) { - summary_print(cmd TSRMLS_CC); + summary_print(cmd); } } - pretty_print(get_help("duplicate!" TSRMLS_CC) TSRMLS_CC); + pretty_print(get_help("duplicate!")); return SUCCESS; } else { - phpdbg_error("Internal help error, non-unique alias \"%c\"", param->str[0]); + phpdbg_error("help", "type=\"ambiguousalias\" alias=\"%s\"", "Internal help error, non-unique alias \"%c\"", param->str[0]); return FAILURE; } } else { /* no prompt command found so try help topic */ - n = get_command( param->str, param->len, &cmd, phpdbg_help_commands TSRMLS_CC); + n = get_command( param->str, param->len, &cmd, phpdbg_help_commands); if (n>0) { - if (cmd->alias == 'a') { /* help aliases executes a canned routine */ - return cmd->handler(param TSRMLS_CC); + if (cmd->alias == 'a') { /* help aliases executes a canned routine */ + return cmd->handler(param); } else { - pretty_print(get_help(cmd->name TSRMLS_CC) TSRMLS_CC); + pretty_print(get_help(cmd->name)); return SUCCESS; } } @@ -259,35 +265,42 @@ PHPDBG_HELP(aliases) /* {{{ */ int len; /* Print out aliases for all commands except help as this one comes last */ - phpdbg_writeln("Below are the aliased, short versions of all supported commands"); + phpdbg_writeln("help", "", "Below are the aliased, short versions of all supported commands"); + phpdbg_xml("<helpcommands %r>"); for(c = phpdbg_prompt_commands; c->name; c++) { if (c->alias && c->alias != 'h') { - phpdbg_writeln(" %c %-20s %s", c->alias, c->name, c->tip); + phpdbg_writeln("command", "alias=\"%c\" name=\"%s\" tip=\"%s\"", " %c %-20s %s", c->alias, c->name, c->tip); if (c->subs) { len = 20 - 1 - c->name_len; for(c_sub = c->subs; c_sub->alias; c_sub++) { if (c_sub->alias) { - phpdbg_writeln(" %c %c %s %-*s %s", - c->alias, c_sub->alias, (char *)c->name, len, c_sub->name, c_sub->tip); + phpdbg_writeln("subcommand", "parent_alias=\"%c\" alias=\"%c\" parent=\"%s\" name=\"%-*s\" tip=\"%s\"", " %c %c %s %-*s %s", + c->alias, c_sub->alias, c->name, len, c_sub->name, c_sub->tip); } } } } } + phpdbg_xml("</helpcommands>"); + /* Print out aliases for help as this one comes last, with the added text on how aliases are used */ - get_command("h", 1, &c, phpdbg_prompt_commands TSRMLS_CC); - phpdbg_writeln(" %c %-20s %s\n", c->alias, c->name, c->tip); + get_command("h", 1, &c, phpdbg_prompt_commands); + phpdbg_writeln("aliasinfo", "alias=\"%c\" name=\"%s\" tip=\"%s\"", " %c %-20s %s\n", c->alias, c->name, c->tip); + + phpdbg_xml("<helpaliases>"); len = 20 - 1 - c->name_len; for(c_sub = c->subs; c_sub->alias; c_sub++) { if (c_sub->alias) { - phpdbg_writeln(" %c %c %s %-*s %s", + phpdbg_writeln("alias", "parent_alias=\"%c\" alias=\"%c\" parent=\"%s\" name=\"%-*s\" tip=\"%s\"", " %c %c %s %-*s %s", c->alias, c_sub->alias, c->name, len, c_sub->name, c_sub->tip); } } - pretty_print(get_help("aliases!" TSRMLS_CC) TSRMLS_CC); + phpdbg_xml("</helpaliases>"); + + pretty_print(get_help("aliases!")); return SUCCESS; } /* }}} */ @@ -319,7 +332,7 @@ phpdbg_help_text_t phpdbg_help_text[] = { " **list** list PHP source" CR " **info** displays information on the debug session" CR " **print** show opcodes" CR -" **frame** select a stack frame and print a stack frame summary" CR +" **frame** select a stack frame and print a stack frame summary" CR " **back** shows the current backtrace" CR " **help** provide help on a topic" CR CR @@ -329,6 +342,7 @@ phpdbg_help_text_t phpdbg_help_text[] = { " **step** continue execution until other line is reached" CR " **continue** continue execution" CR " **until** continue execution up to the given location" CR +" **next** continue execution up to the given location and halt on the first line after it" CR " **finish** continue up to end of the current execution frame" CR " **leave** continue up to end of the current execution frame and halt after the calling instruction" CR " **break** set a breakpoint at the specified target" CR @@ -362,33 +376,43 @@ phpdbg_help_text_t phpdbg_help_text[] = { " **-c** **-c**/my/php.ini Set php.ini file to load" CR " **-d** **-d**memory_limit=4G Set a php.ini directive" CR " **-n** Disable default php.ini" CR -" **-q** Supress welcome banner" CR +" **-q** Suppress welcome banner" CR " **-v** Enable oplog output" CR -" **-s** Enable stepping" CR " **-b** Disable colour" CR " **-i** **-i**my.init Set .phpdbginit file" CR " **-I** Ignore default .phpdbginit" CR " **-O** **-O**my.oplog Sets oplog output file" CR " **-r** Run execution context" CR -" **-rr** Run execution context and quit after execution" CR +" **-rr** Run execution context and quit after execution (not respecting breakpoints)" CR +" **-e** Generate extended information for debugger/profiler" CR " **-E** Enable step through eval, careful!" CR " **-S** **-S**cli Override SAPI name, careful!" CR " **-l** **-l**4000 Setup remote console ports" CR " **-a** **-a**192.168.0.3 Setup remote console bind address" CR +" **-x** Enable xml output (instead of normal text output)" CR +" **-p** **-p**, **-p=func**, **-p* ** Output opcodes and quit" CR +" **-h** Print the help overview" CR " **-V** Print version number" CR " **--** **--** arg1 arg2 Use to delimit phpdbg arguments and php $argv; append any $argv " "argument after it" CR CR "**Remote Console Mode**" CR CR -"This mode is enabled by specifying the **-a** option. Phpdbg will bind only to the loopback " +"This mode is enabled by specifying the **-a** option. Phpdbg will bind only to the loopback " "interface by default, and this can only be overridden by explicitly setting the remote console " "bind address using the **-a** option. If **-a** is specied without an argument, then phpdbg " "will bind to all available interfaces. You should be aware of the security implications of " "doing this, so measures should be taken to secure this service if bound to a publicly accessible " "interface/port." CR CR -"Specify both stdin and stdout with -lstdin/stdout; by default stdout is stdin * 2." +"**Opcode output**" CR CR + +"Outputting opcodes requires that a file path is passed as last argument. Modes of execution:" CR +"**-p** Outputs the main execution context" CR +"**-p* **Outputs all opcodes in the whole file (including classes and functions)" CR +"**-p=function_name** Outputs opcodes of a given function in the file" CR +"**-p=class_name::** Outputs opcodes of all the methods of a given class" CR +"**-p=class_name::method** Outputs opcodes of a given method" }, {"phpdbginit", CR @@ -400,10 +424,10 @@ phpdbg_help_text_t phpdbg_help_text[] = { "Debugger scripts can also be executed using the **source** command." CR CR "A script file can contain a sequence of valid debugger commands, comments and embedded PHP " -"code. " CR CR +"code. " CR CR "Comment lines are prefixed by the **#** character. Note that comments are only allowed in script " -"files and not in interactive sessions." CR CR +"files and not in interactive sessions." CR CR "PHP code is delimited by the start and end escape tags **<:** and **:>**. PHP code can be used " "to define application context for a debugging session and also to extend the debugger by defining " @@ -545,7 +569,7 @@ phpdbg_help_text_t phpdbg_help_text[] = { " $P break ZEND_ADD" CR " $P b ZEND_ADD" CR -" Break on any occurence of the opcode ZEND_ADD" CR CR +" Break on any occurrence of the opcode ZEND_ADD" CR CR " $P break del 2" CR " $P b ~ 2" CR @@ -596,7 +620,7 @@ phpdbg_help_text_t phpdbg_help_text[] = { }, {"exec", -"The **exec** command sets the execution context, that is the script to be executed. The " +"The **exec** command sets the execution context, that is the script to be executed. The " "execution context must be defined either by executing the **exec** command or by using the " "**-e** command line option." CR CR @@ -625,8 +649,8 @@ phpdbg_help_text_t phpdbg_help_text[] = { {"frame", "The **frame** takes an optional integer argument. If omitted, then the current frame is displayed " -"If specified then the current scope is set to the corresponding frame listed in a **back** trace. " "This can be used to allowing access to the variables in a higher stack frame than that currently " -"being executed." CR CR +"If specified then the current scope is set to the corresponding frame listed in a **back** trace. " +"This can be used to allowing access to the variables in a higher stack frame than that currently being executed." CR CR "**Examples**" CR CR " $P frame 2" CR @@ -639,17 +663,20 @@ phpdbg_help_text_t phpdbg_help_text[] = { {"info", "**info** commands provide quick access to various types of information about the PHP environment" CR +"By default general information about environment and PHP build is shown." CR "Specific info commands are show below:" CR CR " **Target** **Alias** **Purpose**" CR -" **break** **b** show current breakpoints" CR -" **files** **F** show included files" CR -" **classes** **c** show loaded classes" CR -" **funcs** **f** show loaded classes" CR -" **error** **e** show last error" CR -" **vars** **v** show active variables" CR -" **literal** **l** show active literal constants" CR -" **memory** **m** show memory manager stats" +" **break** **b** show current breakpoints" CR +" **files** **F** show included files" CR +" **classes** **c** show loaded classes" CR +" **funcs** **f** show loaded functions" CR +" **error** **e** show last error" CR +" **constants** **d** show user-defined constants" CR +" **vars** **v** show active variables" CR +" **globals** **g** show superglobal variables" CR +" **literal** **l** show active literal constants" CR +" **memory** **m** show memory manager stats" }, // ******** same issue about breakpoints in called frames @@ -724,7 +751,7 @@ phpdbg_help_text_t phpdbg_help_text[] = { }, {"print", -"By default, print will show information about the current execution context." CR +"By default, print will show the opcodes of the current execution context." CR "Other printing commands give access to instruction information." CR "Specific printers loaded are show below:" CR CR @@ -736,6 +763,8 @@ phpdbg_help_text_t phpdbg_help_text[] = { " **func** **f** print out the instructions in the specified function" CR " **stack** **s** print out the instructions in the current stack" CR CR +"In case passed argument does not match a specific printing command, it will treat it as function or method name and print its opcodes" CR CR + "**Examples**" CR CR " $P print class \\\\my\\\\class" CR " $P p c \\\\my\\\\class" CR @@ -875,10 +904,22 @@ phpdbg_help_text_t phpdbg_help_text[] = { " $P s" CR " Will continue and break again in the next encountered line" CR CR }, +{"next", +"The **next** command causes control to be passed back to the vm, continuing execution. Any " +"breakpoints that are encountered before the next source line will be skipped. Execution will" +"be stopped when that line is left." CR CR +"Note when **step**ping is enabled, any opcode steps within the current line are also skipped. "CR CR + +"Note that if the next line is **not** executed then **all** subsequent breakpoints will be " +"skipped. " CR CR + +"Note **next** will trigger a \"not executing\" error if not executing." + +}, {"until", -"The **until** command causes control to be passed back to the vm, continuing execution. Any " -"breakpoints that are encountered before the next source line will be skipped. Execution " +"The **until** command causes control to be passed back to the vm, continuing execution. Any " +"breakpoints that are encountered before the next source line will be skipped. Execution " "will then continue until the next breakpoint or completion of the script" CR CR "Note when **step**ping is enabled, any opcode steps within the current line are also skipped. "CR CR diff --git a/sapi/phpdbg/phpdbg_help.h b/sapi/phpdbg/phpdbg_help.h index 20a954d2d7..7473684d3f 100644 --- a/sapi/phpdbg/phpdbg_help.h +++ b/sapi/phpdbg/phpdbg_help.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -35,9 +35,9 @@ PHPDBG_HELP(aliases); extern const phpdbg_command_t phpdbg_help_commands[]; #define phpdbg_help_header() \ - phpdbg_notice("Welcome to phpdbg, the interactive PHP debugger, v%s", PHPDBG_VERSION); + phpdbg_notice("version", "version=\"%s\"", "Welcome to phpdbg, the interactive PHP debugger, v%s", PHPDBG_VERSION); #define phpdbg_help_footer() \ - phpdbg_notice("Please report bugs to <%s>", PHPDBG_ISSUES); + phpdbg_notice("issues", "url=\"%s\"", "Please report bugs to <%s>", PHPDBG_ISSUES); typedef struct _phpdbg_help_text_t { char *key; diff --git a/sapi/phpdbg/phpdbg_info.c b/sapi/phpdbg/phpdbg_info.c index be71916d65..ddd8229c08 100644 --- a/sapi/phpdbg/phpdbg_info.c +++ b/sapi/phpdbg/phpdbg_info.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -25,52 +25,58 @@ #include "phpdbg_bp.h" #include "phpdbg_prompt.h" -ZEND_EXTERN_MODULE_GLOBALS(phpdbg); +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) -#define PHPDBG_INFO_COMMAND_D(f, h, a, m, l, s) \ - PHPDBG_COMMAND_D_EXP(f, h, a, m, l, s, &phpdbg_prompt_commands[14]) +#define PHPDBG_INFO_COMMAND_D(f, h, a, m, l, s, flags) \ + PHPDBG_COMMAND_D_EXP(f, h, a, m, l, s, &phpdbg_prompt_commands[13], flags) const phpdbg_command_t phpdbg_info_commands[] = { - PHPDBG_INFO_COMMAND_D(break, "show breakpoints", 'b', info_break, NULL, 0), - PHPDBG_INFO_COMMAND_D(files, "show included files", 'F', info_files, NULL, 0), - PHPDBG_INFO_COMMAND_D(classes, "show loaded classes", 'c', info_classes, NULL, 0), - PHPDBG_INFO_COMMAND_D(funcs, "show loaded classes", 'f', info_funcs, NULL, 0), - PHPDBG_INFO_COMMAND_D(error, "show last error", 'e', info_error, NULL, 0), - PHPDBG_INFO_COMMAND_D(vars, "show active variables", 'v', info_vars, NULL, 0), - PHPDBG_INFO_COMMAND_D(literal, "show active literal constants", 'l', info_literal, NULL, 0), - PHPDBG_INFO_COMMAND_D(memory, "show memory manager stats", 'm', info_memory, NULL, 0), + PHPDBG_INFO_COMMAND_D(break, "show breakpoints", 'b', info_break, NULL, 0, PHPDBG_ASYNC_SAFE), + PHPDBG_INFO_COMMAND_D(files, "show included files", 'F', info_files, NULL, 0, PHPDBG_ASYNC_SAFE), + PHPDBG_INFO_COMMAND_D(classes, "show loaded classes", 'c', info_classes, NULL, 0, PHPDBG_ASYNC_SAFE), + PHPDBG_INFO_COMMAND_D(funcs, "show loaded classes", 'f', info_funcs, NULL, 0, PHPDBG_ASYNC_SAFE), + PHPDBG_INFO_COMMAND_D(error, "show last error", 'e', info_error, NULL, 0, PHPDBG_ASYNC_SAFE), + PHPDBG_INFO_COMMAND_D(constants, "show user defined constants", 'd', info_constants, NULL, 0, PHPDBG_ASYNC_SAFE), + PHPDBG_INFO_COMMAND_D(vars, "show active variables", 'v', info_vars, NULL, 0, PHPDBG_ASYNC_SAFE), + PHPDBG_INFO_COMMAND_D(globals, "show superglobals", 'g', info_globals, NULL, 0, PHPDBG_ASYNC_SAFE), + PHPDBG_INFO_COMMAND_D(literal, "show active literal constants", 'l', info_literal, NULL, 0, PHPDBG_ASYNC_SAFE), + PHPDBG_INFO_COMMAND_D(memory, "show memory manager stats", 'm', info_memory, NULL, 0, PHPDBG_ASYNC_SAFE), PHPDBG_END_COMMAND }; PHPDBG_INFO(break) /* {{{ */ { - phpdbg_print_breakpoints(PHPDBG_BREAK_FILE TSRMLS_CC); - phpdbg_print_breakpoints(PHPDBG_BREAK_SYM TSRMLS_CC); - phpdbg_print_breakpoints(PHPDBG_BREAK_METHOD TSRMLS_CC); - phpdbg_print_breakpoints(PHPDBG_BREAK_OPLINE TSRMLS_CC); - phpdbg_print_breakpoints(PHPDBG_BREAK_FILE_OPLINE TSRMLS_CC); - phpdbg_print_breakpoints(PHPDBG_BREAK_FUNCTION_OPLINE TSRMLS_CC); - phpdbg_print_breakpoints(PHPDBG_BREAK_METHOD_OPLINE TSRMLS_CC); - phpdbg_print_breakpoints(PHPDBG_BREAK_COND TSRMLS_CC); - phpdbg_print_breakpoints(PHPDBG_BREAK_OPCODE TSRMLS_CC); + phpdbg_print_breakpoints(PHPDBG_BREAK_FILE); + phpdbg_print_breakpoints(PHPDBG_BREAK_SYM); + phpdbg_print_breakpoints(PHPDBG_BREAK_METHOD); + phpdbg_print_breakpoints(PHPDBG_BREAK_OPLINE); + phpdbg_print_breakpoints(PHPDBG_BREAK_FILE_OPLINE); + phpdbg_print_breakpoints(PHPDBG_BREAK_FUNCTION_OPLINE); + phpdbg_print_breakpoints(PHPDBG_BREAK_METHOD_OPLINE); + phpdbg_print_breakpoints(PHPDBG_BREAK_COND); + phpdbg_print_breakpoints(PHPDBG_BREAK_OPCODE); return SUCCESS; } /* }}} */ PHPDBG_INFO(files) /* {{{ */ { - HashPosition pos; - char *fname; + zend_string *fname; - phpdbg_notice("Included files: %d", - zend_hash_num_elements(&EG(included_files))); + phpdbg_try_access { + phpdbg_notice("includedfilecount", "num=\"%d\"", "Included files: %d", zend_hash_num_elements(&EG(included_files))); + } phpdbg_catch_access { + phpdbg_error("signalsegv", "", "Could not fetch included file count, invalid data source"); + return SUCCESS; + } phpdbg_end_try_access(); - zend_hash_internal_pointer_reset_ex(&EG(included_files), &pos); - while (zend_hash_get_current_key_ex(&EG(included_files), &fname, - NULL, NULL, 0, &pos) == HASH_KEY_IS_STRING) { - phpdbg_writeln("File: %s", fname); - zend_hash_move_forward_ex(&EG(included_files), &pos); - } + phpdbg_try_access { + ZEND_HASH_FOREACH_STR_KEY(&EG(included_files), fname) { + phpdbg_writeln("includedfile", "name=\"%s\"", "File: %s", ZSTR_VAL(fname)); + } ZEND_HASH_FOREACH_END(); + } phpdbg_catch_access { + phpdbg_error("signalsegv", "", "Could not fetch file name, invalid data source, aborting included file listing"); + } phpdbg_end_try_access(); return SUCCESS; } /* }}} */ @@ -78,125 +84,208 @@ PHPDBG_INFO(files) /* {{{ */ PHPDBG_INFO(error) /* {{{ */ { if (PG(last_error_message)) { - phpdbg_writeln("Last error: %s at %s line %d", - PG(last_error_message), PG(last_error_file), PG(last_error_lineno)); + phpdbg_try_access { + phpdbg_writeln("lasterror", "error=\"%s\" file=\"%s\" line=\"%d\"", "Last error: %s at %s line %d", PG(last_error_message), PG(last_error_file), PG(last_error_lineno)); + } phpdbg_catch_access { + phpdbg_notice("lasterror", "error=\"\"", "No error found!"); + } phpdbg_end_try_access(); } else { - phpdbg_notice("No error found!"); + phpdbg_notice("lasterror", "error=\"\"", "No error found!"); } return SUCCESS; } /* }}} */ -PHPDBG_INFO(vars) /* {{{ */ +PHPDBG_INFO(constants) /* {{{ */ { - HashTable vars; - HashPosition pos; - char *var; - zval **data; + HashTable consts; + zend_constant *data; - if (!EG(active_op_array)) { - phpdbg_error("No active op array!"); - return SUCCESS; + zend_hash_init(&consts, 8, NULL, NULL, 0); + + if (EG(zend_constants)) { + phpdbg_try_access { + ZEND_HASH_FOREACH_PTR(EG(zend_constants), data) { + if (data->module_number == PHP_USER_CONSTANT) { + zend_hash_update_ptr(&consts, data->name, data); + } + } ZEND_HASH_FOREACH_END(); + } phpdbg_catch_access { + phpdbg_error("signalsegv", "", "Cannot fetch all the constants, invalid data source"); + } phpdbg_end_try_access(); } - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); + phpdbg_notice("constantinfo", "num=\"%d\"", "User-defined constants (%d)", zend_hash_num_elements(&consts)); + + if (zend_hash_num_elements(&consts)) { + phpdbg_out("Address Refs Type Constant\n"); + ZEND_HASH_FOREACH_PTR(&consts, data) { + +#define VARIABLEINFO(attrs, msg, ...) \ + phpdbg_writeln("constant", \ + "address=\"%p\" refcount=\"%d\" type=\"%s\" name=\"%.*s\" " attrs, \ + "%-18p %-7d %-9s %.*s" msg, &data->value, \ + Z_REFCOUNTED(data->value) ? Z_REFCOUNT(data->value) : 1, \ + zend_zval_type_name(&data->value), \ + (int) ZSTR_LEN(data->name), ZSTR_VAL(data->name), ##__VA_ARGS__) + + switch (Z_TYPE(data->value)) { + case IS_STRING: + phpdbg_try_access { + VARIABLEINFO("length=\"%zd\" value=\"%.*s\"", "\nstring (%zd) \"%.*s%s\"", Z_STRLEN(data->value), Z_STRLEN(data->value) < 255 ? (int) Z_STRLEN(data->value) : 255, Z_STRVAL(data->value), Z_STRLEN(data->value) > 255 ? "..." : ""); + } phpdbg_catch_access { + VARIABLEINFO("", ""); + } phpdbg_end_try_access(); + break; + case IS_TRUE: + VARIABLEINFO("value=\"true\"", "\nbool (true)"); + break; + case IS_FALSE: + VARIABLEINFO("value=\"false\"", "\nbool (false)"); + break; + case IS_LONG: + VARIABLEINFO("value=\"%ld\"", "\nint (%ld)", Z_LVAL(data->value)); + break; + case IS_DOUBLE: + VARIABLEINFO("value=\"%lf\"", "\ndouble (%lf)", Z_DVAL(data->value)); + break; + default: + VARIABLEINFO("", ""); + +#undef VARIABLEINFO + } + } ZEND_HASH_FOREACH_END(); + } - if (!EG(active_symbol_table)) { - phpdbg_error("No active symbol table!"); - return SUCCESS; + return SUCCESS; +} /* }}} */ + +static int phpdbg_arm_auto_global(zval *ptrzv) { + zend_auto_global *auto_global = Z_PTR_P(ptrzv); + + if (auto_global->armed) { + if (PHPDBG_G(flags) & PHPDBG_IN_SIGNAL_HANDLER) { + phpdbg_notice("variableinfo", "unreachable=\"%.*s\"", "Cannot show information about superglobal variable %.*s", (int) ZSTR_LEN(auto_global->name), ZSTR_VAL(auto_global->name)); + } else { + auto_global->armed = auto_global->auto_global_callback(auto_global->name); } } - zend_hash_init(&vars, 8, NULL, NULL, 0); + return 0; +} - zend_hash_internal_pointer_reset_ex(EG(active_symbol_table), &pos); - while (zend_hash_get_current_key_ex(EG(active_symbol_table), &var, - NULL, NULL, 0, &pos) == HASH_KEY_IS_STRING) { - zend_hash_get_current_data_ex(EG(active_symbol_table), (void **)&data, &pos); - if (*var != '_') { - zend_hash_update( - &vars, var, strlen(var)+1, (void**)data, sizeof(zval*), NULL); - } - zend_hash_move_forward_ex(EG(active_symbol_table), &pos); +static int phpdbg_print_symbols(zend_bool show_globals) { + HashTable vars; + zend_array *symtable; + zend_string *var; + zval *data; + + if (!EG(current_execute_data) || !EG(current_execute_data)->func) { + phpdbg_error("inactive", "type=\"op_array\"", "No active op array!"); + return SUCCESS; + } + + if (show_globals) { + /* that array should only be manipulated during init, so safe for async access during execution */ + zend_hash_apply(CG(auto_globals), (apply_func_t) phpdbg_arm_auto_global); + symtable = &EG(symbol_table); + } else if (!(symtable = zend_rebuild_symbol_table())) { + phpdbg_error("inactive", "type=\"symbol_table\"", "No active symbol table!"); + return SUCCESS; } - { - zend_op_array *ops = EG(active_op_array); - + zend_hash_init(&vars, 8, NULL, NULL, 0); + + phpdbg_try_access { + ZEND_HASH_FOREACH_STR_KEY_VAL(symtable, var, data) { + if (zend_is_auto_global(var) ^ !show_globals) { + zend_hash_update(&vars, var, data); + } + } ZEND_HASH_FOREACH_END(); + } phpdbg_catch_access { + phpdbg_error("signalsegv", "", "Cannot fetch all data from the symbol table, invalid data source"); + } phpdbg_end_try_access(); + + if (show_globals) { + phpdbg_notice("variableinfo", "num=\"%d\"", "Superglobal variables (%d)", zend_hash_num_elements(&vars)); + } else { + zend_op_array *ops = &EG(current_execute_data)->func->op_array; + if (ops->function_name) { if (ops->scope) { - phpdbg_notice( - "Variables in %s::%s() (%d)", ops->scope->name, ops->function_name, zend_hash_num_elements(&vars)); + phpdbg_notice("variableinfo", "method=\"%s::%s\" num=\"%d\"", "Variables in %s::%s() (%d)", ops->scope->name->val, ops->function_name->val, zend_hash_num_elements(&vars)); } else { - phpdbg_notice( - "Variables in %s() (%d)", ops->function_name, zend_hash_num_elements(&vars)); + phpdbg_notice("variableinfo", "function=\"%s\" num=\"%d\"", "Variables in %s() (%d)", ZSTR_VAL(ops->function_name), zend_hash_num_elements(&vars)); } } else { if (ops->filename) { - phpdbg_notice( - "Variables in %s (%d)", ops->filename, zend_hash_num_elements(&vars)); + phpdbg_notice("variableinfo", "file=\"%s\" num=\"%d\"", "Variables in %s (%d)", ZSTR_VAL(ops->filename), zend_hash_num_elements(&vars)); } else { - phpdbg_notice( - "Variables @ %p (%d)", ops, zend_hash_num_elements(&vars)); + phpdbg_notice("variableinfo", "opline=\"%p\" num=\"%d\"", "Variables @ %p (%d)", ops, zend_hash_num_elements(&vars)); } } } if (zend_hash_num_elements(&vars)) { - phpdbg_writeln("Address\t\tRefs\tType\t\tVariable"); - for (zend_hash_internal_pointer_reset_ex(&vars, &pos); - zend_hash_get_current_data_ex(&vars, (void**) &data, &pos) == SUCCESS; - zend_hash_move_forward_ex(&vars, &pos)) { - char *var; - - zend_hash_get_current_key_ex(&vars, &var, NULL, NULL, 0, &pos); - - if (*data) { - phpdbg_write( - "%p\t%d\t", - *data, - Z_REFCOUNT_PP(data)); - - switch (Z_TYPE_PP(data)) { - case IS_STRING: phpdbg_write("(string)\t"); break; - case IS_LONG: phpdbg_write("(integer)\t"); break; - case IS_DOUBLE: phpdbg_write("(float)\t"); break; - case IS_RESOURCE: phpdbg_write("(resource)\t"); break; - case IS_ARRAY: phpdbg_write("(array)\t"); break; - case IS_OBJECT: phpdbg_write("(object)\t"); break; - case IS_NULL: phpdbg_write("(null)\t"); break; + phpdbg_out("Address Refs Type Variable\n"); + ZEND_HASH_FOREACH_STR_KEY_VAL(&vars, var, data) { + phpdbg_try_access { + const char *isref = ""; +#define VARIABLEINFO(attrs, msg, ...) \ + phpdbg_writeln("variable", \ + "address=\"%p\" refcount=\"%d\" type=\"%s\" refstatus=\"%s\" name=\"%.*s\" " attrs, \ + "%-18p %-7d %-9s %s$%.*s" msg, data, Z_REFCOUNTED_P(data) ? Z_REFCOUNT_P(data) : 1, zend_zval_type_name(data), isref, (int) ZSTR_LEN(var), ZSTR_VAL(var), ##__VA_ARGS__) +retry_switch: + switch (Z_TYPE_P(data)) { + case IS_RESOURCE: + phpdbg_try_access { + const char *type = zend_rsrc_list_get_rsrc_type(Z_RES_P(data)); + VARIABLEINFO("type=\"%s\"", "\n|-------(typeof)------> (%s)\n", type ? type : "unknown"); + } phpdbg_catch_access { + VARIABLEINFO("type=\"unknown\"", "\n|-------(typeof)------> (unknown)\n"); + } phpdbg_end_try_access(); + break; + case IS_OBJECT: + phpdbg_try_access { + VARIABLEINFO("instanceof=\"%s\"", "\n|-----(instanceof)----> (%s)\n", ZSTR_VAL(Z_OBJCE_P(data)->name)); + } phpdbg_catch_access { + VARIABLEINFO("instanceof=\"%s\"", "\n|-----(instanceof)----> (unknown)\n"); + } phpdbg_end_try_access(); + break; + case IS_STRING: + phpdbg_try_access { + VARIABLEINFO("length=\"%zd\" value=\"%.*s\"", "\nstring (%zd) \"%.*s%s\"", Z_STRLEN_P(data), Z_STRLEN_P(data) < 255 ? (int) Z_STRLEN_P(data) : 255, Z_STRVAL_P(data), Z_STRLEN_P(data) > 255 ? "..." : ""); + } phpdbg_catch_access { + VARIABLEINFO("", ""); + } phpdbg_end_try_access(); + break; + case IS_TRUE: + VARIABLEINFO("value=\"true\"", "\nbool (true)"); + break; + case IS_FALSE: + VARIABLEINFO("value=\"false\"", "\nbool (false)"); + break; + case IS_LONG: + VARIABLEINFO("value=\"%ld\"", "\nint (%ld)", Z_LVAL_P(data)); + break; + case IS_DOUBLE: + VARIABLEINFO("value=\"%lf\"", "\ndouble (%lf)", Z_DVAL_P(data)); + break; + case IS_REFERENCE: + isref = "&"; + data = Z_REFVAL_P(data); + goto retry_switch; + case IS_INDIRECT: + data = Z_INDIRECT_P(data); + goto retry_switch; + default: + VARIABLEINFO("", ""); } - if (Z_TYPE_PP(data) == IS_RESOURCE) { - int type; - - phpdbg_writeln( - "%s$%s", Z_ISREF_PP(data) ? "&": "", var); - if (zend_list_find(Z_RESVAL_PP(data), &type)) { - phpdbg_write( - "|-------(typeof)------> (%s)", - zend_rsrc_list_get_rsrc_type(type TSRMLS_CC)); - } else { - phpdbg_write( - "|-------(typeof)------> (unknown)"); - } - phpdbg_writeln(EMPTY); - } else if (Z_TYPE_PP(data) == IS_OBJECT) { - phpdbg_writeln( - "%s$%s", Z_ISREF_PP(data) ? "&": "", var); - phpdbg_write( - "|-----(instanceof)----> (%s)", Z_OBJCE_PP(data)->name); - phpdbg_writeln(EMPTY); - } else { - phpdbg_write( - "%s$%s", Z_ISREF_PP(data) ? "&": "", var); - } - } else { - phpdbg_write( - "n/a\tn/a\tn/a\t$%s", var); - } - phpdbg_writeln(EMPTY); - } +#undef VARIABLEINFO + } phpdbg_catch_access { + phpdbg_writeln("variable", "address=\"%p\" name=\"%s\"", "%p\tn/a\tn/a\t$%s", data, ZSTR_VAL(var)); + } phpdbg_end_try_access(); + } ZEND_HASH_FOREACH_END(); } zend_hash_destroy(&vars); @@ -204,42 +293,48 @@ PHPDBG_INFO(vars) /* {{{ */ return SUCCESS; } /* }}} */ +PHPDBG_INFO(vars) /* {{{ */ +{ + return phpdbg_print_symbols(0); +} + +PHPDBG_INFO(globals) /* {{{ */ +{ + return phpdbg_print_symbols(1); +} + PHPDBG_INFO(literal) /* {{{ */ { - if ((EG(in_execution) && EG(active_op_array)) || PHPDBG_G(ops)) { - zend_op_array *ops = EG(active_op_array) ? EG(active_op_array) : PHPDBG_G(ops); - int literal = 0, count = ops->last_literal-1; + /* literals are assumed to not be manipulated during executing of their op_array and as such async safe */ + zend_bool in_executor = PHPDBG_G(in_execution) && EG(current_execute_data) && EG(current_execute_data)->func; + if (in_executor || PHPDBG_G(ops)) { + zend_op_array *ops = in_executor ? &EG(current_execute_data)->func->op_array : PHPDBG_G(ops); + int literal = 0, count = ops->last_literal - 1; if (ops->function_name) { if (ops->scope) { - phpdbg_notice( - "Literal Constants in %s::%s() (%d)", ops->scope->name, ops->function_name, count); + phpdbg_notice("literalinfo", "method=\"%s::%s\" num=\"%d\"", "Literal Constants in %s::%s() (%d)", ops->scope->name->val, ops->function_name->val, count); } else { - phpdbg_notice( - "Literal Constants in %s() (%d)", ops->function_name, count); + phpdbg_notice("literalinfo", "function=\"%s\" num=\"%d\"", "Literal Constants in %s() (%d)", ops->function_name->val, count); } } else { if (ops->filename) { - phpdbg_notice( - "Literal Constants in %s (%d)", ops->filename, count); + phpdbg_notice("literalinfo", "file=\"%s\" num=\"%d\"", "Literal Constants in %s (%d)", ZSTR_VAL(ops->filename), count); } else { - phpdbg_notice( - "Literal Constants @ %p (%d)", ops, count); + phpdbg_notice("literalinfo", "opline=\"%p\" num=\"%d\"", "Literal Constants @ %p (%d)", ops, count); } } while (literal < ops->last_literal) { - if (Z_TYPE(ops->literals[literal].constant) != IS_NULL) { - phpdbg_write("|-------- C%u -------> [", literal); - zend_print_zval( - &ops->literals[literal].constant, 0); - phpdbg_write("]"); - phpdbg_writeln(EMPTY); + if (Z_TYPE(ops->literals[literal]) != IS_NULL) { + phpdbg_write("literal", "id=\"%u\"", "|-------- C%u -------> [", literal); + zend_print_zval(&ops->literals[literal], 0); + phpdbg_out("]\n"); } literal++; } } else { - phpdbg_error("Not executing!"); + phpdbg_error("inactive", "type=\"execution\"", "Not executing!"); } return SUCCESS; @@ -247,85 +342,85 @@ PHPDBG_INFO(literal) /* {{{ */ PHPDBG_INFO(memory) /* {{{ */ { - if (is_zend_mm(TSRMLS_C)) { - phpdbg_notice("Memory Manager Information"); - phpdbg_notice("Current"); - phpdbg_writeln("|-------> Used:\t%.3f kB", - (float) (zend_memory_usage(0 TSRMLS_CC)/1024)); - phpdbg_writeln("|-------> Real:\t%.3f kB", - (float) (zend_memory_usage(1 TSRMLS_CC)/1024)); - phpdbg_notice("Peak"); - phpdbg_writeln("|-------> Used:\t%.3f kB", - (float) (zend_memory_peak_usage(0 TSRMLS_CC)/1024)); - phpdbg_writeln("|-------> Real:\t%.3f kB", - (float) (zend_memory_peak_usage(1 TSRMLS_CC)/1024)); + size_t used, real, peak_used, peak_real; + zend_mm_heap *heap; + zend_bool is_mm; + + if (PHPDBG_G(flags) & PHPDBG_IN_SIGNAL_HANDLER) { + heap = zend_mm_set_heap(phpdbg_original_heap_sigsafe_mem()); + } + if ((is_mm = is_zend_mm())) { + used = zend_memory_usage(0); + real = zend_memory_usage(1); + peak_used = zend_memory_peak_usage(0); + peak_real = zend_memory_peak_usage(1); + } + if (PHPDBG_G(flags) & PHPDBG_IN_SIGNAL_HANDLER) { + zend_mm_set_heap(heap); + } + + if (is_mm) { + phpdbg_notice("meminfo", "", "Memory Manager Information"); + phpdbg_notice("current", "", "Current"); + phpdbg_writeln("used", "mem=\"%.3f\"", "|-------> Used:\t%.3f kB", (float) (used / 1024)); + phpdbg_writeln("real", "mem=\"%.3f\"", "|-------> Real:\t%.3f kB", (float) (real / 1024)); + phpdbg_notice("peak", "", "Peak"); + phpdbg_writeln("used", "mem=\"%.3f\"", "|-------> Used:\t%.3f kB", (float) (peak_used / 1024)); + phpdbg_writeln("real", "mem=\"%.3f\"", "|-------> Real:\t%.3f kB", (float) (peak_real / 1024)); } else { - phpdbg_error("Memory Manager Disabled!"); + phpdbg_error("inactive", "type=\"memory_manager\"", "Memory Manager Disabled!"); } return SUCCESS; } /* }}} */ -static inline void phpdbg_print_class_name(zend_class_entry **ce TSRMLS_DC) /* {{{ */ +static inline void phpdbg_print_class_name(zend_class_entry *ce) /* {{{ */ { - phpdbg_write( - "%s %s %s (%d)", - ((*ce)->type == ZEND_USER_CLASS) ? - "User" : "Internal", - ((*ce)->ce_flags & ZEND_ACC_INTERFACE) ? - "Interface" : - ((*ce)->ce_flags & ZEND_ACC_ABSTRACT) ? - "Abstract Class" : - "Class", - (*ce)->name, zend_hash_num_elements(&(*ce)->function_table)); + const char *visibility = ce->type == ZEND_USER_CLASS ? "User" : "Internal"; + const char *type = (ce->ce_flags & ZEND_ACC_INTERFACE) ? "Interface" : (ce->ce_flags & ZEND_ACC_ABSTRACT) ? "Abstract Class" : "Class"; + + phpdbg_writeln("class", "type=\"%s\" flags=\"%s\" name=\"%.*s\" methodcount=\"%d\"", "%s %s %.*s (%d)", visibility, type, (int) ZSTR_LEN(ce->name), ZSTR_VAL(ce->name), zend_hash_num_elements(&ce->function_table)); } /* }}} */ PHPDBG_INFO(classes) /* {{{ */ { - HashPosition position; - zend_class_entry **ce; + zend_class_entry *ce; HashTable classes; zend_hash_init(&classes, 8, NULL, NULL, 0); - for (zend_hash_internal_pointer_reset_ex(EG(class_table), &position); - zend_hash_get_current_data_ex(EG(class_table), (void**)&ce, &position) == SUCCESS; - zend_hash_move_forward_ex(EG(class_table), &position)) { - - if ((*ce)->type == ZEND_USER_CLASS) { - zend_hash_next_index_insert( - &classes, ce, sizeof(ce), NULL); - } - } - - phpdbg_notice("User Classes (%d)", - zend_hash_num_elements(&classes)); + phpdbg_try_access { + ZEND_HASH_FOREACH_PTR(EG(class_table), ce) { + if (ce->type == ZEND_USER_CLASS) { + zend_hash_next_index_insert_ptr(&classes, ce); + } + } ZEND_HASH_FOREACH_END(); + } phpdbg_catch_access { + phpdbg_notice("signalsegv", "", "Not all classes could be fetched, possibly invalid data source"); + } phpdbg_end_try_access(); - for (zend_hash_internal_pointer_reset_ex(&classes, &position); - zend_hash_get_current_data_ex(&classes, (void**)&ce, &position) == SUCCESS; - zend_hash_move_forward_ex(&classes, &position)) { + phpdbg_notice("classinfo", "num=\"%d\"", "User Classes (%d)", zend_hash_num_elements(&classes)); - phpdbg_print_class_name(ce TSRMLS_CC); - phpdbg_writeln(EMPTY); + /* once added, assume that classes are stable... until shutdown. */ + ZEND_HASH_FOREACH_PTR(&classes, ce) { + phpdbg_print_class_name(ce); - if ((*ce)->parent) { - zend_class_entry *pce = (*ce)->parent; + if (ce->parent) { + zend_class_entry *pce; + phpdbg_xml("<parents %r>"); + pce = ce->parent; do { - phpdbg_write("|-------- "); - phpdbg_print_class_name(&pce TSRMLS_CC); - phpdbg_writeln(EMPTY); + phpdbg_out("|-------- "); + phpdbg_print_class_name(pce); } while ((pce = pce->parent)); + phpdbg_xml("</parents>"); } - if ((*ce)->info.user.filename) { - phpdbg_writeln( - "|---- in %s on line %u", - (*ce)->info.user.filename, - (*ce)->info.user.line_start); + if (ce->info.user.filename) { + phpdbg_writeln("classsource", "file=\"%s\" line=\"%u\"", "|---- in %s on line %u", ZSTR_VAL(ce->info.user.filename), ce->info.user.line_start); } else { - phpdbg_writeln("|---- no source code"); + phpdbg_writeln("classsource", "", "|---- no source code"); } - phpdbg_writeln(EMPTY); - } + } ZEND_HASH_FOREACH_END(); zend_hash_destroy(&classes); @@ -334,36 +429,34 @@ PHPDBG_INFO(classes) /* {{{ */ PHPDBG_INFO(funcs) /* {{{ */ { - HashPosition position; - zend_function *zf, **pzf; + zend_function *zf; HashTable functions; zend_hash_init(&functions, 8, NULL, NULL, 0); - for (zend_hash_internal_pointer_reset_ex(EG(function_table), &position); - zend_hash_get_current_data_ex(EG(function_table), (void**)&zf, &position) == SUCCESS; - zend_hash_move_forward_ex(EG(function_table), &position)) { + phpdbg_try_access { + ZEND_HASH_FOREACH_PTR(EG(function_table), zf) { + if (zf->type == ZEND_USER_FUNCTION) { + zend_hash_next_index_insert_ptr(&functions, zf); + } + } ZEND_HASH_FOREACH_END(); + } phpdbg_catch_access { + phpdbg_notice("signalsegv", "", "Not all functions could be fetched, possibly invalid data source"); + } phpdbg_end_try_access(); - if (zf->type == ZEND_USER_FUNCTION) { - zend_hash_next_index_insert( - &functions, (void**) &zf, sizeof(zend_function), NULL); - } - } + phpdbg_notice("functioninfo", "num=\"%d\"", "User Functions (%d)", zend_hash_num_elements(&functions)); - phpdbg_notice("User Functions (%d)", - zend_hash_num_elements(&functions)); + ZEND_HASH_FOREACH_PTR(&functions, zf) { + zend_op_array *op_array = &zf->op_array; - for (zend_hash_internal_pointer_reset_ex(&functions, &position); - zend_hash_get_current_data_ex(&functions, (void**)&pzf, &position) == SUCCESS; - zend_hash_move_forward_ex(&functions, &position)) { - zend_op_array *op_array = &((*pzf)->op_array); + phpdbg_write("function", "name=\"%s\"", "|-------- %s", op_array->function_name ? ZSTR_VAL(op_array->function_name) : "{main}"); - phpdbg_writeln( - "|-------- %s in %s on line %d", - op_array->function_name ? op_array->function_name : "{main}", - op_array->filename ? op_array->filename : "(no source code)", - op_array->line_start); - } + if (op_array->filename) { + phpdbg_writeln("functionsource", "file=\"%s\" line=\"%d\"", " in %s on line %d", ZSTR_VAL(op_array->filename), op_array->line_start); + } else { + phpdbg_writeln("functionsource", "", " (no source code)"); + } + } ZEND_HASH_FOREACH_END(); zend_hash_destroy(&functions); diff --git a/sapi/phpdbg/phpdbg_info.h b/sapi/phpdbg/phpdbg_info.h index 2fcf91e649..3e7d585576 100644 --- a/sapi/phpdbg/phpdbg_info.h +++ b/sapi/phpdbg/phpdbg_info.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -30,7 +30,9 @@ PHPDBG_INFO(break); PHPDBG_INFO(classes); PHPDBG_INFO(funcs); PHPDBG_INFO(error); +PHPDBG_INFO(constants); PHPDBG_INFO(vars); +PHPDBG_INFO(globals); PHPDBG_INFO(literal); PHPDBG_INFO(memory); diff --git a/sapi/phpdbg/phpdbg_io.c b/sapi/phpdbg/phpdbg_io.c new file mode 100644 index 0000000000..b2f4ba7c0d --- /dev/null +++ b/sapi/phpdbg/phpdbg_io.c @@ -0,0 +1,361 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2016 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: Anatol Belski <ab@php.net> | + +----------------------------------------------------------------------+ +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "phpdbg_io.h" + +#ifdef PHP_WIN32 +#undef UNICODE +#include "win32/inet.h" +#include <winsock2.h> +#include <windows.h> +#include <Ws2tcpip.h> +#include "win32/sockets.h" + +#else + +#if HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#include <sys/socket.h> +#include <netinet/in.h> +#if HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif +#include <netdb.h> +#include <fcntl.h> +#include <poll.h> +#endif + +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) + +/* is easy to generalize ... but not needed for now */ +PHPDBG_API int phpdbg_consume_stdin_line(char *buf) { + int bytes = PHPDBG_G(input_buflen), len = 0; + + if (PHPDBG_G(input_buflen)) { + memcpy(buf, PHPDBG_G(input_buffer), bytes); + } + + PHPDBG_G(last_was_newline) = 1; + + do { + int i; + if (bytes <= 0) { + continue; + } + + for (i = len; i < len + bytes; i++) { + if (buf[i] == '\x03') { + if (i != len + bytes - 1) { + memmove(buf + i, buf + i + 1, len + bytes - i - 1); + } + len--; + i--; + continue; + } + if (buf[i] == '\n') { + PHPDBG_G(input_buflen) = len + bytes - 1 - i; + if (PHPDBG_G(input_buflen)) { + memcpy(PHPDBG_G(input_buffer), buf + i + 1, PHPDBG_G(input_buflen)); + } + if (i != PHPDBG_MAX_CMD - 1) { + buf[i + 1] = 0; + } + return i; + } + } + + len += bytes; + } while ((bytes = phpdbg_mixed_read(PHPDBG_G(io)[PHPDBG_STDIN].fd, buf + len, PHPDBG_MAX_CMD - len, -1)) > 0); + + if (bytes <= 0) { + PHPDBG_G(flags) |= PHPDBG_IS_QUITTING | PHPDBG_IS_DISCONNECTED; + zend_bailout(); + } + + return bytes; +} + +PHPDBG_API int phpdbg_consume_bytes(int sock, char *ptr, int len, int tmo) { + int got_now, i = len, j; + char *p = ptr; +#ifndef PHP_WIN32 + struct pollfd pfd; + + if (tmo < 0) goto recv_once; + pfd.fd = sock; + pfd.events = POLLIN; + + j = poll(&pfd, 1, tmo); + + if (j == 0) { +#else + struct fd_set readfds; + struct timeval ttmo; + + if (tmo < 0) goto recv_once; + FD_ZERO(&readfds); + FD_SET(sock, &readfds); + + ttmo.tv_sec = 0; + ttmo.tv_usec = tmo*1000; + + j = select(0, &readfds, NULL, NULL, &ttmo); + + if (j <= 0) { +#endif + return -1; + } + +recv_once: + while(i > 0) { + if (tmo < 0) { + /* There's something to read. Read what's available and proceed + disregarding whether len could be exhausted or not.*/ + int can_read = recv(sock, p, i, MSG_PEEK); +#ifndef _WIN32 + if (can_read == -1 && errno == EINTR) { + continue; + } +#endif + i = can_read; + } + +#ifdef _WIN32 + got_now = recv(sock, p, i, 0); +#else + do { + got_now = recv(sock, p, i, 0); + } while (got_now == -1 && errno == EINTR); +#endif + + if (got_now == -1) { + quiet_write(PHPDBG_G(io)[PHPDBG_STDERR].fd, ZEND_STRL("Read operation timed out!\n")); + return -1; + } + i -= got_now; + p += got_now; + } + + return p - ptr; +} + +PHPDBG_API int phpdbg_send_bytes(int sock, const char *ptr, int len) { + int sent, i = len; + const char *p = ptr; +/* XXX poll/select needed here? */ + while(i > 0) { + sent = send(sock, p, i, 0); + if (sent == -1) { + return -1; + } + i -= sent; + p += sent; + } + + return len; +} + + +PHPDBG_API int phpdbg_mixed_read(int sock, char *ptr, int len, int tmo) { + int ret; + + if (PHPDBG_G(flags) & PHPDBG_IS_REMOTE) { + return phpdbg_consume_bytes(sock, ptr, len, tmo); + } + + do { + ret = read(sock, ptr, len); + } while (ret == -1 && errno == EINTR); + + return ret; +} + +static int phpdbg_output_pager(int sock, const char *ptr, int len) { + int count = 0, bytes = 0; + const char *p = ptr, *endp = ptr + len; + + while ((p = memchr(p, '\n', endp - p))) { + count++; + p++; + + if (count % PHPDBG_G(lines) == 0) { + bytes += write(sock, ptr + bytes, (p - ptr) - bytes); + + if (memchr(p, '\n', endp - p)) { + char buf[PHPDBG_MAX_CMD]; + write(sock, ZEND_STRL("\r---Type <return> to continue or q <return> to quit---")); + phpdbg_consume_stdin_line(buf); + if (*buf == 'q') { + break; + } + write(sock, "\r", 1); + } else break; + } + } + if (bytes && count % PHPDBG_G(lines) != 0) { + bytes += write(sock, ptr + bytes, len - bytes); + } else if (!bytes) { + bytes += write(sock, ptr, len); + } + return bytes; +} + +PHPDBG_API int phpdbg_mixed_write(int sock, const char *ptr, int len) { + if (PHPDBG_G(flags) & PHPDBG_IS_REMOTE) { + return phpdbg_send_bytes(sock, ptr, len); + } + + if ((PHPDBG_G(flags) & PHPDBG_HAS_PAGINATION) + && !(PHPDBG_G(flags) & PHPDBG_WRITE_XML) + && PHPDBG_G(io)[PHPDBG_STDOUT].fd == sock + && PHPDBG_G(lines) > 0) { + return phpdbg_output_pager(sock, ptr, len); + } + + return write(sock, ptr, len); +} + +PHPDBG_API int phpdbg_open_socket(const char *interface, unsigned short port) { + struct addrinfo res; + int fd = phpdbg_create_listenable_socket(interface, port, &res); + + if (fd == -1) { + return -1; + } + + if (bind(fd, res.ai_addr, res.ai_addrlen) == -1) { + phpdbg_close_socket(fd); + return -4; + } + + listen(fd, 5); + + return fd; +} + + +PHPDBG_API int phpdbg_create_listenable_socket(const char *addr, unsigned short port, struct addrinfo *addr_res) { + int sock = -1, rc; + int reuse = 1; + struct in6_addr serveraddr; + struct addrinfo hints, *res = NULL; + char port_buf[8]; + int8_t any_addr = *addr == '*'; + + do { + memset(&hints, 0, sizeof hints); + if (any_addr) { + hints.ai_flags = AI_PASSIVE; + } else { + hints.ai_flags = AI_NUMERICSERV; + } + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + rc = inet_pton(AF_INET, addr, &serveraddr); + if (1 == rc) { + hints.ai_family = AF_INET; + if (!any_addr) { + hints.ai_flags |= AI_NUMERICHOST; + } + } else { + rc = inet_pton(AF_INET6, addr, &serveraddr); + if (1 == rc) { + hints.ai_family = AF_INET6; + if (!any_addr) { + hints.ai_flags |= AI_NUMERICHOST; + } + } else { + /* XXX get host by name ??? */ + } + } + + snprintf(port_buf, 7, "%u", port); + if (!any_addr) { + rc = getaddrinfo(addr, port_buf, &hints, &res); + } else { + rc = getaddrinfo(NULL, port_buf, &hints, &res); + } + + if (0 != rc) { +#ifndef PHP_WIN32 + if (rc == EAI_SYSTEM) { + char buf[128]; + int wrote; + + wrote = snprintf(buf, 128, "Could not translate address '%s'", addr); + buf[wrote] = '\0'; + quiet_write(PHPDBG_G(io)[PHPDBG_STDERR].fd, buf, strlen(buf)); + + return sock; + } else { +#endif + char buf[256]; + int wrote; + + wrote = snprintf(buf, 256, "Host '%s' not found. %s", addr, estrdup(gai_strerror(rc))); + buf[wrote] = '\0'; + quiet_write(PHPDBG_G(io)[PHPDBG_STDERR].fd, buf, strlen(buf)); + + return sock; +#ifndef PHP_WIN32 + } +#endif + return sock; + } + + if((sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) { + char buf[128]; + int wrote; + + wrote = sprintf(buf, "Unable to create socket"); + buf[wrote] = '\0'; + quiet_write(PHPDBG_G(io)[PHPDBG_STDERR].fd, buf, strlen(buf)); + + return sock; + } + + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &reuse, sizeof(reuse)) == -1) { + phpdbg_close_socket(sock); + return sock; + } + + + } while (0); + + *addr_res = *res; + + return sock; +} + +PHPDBG_API void phpdbg_close_socket(int sock) { + if (socket >= 0) { +#ifdef _WIN32 + closesocket(sock); +#else + shutdown(sock, SHUT_RDWR); + close(sock); +#endif + } +} + diff --git a/sapi/apache/mod_php5.h b/sapi/phpdbg/phpdbg_io.h index 18d16f48d9..8bafc0c999 100644 --- a/sapi/apache/mod_php5.h +++ b/sapi/phpdbg/phpdbg_io.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -12,49 +12,30 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: Rasmus Lerdorf <rasmus@php.net> | + | Authors: Anatol Belski <ab@php.net> | +----------------------------------------------------------------------+ - */ -/* $Id$ */ +*/ -#ifndef MOD_PHP5_H -#define MOD_PHP5_H +#ifndef PHPDBG_IO_H +#define PHPDBG_IO_H -#if !defined(WIN32) && !defined(WINNT) -#ifndef MODULE_VAR_EXPORT -#define MODULE_VAR_EXPORT -#endif -#endif +#include "phpdbg.h" -typedef struct { - long engine; - long last_modified; - long xbithack; - long terminate_child; - zend_bool in_request; -} php_apache_info_struct; - -extern zend_module_entry apache_module_entry; - -#ifdef ZTS -extern int php_apache_info_id; -#define AP(v) TSRMG(php_apache_info_id, php_apache_info_struct *, v) -#else -extern php_apache_info_struct php_apache_info; -#define AP(v) (php_apache_info.v) +/* Older versions of glibc <= 2.3.0 and <= OS X 10.5 do not have this constant defined */ +#ifndef AI_NUMERICSERV +#define AI_NUMERICSERV 0 #endif -/* fix for gcc4 visibility patch */ -#ifndef PHP_WIN32 -# undef MODULE_VAR_EXPORT -# define MODULE_VAR_EXPORT PHPAPI -#endif +PHPDBG_API int phpdbg_consume_stdin_line(char *buf); -#endif /* MOD_PHP5_H */ +PHPDBG_API int phpdbg_consume_bytes(int sock, char *ptr, int len, int tmo); +PHPDBG_API int phpdbg_send_bytes(int sock, const char *ptr, int len); +PHPDBG_API int phpdbg_mixed_read(int sock, char *ptr, int len, int tmo); +PHPDBG_API int phpdbg_mixed_write(int sock, const char *ptr, int len); + +PHPDBG_API int phpdbg_create_listenable_socket(const char *addr, unsigned short port, struct addrinfo *res); +PHPDBG_API int phpdbg_open_socket(const char *interface, unsigned short port); +PHPDBG_API void phpdbg_close_socket(int sock); + +#endif /* PHPDBG_IO_H */ -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - */ diff --git a/sapi/phpdbg/phpdbg_lexer.c b/sapi/phpdbg/phpdbg_lexer.c index 3092dc396d..10af103fb0 100644 --- a/sapi/phpdbg/phpdbg_lexer.c +++ b/sapi/phpdbg/phpdbg_lexer.c @@ -1,5 +1,5 @@ -/* Generated by re2c 0.13.5 */ -#line 1 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" +/* Generated by re2c 0.14.3 */ +#line 1 "sapi/phpdbg/phpdbg_lexer.l" /* * phpdbg_lexer.l */ @@ -16,6 +16,7 @@ #define YYGETCONDITION() LEX(state) #define YYCURSOR LEX(cursor) #define YYMARKER LEX(marker) +#define YYCTXMARKER LEX(ctxmarker) #define yyleng LEX(len) #define yytext ((char*) LEX(text)) #undef YYDEBUG @@ -23,12 +24,13 @@ #define YYFILL(n) #define NORMAL 0 -#define RAW 1 -#define INITIAL 2 +#define PRE_RAW 1 +#define RAW 2 +#define INITIAL 3 -ZEND_EXTERN_MODULE_GLOBALS(phpdbg); +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) -void phpdbg_init_lexer (phpdbg_param_t *stack, char *input TSRMLS_DC) { +void phpdbg_init_lexer (phpdbg_param_t *stack, char *input) { PHPDBG_G(parser_stack) = stack; YYSETCONDITION(INITIAL); @@ -37,21 +39,43 @@ void phpdbg_init_lexer (phpdbg_param_t *stack, char *input TSRMLS_DC) { LEX(len) = strlen(input); } +static int unescape_string(char *s) { + switch (*s) { + case '\'': + case '\"': { + char start = *s; + size_t off = 1; + do { + if (s[off] == '\\') { + off++; + } + *s = s[off]; + } while ((++s)[off] != start); + return off + 1; + } + } + + return 0; +} + int phpdbg_lex (phpdbg_param_t* yylval) { - TSRMLS_FETCH(); /* Slow, but this is not a major problem here. TODO: Use TSRMLS_DC */ restart: LEX(text) = YYCURSOR; -#line 48 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" +#line 68 "sapi/phpdbg/phpdbg_lexer.c" { YYCTYPE yych; unsigned int yyaccept = 0; - if (YYGETCONDITION() < 1) { - goto yyc_NORMAL; + if (YYGETCONDITION() < 2) { + if (YYGETCONDITION() < 1) { + goto yyc_NORMAL; + } else { + goto yyc_PRE_RAW; + } } else { - if (YYGETCONDITION() < 2) { + if (YYGETCONDITION() < 3) { goto yyc_RAW; } else { goto yyc_INITIAL; @@ -62,7 +86,7 @@ yyc_INITIAL: { static const unsigned char yybm[] = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 128, 128, 0, 0, 128, 0, 0, + 0, 128, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, @@ -94,220 +118,217 @@ yyc_INITIAL: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; - - YYDEBUG(0, *YYCURSOR); + YYDEBUG(1, *YYCURSOR); YYFILL(4); yych = *YYCURSOR; - if (yych <= 'D') { - if (yych <= '\n') { - if (yych <= 0x00) goto yy6; - if (yych <= 0x08) goto yy11; - if (yych >= '\n') goto yy4; + if (yych <= '#') { + if (yych <= '\f') { + if (yych <= 0x08) { + if (yych <= 0x00) goto yy9; + goto yy14; + } else { + if (yych <= '\t') goto yy3; + if (yych <= '\n') goto yy9; + goto yy14; + } } else { - if (yych <= '\r') { - if (yych <= '\f') goto yy11; + if (yych <= 0x1F) { + if (yych >= 0x0E) goto yy14; } else { - if (yych != ' ') goto yy11; + if (yych <= ' ') goto yy5; + if (yych <= '"') goto yy14; + goto yy8; } } } else { - if (yych <= 'd') { - if (yych <= 'Q') { - if (yych <= 'E') goto yy7; - goto yy11; + if (yych <= 'S') { + if (yych <= 'E') { + if (yych <= 'D') goto yy14; + goto yy10; } else { - if (yych <= 'R') goto yy10; - if (yych <= 'S') goto yy8; + if (yych <= 'Q') goto yy14; + if (yych <= 'R') goto yy13; goto yy11; } } else { if (yych <= 'q') { - if (yych <= 'e') goto yy7; - goto yy11; + if (yych == 'e') goto yy10; + goto yy14; } else { - if (yych <= 'r') goto yy9; - if (yych <= 's') goto yy8; - goto yy11; + if (yych <= 'r') goto yy12; + if (yych <= 's') goto yy11; + goto yy14; } } } - YYDEBUG(2, *YYCURSOR); - ++YYCURSOR; - if ((yych = *YYCURSOR) <= '\f') { - if (yych <= 0x08) goto yy3; - if (yych <= '\n') goto yy26; - } else { - if (yych <= '\r') goto yy26; - if (yych == ' ') goto yy26; - } yy3: YYDEBUG(3, *YYCURSOR); + ++YYCURSOR; + if (yybm[0+(yych = *YYCURSOR)] & 128) { + goto yy5; + } +yy4: + YYDEBUG(4, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 161 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" +#line 206 "sapi/phpdbg/phpdbg_lexer.l" { YYSETCONDITION(NORMAL); YYCURSOR = LEX(text); goto restart; } -#line 154 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" -yy4: - YYDEBUG(4, *YYCURSOR); - ++YYCURSOR; - if ((yych = *YYCURSOR) <= '\f') { - if (yych <= 0x08) goto yy5; - if (yych <= '\n') goto yy26; - } else { - if (yych <= '\r') goto yy26; - if (yych == ' ') goto yy26; - } +#line 181 "sapi/phpdbg/phpdbg_lexer.c" yy5: YYDEBUG(5, *YYCURSOR); + ++YYCURSOR; + YYFILL(1); + yych = *YYCURSOR; + YYDEBUG(6, *YYCURSOR); + if (yybm[0+yych] & 128) { + goto yy5; + } + YYDEBUG(7, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 68 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" +#line 175 "sapi/phpdbg/phpdbg_lexer.l" { - return 0; + /* ignore whitespace */ + + goto restart; } -#line 172 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" -yy6: - YYDEBUG(6, *YYCURSOR); - yych = *++YYCURSOR; - goto yy3; -yy7: - YYDEBUG(7, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'V') goto yy22; - if (yych == 'v') goto yy22; - goto yy3; +#line 199 "sapi/phpdbg/phpdbg_lexer.c" yy8: YYDEBUG(8, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'H') goto yy18; - if (yych == 'h') goto yy18; - goto yy3; + yych = *++YYCURSOR; + goto yy4; yy9: YYDEBUG(9, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yybm[0+yych] & 128) { - goto yy15; - } - if (yych == 'U') goto yy12; - if (yych == 'u') goto yy12; - goto yy3; + yych = *++YYCURSOR; + goto yy4; yy10: YYDEBUG(10, *YYCURSOR); yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'U') goto yy12; - if (yych == 'u') goto yy12; - goto yy3; + if (yych == 'V') goto yy25; + if (yych == 'v') goto yy25; + goto yy4; yy11: YYDEBUG(11, *YYCURSOR); - yych = *++YYCURSOR; - goto yy3; + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if (yych == 'H') goto yy21; + if (yych == 'h') goto yy21; + goto yy4; yy12: YYDEBUG(12, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'N') goto yy14; - if (yych == 'n') goto yy14; + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= 0x1F) { + if (yych <= '\t') { + if (yych <= 0x08) goto yy4; + goto yy18; + } else { + if (yych == '\r') goto yy18; + goto yy4; + } + } else { + if (yych <= 'U') { + if (yych <= ' ') goto yy18; + if (yych <= 'T') goto yy4; + goto yy15; + } else { + if (yych == 'u') goto yy15; + goto yy4; + } + } yy13: YYDEBUG(13, *YYCURSOR); - YYCURSOR = YYMARKER; - goto yy3; + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if (yych == 'U') goto yy15; + if (yych == 'u') goto yy15; + goto yy4; yy14: YYDEBUG(14, *YYCURSOR); yych = *++YYCURSOR; - if (yybm[0+yych] & 128) { - goto yy15; - } - goto yy13; + goto yy4; yy15: YYDEBUG(15, *YYCURSOR); - ++YYCURSOR; - YYFILL(1); - yych = *YYCURSOR; + yych = *++YYCURSOR; + if (yych == 'N') goto yy17; + if (yych == 'n') goto yy17; +yy16: YYDEBUG(16, *YYCURSOR); - if (yybm[0+yych] & 128) { - goto yy15; - } + YYCURSOR = YYMARKER; + goto yy4; +yy17: YYDEBUG(17, *YYCURSOR); - yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 155 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" - { - YYSETCONDITION(RAW); - phpdbg_init_param(yylval, EMPTY_PARAM); - return T_RUN; -} -#line 245 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" -yy18: - YYDEBUG(18, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '\f') { - if (yych <= 0x08) goto yy13; - if (yych >= '\v') goto yy13; + if (yych != '\t') goto yy16; } else { - if (yych <= '\r') goto yy19; - if (yych != ' ') goto yy13; + if (yych <= '\r') goto yy18; + if (yych != ' ') goto yy16; } -yy19: - YYDEBUG(19, *YYCURSOR); +yy18: + YYDEBUG(18, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(20, *YYCURSOR); + YYDEBUG(19, *YYCURSOR); if (yych <= '\f') { - if (yych <= 0x08) goto yy21; - if (yych <= '\n') goto yy19; + if (yych == '\t') goto yy18; } else { - if (yych <= '\r') goto yy19; - if (yych == ' ') goto yy19; + if (yych <= '\r') goto yy18; + if (yych == ' ') goto yy18; } -yy21: - YYDEBUG(21, *YYCURSOR); + YYDEBUG(20, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 150 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" +#line 193 "sapi/phpdbg/phpdbg_lexer.l" { - YYSETCONDITION(RAW); + YYSETCONDITION(PRE_RAW); phpdbg_init_param(yylval, EMPTY_PARAM); - return T_SHELL; + return T_RUN; } -#line 278 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" -yy22: - YYDEBUG(22, *YYCURSOR); +#line 293 "sapi/phpdbg/phpdbg_lexer.c" +yy21: + YYDEBUG(21, *YYCURSOR); yych = *++YYCURSOR; if (yych <= '\f') { - if (yych <= 0x08) goto yy13; - if (yych >= '\v') goto yy13; + if (yych != '\t') goto yy16; } else { - if (yych <= '\r') goto yy23; - if (yych != ' ') goto yy13; + if (yych <= '\r') goto yy22; + if (yych != ' ') goto yy16; } -yy23: - YYDEBUG(23, *YYCURSOR); +yy22: + YYDEBUG(22, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(24, *YYCURSOR); + YYDEBUG(23, *YYCURSOR); if (yych <= '\f') { - if (yych <= 0x08) goto yy25; - if (yych <= '\n') goto yy23; + if (yych == '\t') goto yy22; } else { - if (yych <= '\r') goto yy23; - if (yych == ' ') goto yy23; + if (yych <= '\r') goto yy22; + if (yych == ' ') goto yy22; } -yy25: - YYDEBUG(25, *YYCURSOR); + YYDEBUG(24, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 145 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" +#line 187 "sapi/phpdbg/phpdbg_lexer.l" { - YYSETCONDITION(RAW); + YYSETCONDITION(PRE_RAW); phpdbg_init_param(yylval, EMPTY_PARAM); - return T_EVAL; + return T_SHELL; } -#line 311 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" +#line 323 "sapi/phpdbg/phpdbg_lexer.c" +yy25: + YYDEBUG(25, *YYCURSOR); + yych = *++YYCURSOR; + if (yych <= '\f') { + if (yych != '\t') goto yy16; + } else { + if (yych <= '\r') goto yy26; + if (yych != ' ') goto yy16; + } yy26: YYDEBUG(26, *YYCURSOR); ++YYCURSOR; @@ -315,72 +336,107 @@ yy26: yych = *YYCURSOR; YYDEBUG(27, *YYCURSOR); if (yych <= '\f') { - if (yych <= 0x08) goto yy28; - if (yych <= '\n') goto yy26; + if (yych == '\t') goto yy26; } else { if (yych <= '\r') goto yy26; if (yych == ' ') goto yy26; } -yy28: YYDEBUG(28, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 139 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" +#line 181 "sapi/phpdbg/phpdbg_lexer.l" { - /* ignore whitespace */ - - goto restart; + YYSETCONDITION(PRE_RAW); + phpdbg_init_param(yylval, EMPTY_PARAM); + return T_EVAL; } -#line 334 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" +#line 353 "sapi/phpdbg/phpdbg_lexer.c" } /* *********************************** */ yyc_NORMAL: { static const unsigned char yybm[] = { - 0, 16, 16, 16, 16, 16, 16, 16, - 16, 8, 8, 16, 16, 8, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 8, 16, 16, 0, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 48, 16, - 176, 176, 176, 176, 176, 176, 176, 176, - 176, 176, 0, 16, 16, 16, 16, 16, - 16, 208, 208, 208, 208, 208, 208, 80, - 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 16, 16, 16, 16, 16, - 16, 208, 208, 208, 208, 208, 208, 80, - 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, + /* table 1 .. 8: 0 */ + 0, 242, 242, 242, 242, 242, 242, 242, + 242, 160, 0, 242, 242, 160, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 160, 242, 50, 160, 242, 242, 242, 194, + 242, 242, 242, 242, 242, 242, 243, 242, + 251, 251, 251, 251, 251, 251, 251, 251, + 251, 251, 160, 242, 242, 242, 242, 242, + 242, 254, 254, 254, 254, 254, 254, 246, + 246, 246, 246, 246, 246, 246, 246, 246, + 246, 246, 246, 246, 246, 246, 246, 246, + 246, 246, 246, 242, 2, 242, 242, 242, + 242, 254, 254, 254, 254, 254, 254, 246, + 246, 246, 246, 246, 246, 246, 246, 246, + 246, 246, 246, 246, 246, 246, 246, 246, + 246, 246, 246, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, + /* table 9 .. 10: 256 */ + 0, 128, 128, 128, 128, 128, 128, 128, + 128, 64, 0, 128, 128, 64, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 64, 128, 0, 0, 128, 128, 128, 0, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 0, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, }; YYDEBUG(29, *YYCURSOR); YYFILL(11); yych = *YYCURSOR; + if (yybm[256+yych] & 64) { + goto yy31; + } YYDEBUG(-1, yych); switch (yych) { - case 0x00: goto yy36; + case 0x00: case '\t': - case '\r': - case ' ': goto yy31; - case '\n': goto yy34; - case '#': goto yy55; - case '-': goto yy41; + case '\n': goto yy36; + case '"': goto yy44; + case '#': goto yy34; + case '\'': goto yy46; + case '-': goto yy38; case '.': case '1': case '2': @@ -390,28 +446,28 @@ yyc_NORMAL: case '6': case '7': case '8': - case '9': goto yy42; - case '0': goto yy45; - case ':': goto yy57; + case '9': goto yy47; + case '0': goto yy50; + case ':': goto yy41; case 'D': - case 'd': goto yy46; + case 'd': goto yy51; case 'E': - case 'e': goto yy47; + case 'e': goto yy52; case 'F': - case 'f': goto yy48; + case 'f': goto yy53; case 'I': - case 'i': goto yy37; + case 'i': goto yy40; case 'N': - case 'n': goto yy49; + case 'n': goto yy54; case 'O': - case 'o': goto yy50; + case 'o': goto yy55; case 'T': - case 't': goto yy51; + case 't': goto yy56; case 'Y': - case 'y': goto yy52; - case 'Z': goto yy53; - case 'z': goto yy54; - default: goto yy39; + case 'y': goto yy57; + case 'Z': goto yy58; + case 'z': goto yy59; + default: goto yy42; } yy31: YYDEBUG(31, *YYCURSOR); @@ -419,725 +475,1370 @@ yy31: YYFILL(1); yych = *YYCURSOR; YYDEBUG(32, *YYCURSOR); - if (yybm[0+yych] & 8) { + if (yybm[256+yych] & 64) { goto yy31; } YYDEBUG(33, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 139 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" +#line 175 "sapi/phpdbg/phpdbg_lexer.l" { /* ignore whitespace */ goto restart; } -#line 434 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" +#line 490 "sapi/phpdbg/phpdbg_lexer.c" yy34: YYDEBUG(34, *YYCURSOR); - ++YYCURSOR; - if (yybm[0+(yych = *YYCURSOR)] & 8) { - goto yy31; + YYCTXMARKER = YYCURSOR + 1; + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= '.') { + if (yych <= ',') goto yy35; + if (yych <= '-') goto yy146; + goto yy147; + } else { + if (yych <= '/') goto yy35; + if (yych <= '9') goto yy147; } yy35: YYDEBUG(35, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 68 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" +#line 110 "sapi/phpdbg/phpdbg_lexer.l" { - return 0; + YYSETCONDITION(INITIAL); + return T_SEPARATOR; } -#line 448 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" +#line 512 "sapi/phpdbg/phpdbg_lexer.c" yy36: YYDEBUG(36, *YYCURSOR); - yych = *++YYCURSOR; - goto yy35; -yy37: + ++YYCURSOR; YYDEBUG(37, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'F') goto yy106; - if (yych == 'f') goto yy106; - goto yy40; + yyleng = (size_t) YYCURSOR - (size_t) yytext; +#line 89 "sapi/phpdbg/phpdbg_lexer.l" + { + return 0; +} +#line 522 "sapi/phpdbg/phpdbg_lexer.c" yy38: YYDEBUG(38, *YYCURSOR); + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yybm[0+yych] & 1) { + goto yy47; + } + if (yych == 'r') goto yy136; + goto yy43; +yy39: + YYDEBUG(39, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 125 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" +#line 161 "sapi/phpdbg/phpdbg_lexer.l" { phpdbg_init_param(yylval, STR_PARAM); - yylval->str = zend_strndup(yytext, yyleng); + yylval->str = estrndup(yytext, yyleng - unescape_string(yytext)); yylval->len = yyleng; - return T_ID; + return T_ID; } -#line 470 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" -yy39: - YYDEBUG(39, *YYCURSOR); - yyaccept = 0; - YYMARKER = ++YYCURSOR; - YYFILL(3); - yych = *YYCURSOR; +#line 542 "sapi/phpdbg/phpdbg_lexer.c" yy40: YYDEBUG(40, *YYCURSOR); - if (yybm[0+yych] & 16) { - goto yy39; - } - if (yych <= '9') goto yy38; - goto yy62; + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yych == 'F') goto yy132; + if (yych == 'f') goto yy132; + goto yy43; yy41: YYDEBUG(41, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yybm[0+yych] & 32) { - goto yy42; - } - goto yy40; + YYCTXMARKER = YYCURSOR + 1; + yych = *++YYCURSOR; + if (yych == ':') goto yy130; + if (yych == '\\') goto yy68; + goto yy128; yy42: YYDEBUG(42, *YYCURSOR); yyaccept = 1; YYMARKER = ++YYCURSOR; YYFILL(3); yych = *YYCURSOR; +yy43: YYDEBUG(43, *YYCURSOR); - if (yybm[0+yych] & 32) { + if (yybm[256+yych] & 128) { goto yy42; } - if (yych <= 0x1F) { - if (yych <= '\n') { - if (yych <= 0x00) goto yy44; - if (yych <= 0x08) goto yy39; - } else { - if (yych != '\r') goto yy39; - } - } else { - if (yych <= '#') { - if (yych <= ' ') goto yy44; - if (yych <= '"') goto yy39; - } else { - if (yych == ':') goto yy62; - goto yy39; - } - } + if (yych <= ' ') goto yy39; + if (yych == '#') goto yy39; + if (yych <= '\'') goto yy62; + goto yy61; yy44: YYDEBUG(44, *YYCURSOR); - yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 106 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" - { - phpdbg_init_param(yylval, NUMERIC_PARAM); - yylval->num = atoi(yytext); - return T_DIGITS; -} -#line 527 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" + yych = *++YYCURSOR; + if (yych == '"') goto yy62; + goto yy120; yy45: YYDEBUG(45, *YYCURSOR); - yyaccept = 1; - yych = *(YYMARKER = ++YYCURSOR); - if (yybm[0+yych] & 32) { - goto yy42; - } - if (yych <= 0x1F) { - if (yych <= '\n') { - if (yych <= 0x00) goto yy44; - if (yych <= 0x08) goto yy40; - goto yy44; + YYCURSOR = YYMARKER; + if (yyaccept <= 3) { + if (yyaccept <= 1) { + if (yyaccept == 0) { + goto yy35; + } else { + goto yy39; + } } else { - if (yych == '\r') goto yy44; - goto yy40; + if (yyaccept == 2) { + goto yy49; + } else { + goto yy76; + } } } else { - if (yych <= '#') { - if (yych <= ' ') goto yy44; - if (yych <= '"') goto yy40; - goto yy44; + if (yyaccept <= 5) { + if (yyaccept == 4) { + goto yy107; + } else { + goto yy67; + } } else { - if (yych == 'x') goto yy102; - goto yy40; + goto yy142; } } yy46: YYDEBUG(46, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'I') goto yy96; - if (yych == 'i') goto yy96; - goto yy40; + yych = *++YYCURSOR; + if (yych == '\'') goto yy62; + goto yy109; yy47: YYDEBUG(47, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'N') goto yy91; - if (yych == 'n') goto yy91; - goto yy40; -yy48: + yyaccept = 2; + YYMARKER = ++YYCURSOR; + YYFILL(3); + yych = *YYCURSOR; YYDEBUG(48, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'A') goto yy88; - if (yych == 'a') goto yy88; - goto yy40; + if (yybm[0+yych] & 1) { + goto yy47; + } + if (yych <= ' ') { + if (yych <= '\n') { + if (yych <= 0x00) goto yy49; + if (yych <= 0x08) goto yy42; + } else { + if (yych == '\r') goto yy49; + if (yych <= 0x1F) goto yy42; + } + } else { + if (yych <= '&') { + if (yych <= '!') goto yy42; + if (yych <= '"') goto yy62; + if (yych >= '$') goto yy42; + } else { + if (yych <= '\'') goto yy62; + if (yych <= '/') goto yy42; + if (yych <= ':') goto yy61; + goto yy42; + } + } yy49: YYDEBUG(49, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'O') goto yy84; - if (yych == 'o') goto yy84; - goto yy40; + yyleng = (size_t) YYCURSOR - (size_t) yytext; +#line 142 "sapi/phpdbg/phpdbg_lexer.l" + { + phpdbg_init_param(yylval, NUMERIC_PARAM); + yylval->num = atoi(yytext); + return T_DIGITS; +} +#line 649 "sapi/phpdbg/phpdbg_lexer.c" yy50: YYDEBUG(50, *YYCURSOR); - yyaccept = 0; + yyaccept = 2; yych = *(YYMARKER = ++YYCURSOR); - if (yych <= 'N') { - if (yych == 'F') goto yy83; - if (yych <= 'M') goto yy40; - goto yy77; + if (yybm[0+yych] & 1) { + goto yy47; + } + if (yych <= 0x1F) { + if (yych <= '\n') { + if (yych <= 0x00) goto yy49; + if (yych <= 0x08) goto yy43; + goto yy49; + } else { + if (yych == '\r') goto yy49; + goto yy43; + } } else { - if (yych <= 'f') { - if (yych <= 'e') goto yy40; - goto yy83; + if (yych <= '#') { + if (yych <= ' ') goto yy49; + if (yych <= '"') goto yy43; + goto yy49; } else { - if (yych == 'n') goto yy77; - goto yy40; + if (yych == 'x') goto yy104; + goto yy43; } } yy51: YYDEBUG(51, *YYCURSOR); - yyaccept = 0; + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'R') goto yy81; - if (yych == 'r') goto yy81; - goto yy40; + if (yych == 'I') goto yy98; + if (yych == 'i') goto yy98; + goto yy43; yy52: YYDEBUG(52, *YYCURSOR); - yyaccept = 0; + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'E') goto yy76; - if (yych == 'e') goto yy76; - goto yy40; + if (yych == 'N') goto yy93; + if (yych == 'n') goto yy93; + goto yy43; yy53: YYDEBUG(53, *YYCURSOR); - yyaccept = 0; + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'E') goto yy73; - goto yy40; + if (yych == 'A') goto yy90; + if (yych == 'a') goto yy90; + goto yy43; yy54: YYDEBUG(54, *YYCURSOR); - yyaccept = 0; + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'e') goto yy61; - goto yy40; + if (yych == 'O') goto yy87; + if (yych == 'o') goto yy87; + goto yy43; yy55: YYDEBUG(55, *YYCURSOR); - ++YYCURSOR; + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= 'N') { + if (yych == 'F') goto yy86; + if (yych <= 'M') goto yy43; + goto yy81; + } else { + if (yych <= 'f') { + if (yych <= 'e') goto yy43; + goto yy86; + } else { + if (yych == 'n') goto yy81; + goto yy43; + } + } +yy56: YYDEBUG(56, *YYCURSOR); - yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 84 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" - { - return T_POUND; -} -#line 634 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yych == 'R') goto yy84; + if (yych == 'r') goto yy84; + goto yy43; yy57: YYDEBUG(57, *YYCURSOR); - ++YYCURSOR; - if ((yych = *YYCURSOR) == ':') goto yy59; + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yych == 'E') goto yy80; + if (yych == 'e') goto yy80; + goto yy43; +yy58: YYDEBUG(58, *YYCURSOR); - yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 90 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" - { - return T_COLON; -} -#line 645 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yych == 'E') goto yy77; + goto yy43; yy59: YYDEBUG(59, *YYCURSOR); - ++YYCURSOR; + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yych != 'e') goto yy43; YYDEBUG(60, *YYCURSOR); - yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 87 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" - { - return T_DCOLON; -} -#line 655 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yych == 'n') goto yy71; + goto yy43; yy61: YYDEBUG(61, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'n') goto yy67; - goto yy40; + yych = *++YYCURSOR; + if (yych == '/') goto yy65; + if (yych == '\\') goto yy68; + goto yy45; yy62: YYDEBUG(62, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == '/') goto yy64; + ++YYCURSOR; + YYFILL(3); + yych = *YYCURSOR; yy63: YYDEBUG(63, *YYCURSOR); - YYCURSOR = YYMARKER; - if (yyaccept <= 1) { - if (yyaccept <= 0) { - goto yy38; - } else { - goto yy44; - } - } else { - if (yyaccept <= 2) { - goto yy72; - } else { - goto yy105; - } + if (yybm[0+yych] & 2) { + goto yy62; } + if (yych <= '#') goto yy45; yy64: YYDEBUG(64, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '/') goto yy63; + if (yych != '/') goto yy45; +yy65: YYDEBUG(65, *YYCURSOR); - ++YYCURSOR; + yych = *++YYCURSOR; + if (yych != '/') goto yy45; YYDEBUG(66, *YYCURSOR); + ++YYCURSOR; +yy67: + YYDEBUG(67, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 78 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" +#line 123 "sapi/phpdbg/phpdbg_lexer.l" { phpdbg_init_param(yylval, STR_PARAM); - yylval->str = zend_strndup(yytext, yyleng); + yylval->str = estrndup(yytext, yyleng); yylval->len = yyleng; return T_PROTO; } -#line 697 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" -yy67: - YYDEBUG(67, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yych != 'd') goto yy40; +#line 788 "sapi/phpdbg/phpdbg_lexer.c" +yy68: YYDEBUG(68, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yych != '_') goto yy40; -yy69: + yyaccept = 1; + YYMARKER = ++YYCURSOR; + YYFILL(1); + yych = *YYCURSOR; YYDEBUG(69, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yybm[0+yych] & 64) { - goto yy70; + if (yych <= ' ') { + if (yych <= '\n') { + if (yych <= 0x00) goto yy39; + if (yych <= 0x08) goto yy68; + goto yy39; + } else { + if (yych == '\r') goto yy39; + if (yych <= 0x1F) goto yy68; + goto yy39; + } + } else { + if (yych <= '&') { + if (yych <= '!') goto yy68; + if (yych <= '#') goto yy39; + goto yy68; + } else { + if (yych <= '\'') goto yy39; + if (yych != ':') goto yy68; + } } - goto yy40; -yy70: YYDEBUG(70, *YYCURSOR); - yyaccept = 2; + ++YYCURSOR; + YYFILL(1); + yych = *YYCURSOR; + if (yych == '\\') goto yy68; + goto yy45; +yy71: + YYDEBUG(71, *YYCURSOR); + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yych != 'd') goto yy43; + YYDEBUG(72, *YYCURSOR); + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yych != '_') goto yy43; +yy73: + YYDEBUG(73, *YYCURSOR); + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yybm[0+yych] & 4) { + goto yy74; + } + goto yy43; +yy74: + YYDEBUG(74, *YYCURSOR); + yyaccept = 3; YYMARKER = ++YYCURSOR; YYFILL(3); yych = *YYCURSOR; - YYDEBUG(71, *YYCURSOR); - if (yybm[0+yych] & 64) { - goto yy70; + YYDEBUG(75, *YYCURSOR); + if (yybm[0+yych] & 4) { + goto yy74; } - if (yych <= 0x1F) { + if (yych <= ' ') { if (yych <= '\n') { - if (yych <= 0x00) goto yy72; - if (yych <= 0x08) goto yy39; + if (yych <= 0x00) goto yy76; + if (yych <= 0x08) goto yy42; } else { - if (yych != '\r') goto yy39; + if (yych == '\r') goto yy76; + if (yych <= 0x1F) goto yy42; } } else { - if (yych <= '#') { - if (yych <= ' ') goto yy72; - if (yych <= '"') goto yy39; + if (yych <= '&') { + if (yych <= '!') goto yy42; + if (yych <= '"') goto yy62; + if (yych >= '$') goto yy42; } else { - if (yych == ':') goto yy62; - goto yy39; + if (yych <= '\'') goto yy62; + if (yych == ':') goto yy61; + goto yy42; } } -yy72: - YYDEBUG(72, *YYCURSOR); +yy76: + YYDEBUG(76, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 118 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" +#line 154 "sapi/phpdbg/phpdbg_lexer.l" { phpdbg_init_param(yylval, OP_PARAM); - yylval->str = zend_strndup(yytext, yyleng); + yylval->str = estrndup(yytext, yyleng); yylval->len = yyleng; return T_OPCODE; } -#line 751 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" -yy73: - YYDEBUG(73, *YYCURSOR); - yyaccept = 0; +#line 878 "sapi/phpdbg/phpdbg_lexer.c" +yy77: + YYDEBUG(77, *YYCURSOR); + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych != 'N') goto yy40; - YYDEBUG(74, *YYCURSOR); - yyaccept = 0; + if (yych != 'N') goto yy43; + YYDEBUG(78, *YYCURSOR); + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych != 'D') goto yy40; - YYDEBUG(75, *YYCURSOR); - yyaccept = 0; + if (yych != 'D') goto yy43; + YYDEBUG(79, *YYCURSOR); + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych == '_') goto yy69; - goto yy40; -yy76: - YYDEBUG(76, *YYCURSOR); - yyaccept = 0; + if (yych == '_') goto yy73; + goto yy43; +yy80: + YYDEBUG(80, *YYCURSOR); + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'S') goto yy77; - if (yych != 's') goto yy40; -yy77: - YYDEBUG(77, *YYCURSOR); - yyaccept = 0; + if (yych == 'S') goto yy81; + if (yych != 's') goto yy43; +yy81: + YYDEBUG(81, *YYCURSOR); + YYCTXMARKER = YYCURSOR + 1; + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); if (yych <= '\f') { - if (yych <= 0x08) goto yy40; - if (yych >= '\v') goto yy40; + if (yych <= 0x00) goto yy82; + if (yych <= 0x08) goto yy43; + if (yych >= '\v') goto yy43; } else { - if (yych <= '\r') goto yy78; - if (yych != ' ') goto yy40; + if (yych <= '\r') goto yy82; + if (yych != ' ') goto yy43; } -yy78: - YYDEBUG(78, *YYCURSOR); +yy82: + YYDEBUG(82, *YYCURSOR); ++YYCURSOR; - YYFILL(1); - yych = *YYCURSOR; - YYDEBUG(79, *YYCURSOR); - if (yych <= '\f') { - if (yych <= 0x08) goto yy80; - if (yych <= '\n') goto yy78; - } else { - if (yych <= '\r') goto yy78; - if (yych == ' ') goto yy78; - } -yy80: - YYDEBUG(80, *YYCURSOR); + YYDEBUG(83, *YYCURSOR); + YYCURSOR = YYCTXMARKER; yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 94 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" +#line 130 "sapi/phpdbg/phpdbg_lexer.l" { phpdbg_init_param(yylval, NUMERIC_PARAM); - yylval->num = 1; + yylval->num = 1; return T_TRUTHY; } -#line 805 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" -yy81: - YYDEBUG(81, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'U') goto yy82; - if (yych != 'u') goto yy40; -yy82: - YYDEBUG(82, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'E') goto yy77; - if (yych == 'e') goto yy77; - goto yy40; -yy83: - YYDEBUG(83, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'F') goto yy84; - if (yych != 'f') goto yy40; +#line 924 "sapi/phpdbg/phpdbg_lexer.c" yy84: YYDEBUG(84, *YYCURSOR); - yyaccept = 0; + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych <= '\f') { - if (yych <= 0x08) goto yy40; - if (yych >= '\v') goto yy40; - } else { - if (yych <= '\r') goto yy85; - if (yych != ' ') goto yy40; - } + if (yych == 'U') goto yy85; + if (yych != 'u') goto yy43; yy85: YYDEBUG(85, *YYCURSOR); - ++YYCURSOR; - YYFILL(1); - yych = *YYCURSOR; + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yych == 'E') goto yy81; + if (yych == 'e') goto yy81; + goto yy43; +yy86: YYDEBUG(86, *YYCURSOR); + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yych == 'F') goto yy87; + if (yych != 'f') goto yy43; +yy87: + YYDEBUG(87, *YYCURSOR); + YYCTXMARKER = YYCURSOR + 1; + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); if (yych <= '\f') { - if (yych <= 0x08) goto yy87; - if (yych <= '\n') goto yy85; + if (yych <= 0x00) goto yy88; + if (yych <= 0x08) goto yy43; + if (yych >= '\v') goto yy43; } else { - if (yych <= '\r') goto yy85; - if (yych == ' ') goto yy85; + if (yych <= '\r') goto yy88; + if (yych != ' ') goto yy43; } -yy87: - YYDEBUG(87, *YYCURSOR); +yy88: + YYDEBUG(88, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(89, *YYCURSOR); + YYCURSOR = YYCTXMARKER; yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 100 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" +#line 136 "sapi/phpdbg/phpdbg_lexer.l" { phpdbg_init_param(yylval, NUMERIC_PARAM); yylval->num = 0; return T_FALSY; } -#line 858 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" -yy88: - YYDEBUG(88, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'L') goto yy89; - if (yych != 'l') goto yy40; -yy89: - YYDEBUG(89, *YYCURSOR); - yyaccept = 0; - yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'S') goto yy90; - if (yych != 's') goto yy40; +#line 969 "sapi/phpdbg/phpdbg_lexer.c" yy90: YYDEBUG(90, *YYCURSOR); - yyaccept = 0; + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'E') goto yy84; - if (yych == 'e') goto yy84; - goto yy40; + if (yych == 'L') goto yy91; + if (yych != 'l') goto yy43; yy91: YYDEBUG(91, *YYCURSOR); - yyaccept = 0; + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'A') goto yy92; - if (yych != 'a') goto yy40; + if (yych == 'S') goto yy92; + if (yych != 's') goto yy43; yy92: YYDEBUG(92, *YYCURSOR); - yyaccept = 0; + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'B') goto yy93; - if (yych != 'b') goto yy40; + if (yych == 'E') goto yy87; + if (yych == 'e') goto yy87; + goto yy43; yy93: YYDEBUG(93, *YYCURSOR); - yyaccept = 0; + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'L') goto yy94; - if (yych != 'l') goto yy40; + if (yych == 'A') goto yy94; + if (yych != 'a') goto yy43; yy94: YYDEBUG(94, *YYCURSOR); - yyaccept = 0; + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'E') goto yy95; - if (yych != 'e') goto yy40; + if (yych == 'B') goto yy95; + if (yych != 'b') goto yy43; yy95: YYDEBUG(95, *YYCURSOR); - yyaccept = 0; + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'D') goto yy77; - if (yych == 'd') goto yy77; - goto yy40; + if (yych == 'L') goto yy96; + if (yych != 'l') goto yy43; yy96: YYDEBUG(96, *YYCURSOR); - yyaccept = 0; + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'S') goto yy97; - if (yych != 's') goto yy40; + if (yych == 'E') goto yy97; + if (yych != 'e') goto yy43; yy97: YYDEBUG(97, *YYCURSOR); - yyaccept = 0; + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'A') goto yy98; - if (yych != 'a') goto yy40; + if (yych == 'D') goto yy81; + if (yych == 'd') goto yy81; + goto yy43; yy98: YYDEBUG(98, *YYCURSOR); - yyaccept = 0; + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'B') goto yy99; - if (yych != 'b') goto yy40; + if (yych == 'S') goto yy99; + if (yych != 's') goto yy43; yy99: YYDEBUG(99, *YYCURSOR); - yyaccept = 0; + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'L') goto yy100; - if (yych != 'l') goto yy40; + if (yych == 'A') goto yy100; + if (yych != 'a') goto yy43; yy100: YYDEBUG(100, *YYCURSOR); - yyaccept = 0; + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'E') goto yy101; - if (yych != 'e') goto yy40; + if (yych == 'B') goto yy101; + if (yych != 'b') goto yy43; yy101: YYDEBUG(101, *YYCURSOR); - yyaccept = 0; + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yych == 'D') goto yy84; - if (yych == 'd') goto yy84; - goto yy40; + if (yych == 'L') goto yy102; + if (yych != 'l') goto yy43; yy102: YYDEBUG(102, *YYCURSOR); - yyaccept = 0; + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); - if (yybm[0+yych] & 128) { - goto yy103; - } - goto yy40; + if (yych == 'E') goto yy103; + if (yych != 'e') goto yy43; yy103: YYDEBUG(103, *YYCURSOR); - yyaccept = 3; + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yych == 'D') goto yy87; + if (yych == 'd') goto yy87; + goto yy43; +yy104: + YYDEBUG(104, *YYCURSOR); + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yybm[0+yych] & 8) { + goto yy105; + } + goto yy43; +yy105: + YYDEBUG(105, *YYCURSOR); + yyaccept = 4; YYMARKER = ++YYCURSOR; YYFILL(3); yych = *YYCURSOR; - YYDEBUG(104, *YYCURSOR); - if (yybm[0+yych] & 128) { - goto yy103; + YYDEBUG(106, *YYCURSOR); + if (yybm[0+yych] & 8) { + goto yy105; } - if (yych <= 0x1F) { + if (yych <= ' ') { if (yych <= '\n') { - if (yych <= 0x00) goto yy105; - if (yych <= 0x08) goto yy39; + if (yych <= 0x00) goto yy107; + if (yych <= 0x08) goto yy42; } else { - if (yych != '\r') goto yy39; + if (yych == '\r') goto yy107; + if (yych <= 0x1F) goto yy42; } } else { - if (yych <= '#') { - if (yych <= ' ') goto yy105; - if (yych <= '"') goto yy39; + if (yych <= '&') { + if (yych <= '!') goto yy42; + if (yych <= '"') goto yy62; + if (yych >= '$') goto yy42; } else { - if (yych == ':') goto yy62; - goto yy39; + if (yych <= '\'') goto yy62; + if (yych <= '/') goto yy42; + if (yych <= ':') goto yy61; + goto yy42; } } -yy105: - YYDEBUG(105, *YYCURSOR); +yy107: + YYDEBUG(107, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 112 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" +#line 148 "sapi/phpdbg/phpdbg_lexer.l" { phpdbg_init_param(yylval, ADDR_PARAM); yylval->addr = strtoul(yytext, 0, 16); return T_ADDR; } -#line 989 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" -yy106: - YYDEBUG(106, *YYCURSOR); - yyaccept = 0; +#line 1104 "sapi/phpdbg/phpdbg_lexer.c" +yy108: + YYDEBUG(108, *YYCURSOR); + ++YYCURSOR; + YYFILL(4); + yych = *YYCURSOR; +yy109: + YYDEBUG(109, *YYCURSOR); + if (yybm[0+yych] & 16) { + goto yy108; + } + if (yych <= '\n') { + if (yych <= 0x00) goto yy45; + if (yych >= '\n') goto yy45; + } else { + if (yych <= '#') goto yy110; + if (yych <= '\'') goto yy118; + if (yych <= ':') goto yy112; + goto yy113; + } +yy110: + YYDEBUG(110, *YYCURSOR); + ++YYCURSOR; + YYFILL(1); + yych = *YYCURSOR; +yy111: + YYDEBUG(111, *YYCURSOR); + if (yybm[0+yych] & 32) { + goto yy110; + } + if (yych <= '\n') goto yy45; + if (yych <= '\'') goto yy115; + goto yy116; +yy112: + YYDEBUG(112, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == '/') goto yy114; + goto yy111; +yy113: + YYDEBUG(113, *YYCURSOR); + ++YYCURSOR; + YYFILL(3); + yych = *YYCURSOR; + if (yych <= '"') { + if (yych <= '\f') { + if (yych <= 0x00) goto yy45; + if (yych <= 0x08) goto yy62; + if (yych <= '\n') goto yy45; + goto yy62; + } else { + if (yych <= '\r') goto yy45; + if (yych == ' ') goto yy45; + goto yy62; + } + } else { + if (yych <= '9') { + if (yych <= '#') goto yy45; + if (yych == '\'') goto yy108; + goto yy62; + } else { + if (yych <= ':') goto yy64; + if (yych == '\\') goto yy108; + goto yy62; + } + } +yy114: + YYDEBUG(114, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == '/') goto yy117; + goto yy111; +yy115: + YYDEBUG(115, *YYCURSOR); + yych = *++YYCURSOR; + goto yy39; +yy116: + YYDEBUG(116, *YYCURSOR); + ++YYCURSOR; + YYFILL(1); + yych = *YYCURSOR; + if (yych == '\'') goto yy110; + if (yych == '\\') goto yy110; + goto yy45; +yy117: + YYDEBUG(117, *YYCURSOR); + yyaccept = 5; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= 0x00) goto yy67; + if (yych == '\n') goto yy67; + goto yy111; +yy118: + YYDEBUG(118, *YYCURSOR); + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= '\r') { + if (yych <= 0x08) { + if (yych <= 0x00) goto yy39; + goto yy63; + } else { + if (yych <= '\n') goto yy39; + if (yych <= '\f') goto yy63; + goto yy39; + } + } else { + if (yych <= ' ') { + if (yych <= 0x1F) goto yy63; + goto yy39; + } else { + if (yych == '#') goto yy39; + goto yy63; + } + } +yy119: + YYDEBUG(119, *YYCURSOR); + ++YYCURSOR; + YYFILL(4); + yych = *YYCURSOR; +yy120: + YYDEBUG(120, *YYCURSOR); + if (yybm[0+yych] & 64) { + goto yy119; + } + if (yych <= ' ') { + if (yych <= 0x00) goto yy45; + if (yych == '\n') goto yy45; + } else { + if (yych <= '"') goto yy118; + if (yych <= '#') goto yy121; + if (yych <= ':') goto yy123; + goto yy124; + } +yy121: + YYDEBUG(121, *YYCURSOR); + ++YYCURSOR; + YYFILL(1); + yych = *YYCURSOR; +yy122: + YYDEBUG(122, *YYCURSOR); + if (yybm[0+yych] & 128) { + goto yy121; + } + if (yych <= '\n') goto yy45; + if (yych <= '"') goto yy115; + goto yy126; +yy123: + YYDEBUG(123, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == '/') goto yy125; + goto yy122; +yy124: + YYDEBUG(124, *YYCURSOR); + ++YYCURSOR; + YYFILL(3); + yych = *YYCURSOR; + if (yych <= ' ') { + if (yych <= '\n') { + if (yych <= 0x00) goto yy45; + if (yych <= 0x08) goto yy62; + goto yy45; + } else { + if (yych == '\r') goto yy45; + if (yych <= 0x1F) goto yy62; + goto yy45; + } + } else { + if (yych <= '9') { + if (yych <= '!') goto yy62; + if (yych <= '"') goto yy119; + if (yych <= '#') goto yy45; + goto yy62; + } else { + if (yych <= ':') goto yy64; + if (yych == '\\') goto yy119; + goto yy62; + } + } +yy125: + YYDEBUG(125, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == '/') goto yy127; + goto yy122; +yy126: + YYDEBUG(126, *YYCURSOR); + ++YYCURSOR; + YYFILL(1); + yych = *YYCURSOR; + if (yych == '"') goto yy121; + if (yych == '\\') goto yy121; + goto yy45; +yy127: + YYDEBUG(127, *YYCURSOR); + yyaccept = 5; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= 0x00) goto yy67; + if (yych == '\n') goto yy67; + goto yy122; +yy128: + YYDEBUG(128, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(129, *YYCURSOR); + YYCURSOR = YYCTXMARKER; + yyleng = (size_t) YYCURSOR - (size_t) yytext; +#line 119 "sapi/phpdbg/phpdbg_lexer.l" + { + return T_COLON; +} +#line 1309 "sapi/phpdbg/phpdbg_lexer.c" +yy130: + YYDEBUG(130, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(131, *YYCURSOR); + yyleng = (size_t) YYCURSOR - (size_t) yytext; +#line 115 "sapi/phpdbg/phpdbg_lexer.l" + { + return T_DCOLON; +} +#line 1319 "sapi/phpdbg/phpdbg_lexer.c" +yy132: + YYDEBUG(132, *YYCURSOR); + yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); if (yych <= '\f') { - if (yych <= 0x08) goto yy40; - if (yych >= '\v') goto yy40; + if (yych != '\t') goto yy43; } else { - if (yych <= '\r') goto yy107; - if (yych != ' ') goto yy40; + if (yych <= '\r') goto yy133; + if (yych != ' ') goto yy43; } -yy107: - YYDEBUG(107, *YYCURSOR); +yy133: + YYDEBUG(133, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(108, *YYCURSOR); + YYDEBUG(134, *YYCURSOR); if (yych <= '\f') { - if (yych <= 0x08) goto yy109; - if (yych <= '\n') goto yy107; + if (yych == '\t') goto yy133; } else { - if (yych <= '\r') goto yy107; - if (yych == ' ') goto yy107; + if (yych <= '\r') goto yy133; + if (yych == ' ') goto yy133; } -yy109: - YYDEBUG(109, *YYCURSOR); + YYDEBUG(135, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 72 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" +#line 100 "sapi/phpdbg/phpdbg_lexer.l" { YYSETCONDITION(RAW); phpdbg_init_param(yylval, EMPTY_PARAM); return T_IF; } -#line 1023 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" +#line 1350 "sapi/phpdbg/phpdbg_lexer.c" +yy136: + YYDEBUG(136, *YYCURSOR); + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= ' ') { + if (yych <= '\f') { + if (yych != '\t') goto yy43; + } else { + if (yych <= '\r') goto yy137; + if (yych <= 0x1F) goto yy43; + } + } else { + if (yych <= '.') { + if (yych <= ',') goto yy43; + if (yych <= '-') goto yy139; + goto yy140; + } else { + if (yych <= '/') goto yy43; + if (yych <= '9') goto yy140; + goto yy43; + } + } +yy137: + YYDEBUG(137, *YYCURSOR); + ++YYCURSOR; + YYFILL(2); + yych = *YYCURSOR; + YYDEBUG(138, *YYCURSOR); + if (yych <= ' ') { + if (yych <= '\f') { + if (yych == '\t') goto yy137; + goto yy45; + } else { + if (yych <= '\r') goto yy137; + if (yych <= 0x1F) goto yy45; + goto yy137; + } + } else { + if (yych <= '.') { + if (yych <= ',') goto yy45; + if (yych <= '-') goto yy143; + goto yy144; + } else { + if (yych <= '/') goto yy45; + if (yych <= '9') goto yy144; + goto yy45; + } + } +yy139: + YYDEBUG(139, *YYCURSOR); + yyaccept = 1; + yych = *(YYMARKER = ++YYCURSOR); + if (yych == '.') goto yy140; + if (yych <= '/') goto yy43; + if (yych >= ':') goto yy43; +yy140: + YYDEBUG(140, *YYCURSOR); + yyaccept = 6; + YYMARKER = ++YYCURSOR; + YYFILL(3); + yych = *YYCURSOR; + YYDEBUG(141, *YYCURSOR); + if (yych <= '"') { + if (yych <= '\f') { + if (yych <= 0x00) goto yy142; + if (yych <= 0x08) goto yy42; + if (yych >= '\v') goto yy42; + } else { + if (yych <= 0x1F) { + if (yych >= 0x0E) goto yy42; + } else { + if (yych <= ' ') goto yy142; + if (yych <= '!') goto yy42; + goto yy62; + } + } + } else { + if (yych <= '-') { + if (yych <= '#') goto yy142; + if (yych == '\'') goto yy62; + goto yy42; + } else { + if (yych <= '/') { + if (yych <= '.') goto yy140; + goto yy42; + } else { + if (yych <= '9') goto yy140; + if (yych <= ':') goto yy61; + goto yy42; + } + } + } +yy142: + YYDEBUG(142, *YYCURSOR); + yyleng = (size_t) YYCURSOR - (size_t) yytext; +#line 93 "sapi/phpdbg/phpdbg_lexer.l" + { + char *text = yytext + 2; + while (*++text < '0'); + yylval->num = atoi(text); + return T_REQ_ID; +} +#line 1453 "sapi/phpdbg/phpdbg_lexer.c" +yy143: + YYDEBUG(143, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == '.') goto yy144; + if (yych <= '/') goto yy45; + if (yych >= ':') goto yy45; +yy144: + YYDEBUG(144, *YYCURSOR); + ++YYCURSOR; + YYFILL(1); + yych = *YYCURSOR; + YYDEBUG(145, *YYCURSOR); + if (yych == '.') goto yy144; + if (yych <= '/') goto yy142; + if (yych <= '9') goto yy144; + goto yy142; +yy146: + YYDEBUG(146, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == '.') goto yy147; + if (yych <= '/') goto yy45; + if (yych >= ':') goto yy45; +yy147: + YYDEBUG(147, *YYCURSOR); + ++YYCURSOR; + YYFILL(1); + yych = *YYCURSOR; + YYDEBUG(148, *YYCURSOR); + if (yych == '.') goto yy147; + if (yych <= '/') goto yy149; + if (yych <= '9') goto yy147; +yy149: + YYDEBUG(149, *YYCURSOR); + YYCURSOR = YYCTXMARKER; + yyleng = (size_t) YYCURSOR - (size_t) yytext; +#line 106 "sapi/phpdbg/phpdbg_lexer.l" + { + return T_POUND; +} +#line 1493 "sapi/phpdbg/phpdbg_lexer.c" } /* *********************************** */ -yyc_RAW: +yyc_PRE_RAW: { static const unsigned char yybm[] = { - 0, 64, 64, 64, 64, 64, 64, 64, - 64, 224, 128, 64, 64, 224, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 224, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 64, 64, 64, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 64, 0, 0, 0, 64, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 64, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 128, 0, + 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, }; - YYDEBUG(110, *YYCURSOR); + YYDEBUG(150, *YYCURSOR); YYFILL(2); yych = *YYCURSOR; - if (yybm[0+yych] & 32) { - goto yy112; + if (yych <= '\r') { + if (yych <= '\t') { + if (yych <= 0x00) goto yy158; + if (yych <= 0x08) goto yy160; + } else { + if (yych <= '\n') goto yy158; + if (yych <= '\f') goto yy160; + } + } else { + if (yych <= '"') { + if (yych == ' ') goto yy154; + goto yy160; + } else { + if (yych <= '#') goto yy157; + if (yych == '-') goto yy159; + goto yy160; + } } - if (yych <= 0x00) goto yy117; - if (yych == '\n') goto yy115; - goto yy118; -yy112: - YYDEBUG(112, *YYCURSOR); + YYDEBUG(152, *YYCURSOR); + ++YYCURSOR; + if (yybm[0+(yych = *YYCURSOR)] & 64) { + goto yy154; + } +yy153: + YYDEBUG(153, *YYCURSOR); + yyleng = (size_t) YYCURSOR - (size_t) yytext; +#line 199 "sapi/phpdbg/phpdbg_lexer.l" + { + YYSETCONDITION(RAW); + + YYCURSOR = LEX(text); + goto restart; +} +#line 1568 "sapi/phpdbg/phpdbg_lexer.c" +yy154: + YYDEBUG(154, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(113, *YYCURSOR); - if (yybm[0+yych] & 32) { - goto yy112; + YYDEBUG(155, *YYCURSOR); + if (yybm[0+yych] & 64) { + goto yy154; } - if (yych <= 0x00) goto yy114; - if (yych == '\n') goto yy120; - goto yy118; -yy114: - YYDEBUG(114, *YYCURSOR); + YYDEBUG(156, *YYCURSOR); + yyleng = (size_t) YYCURSOR - (size_t) yytext; +#line 175 "sapi/phpdbg/phpdbg_lexer.l" + { + /* ignore whitespace */ + + goto restart; +} +#line 1586 "sapi/phpdbg/phpdbg_lexer.c" +yy157: + YYDEBUG(157, *YYCURSOR); + yych = *++YYCURSOR; + goto yy153; +yy158: + YYDEBUG(158, *YYCURSOR); + yych = *++YYCURSOR; + goto yy153; +yy159: + YYDEBUG(159, *YYCURSOR); + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if (yych == 'r') goto yy161; + goto yy153; +yy160: + YYDEBUG(160, *YYCURSOR); + yych = *++YYCURSOR; + goto yy153; +yy161: + YYDEBUG(161, *YYCURSOR); + ++YYCURSOR; + YYFILL(2); + yych = *YYCURSOR; + YYDEBUG(162, *YYCURSOR); + if (yybm[0+yych] & 128) { + goto yy165; + } + if (yych <= '\r') { + if (yych == '\t') goto yy161; + if (yych >= '\r') goto yy161; + } else { + if (yych <= ' ') { + if (yych >= ' ') goto yy161; + } else { + if (yych == '-') goto yy164; + } + } +yy163: + YYDEBUG(163, *YYCURSOR); + YYCURSOR = YYMARKER; + goto yy153; +yy164: + YYDEBUG(164, *YYCURSOR); + yych = *++YYCURSOR; + if (yybm[0+yych] & 128) { + goto yy165; + } + goto yy163; +yy165: + YYDEBUG(165, *YYCURSOR); + ++YYCURSOR; + YYFILL(1); + yych = *YYCURSOR; + YYDEBUG(166, *YYCURSOR); + if (yybm[0+yych] & 128) { + goto yy165; + } + YYDEBUG(167, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 132 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" +#line 93 "sapi/phpdbg/phpdbg_lexer.l" + { + char *text = yytext + 2; + while (*++text < '0'); + yylval->num = atoi(text); + return T_REQ_ID; +} +#line 1653 "sapi/phpdbg/phpdbg_lexer.c" + } +/* *********************************** */ +yyc_RAW: + { + static const unsigned char yybm[] = { + 0, 224, 224, 224, 224, 224, 224, 224, + 224, 240, 0, 224, 224, 240, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 240, 224, 64, 192, 224, 224, 224, 128, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 32, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + 224, 224, 224, 224, 224, 224, 224, 224, + }; + YYDEBUG(168, *YYCURSOR); + YYFILL(1); + yych = *YYCURSOR; + if (yybm[0+yych] & 16) { + goto yy170; + } + if (yych <= '!') { + if (yych <= 0x00) goto yy175; + if (yych <= 0x08) goto yy177; + if (yych <= '\n') goto yy175; + goto yy177; + } else { + if (yych <= '#') { + if (yych <= '"') goto yy179; + goto yy173; + } else { + if (yych == '\'') goto yy181; + goto yy177; + } + } +yy170: + YYDEBUG(170, *YYCURSOR); + yyaccept = 0; + YYMARKER = ++YYCURSOR; + YYFILL(1); + yych = *YYCURSOR; + YYDEBUG(171, *YYCURSOR); + if (yybm[0+yych] & 16) { + goto yy170; + } + if (yych <= '!') { + if (yych <= 0x00) goto yy172; + if (yych <= 0x08) goto yy177; + if (yych >= '\v') goto yy177; + } else { + if (yych <= '#') { + if (yych <= '"') goto yy179; + } else { + if (yych == '\'') goto yy181; + goto yy177; + } + } +yy172: + YYDEBUG(172, *YYCURSOR); + yyleng = (size_t) YYCURSOR - (size_t) yytext; +#line 168 "sapi/phpdbg/phpdbg_lexer.l" { phpdbg_init_param(yylval, STR_PARAM); - yylval->str = zend_strndup(yytext, yyleng); + yylval->str = estrndup(yytext, yyleng - unescape_string(yytext)); yylval->len = yyleng; return T_INPUT; } -#line 1093 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" -yy115: - YYDEBUG(115, *YYCURSOR); +#line 1744 "sapi/phpdbg/phpdbg_lexer.c" +yy173: + YYDEBUG(173, *YYCURSOR); ++YYCURSOR; - if (yybm[0+(yych = *YYCURSOR)] & 128) { - goto yy120; - } -yy116: - YYDEBUG(116, *YYCURSOR); + YYDEBUG(174, *YYCURSOR); yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 68 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" +#line 110 "sapi/phpdbg/phpdbg_lexer.l" + { + YYSETCONDITION(INITIAL); + return T_SEPARATOR; +} +#line 1755 "sapi/phpdbg/phpdbg_lexer.c" +yy175: + YYDEBUG(175, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(176, *YYCURSOR); + yyleng = (size_t) YYCURSOR - (size_t) yytext; +#line 89 "sapi/phpdbg/phpdbg_lexer.l" { return 0; } -#line 1107 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" -yy117: - YYDEBUG(117, *YYCURSOR); - yych = *++YYCURSOR; - goto yy116; -yy118: - YYDEBUG(118, *YYCURSOR); +#line 1765 "sapi/phpdbg/phpdbg_lexer.c" +yy177: + YYDEBUG(177, *YYCURSOR); + yyaccept = 0; + YYMARKER = ++YYCURSOR; + YYFILL(1); + yych = *YYCURSOR; + YYDEBUG(178, *YYCURSOR); + if (yybm[0+yych] & 32) { + goto yy177; + } + if (yych <= '\n') goto yy172; + if (yych <= '"') goto yy179; + if (yych <= '#') goto yy172; + goto yy181; +yy179: + YYDEBUG(179, *YYCURSOR); + ++YYCURSOR; + YYFILL(1); + yych = *YYCURSOR; + if (yybm[0+yych] & 128) { + goto yy185; + } + if (yych >= '#') goto yy187; +yy180: + YYDEBUG(180, *YYCURSOR); + YYCURSOR = YYMARKER; + goto yy172; +yy181: + YYDEBUG(181, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(119, *YYCURSOR); if (yybm[0+yych] & 64) { - goto yy118; + goto yy182; } - goto yy114; -yy120: - YYDEBUG(120, *YYCURSOR); + if (yych <= '\'') goto yy180; + goto yy184; +yy182: + YYDEBUG(182, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(121, *YYCURSOR); + YYDEBUG(183, *YYCURSOR); + if (yybm[0+yych] & 64) { + goto yy182; + } + if (yych <= '\n') goto yy180; + if (yych <= '\'') goto yy177; +yy184: + YYDEBUG(184, *YYCURSOR); + ++YYCURSOR; + YYFILL(1); + yych = *YYCURSOR; + if (yych == '\'') goto yy182; + if (yych == '\\') goto yy182; + goto yy180; +yy185: + YYDEBUG(185, *YYCURSOR); + ++YYCURSOR; + YYFILL(1); + yych = *YYCURSOR; + YYDEBUG(186, *YYCURSOR); if (yybm[0+yych] & 128) { - goto yy120; + goto yy185; } - YYDEBUG(122, *YYCURSOR); - yyleng = (size_t) YYCURSOR - (size_t) yytext; -#line 139 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" - { - /* ignore whitespace */ - - goto restart; -} -#line 1139 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.c" + if (yych <= '\n') goto yy180; + if (yych <= '"') goto yy177; +yy187: + YYDEBUG(187, *YYCURSOR); + ++YYCURSOR; + YYFILL(1); + yych = *YYCURSOR; + if (yych == '"') goto yy185; + if (yych == '\\') goto yy185; + goto yy180; } } -#line 168 "/var/root/php-src/sapi/phpdbg/phpdbg_lexer.l" +#line 213 "sapi/phpdbg/phpdbg_lexer.l" } diff --git a/sapi/phpdbg/phpdbg_lexer.h b/sapi/phpdbg/phpdbg_lexer.h index c977243e69..355ce4ece0 100644 --- a/sapi/phpdbg/phpdbg_lexer.h +++ b/sapi/phpdbg/phpdbg_lexer.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -28,13 +28,14 @@ typedef struct { unsigned char *text; unsigned char *cursor; unsigned char *marker; + unsigned char *ctxmarker; int state; } phpdbg_lexer_data; #define yyparse phpdbg_parse #define yylex phpdbg_lex -void phpdbg_init_lexer (phpdbg_param_t *stack, char *input TSRMLS_DC); +void phpdbg_init_lexer (phpdbg_param_t *stack, char *input); int phpdbg_lex (phpdbg_param_t* yylval); diff --git a/sapi/phpdbg/phpdbg_lexer.l b/sapi/phpdbg/phpdbg_lexer.l index 7b3ce38c47..21c4569480 100644 --- a/sapi/phpdbg/phpdbg_lexer.l +++ b/sapi/phpdbg/phpdbg_lexer.l @@ -14,6 +14,7 @@ #define YYGETCONDITION() LEX(state) #define YYCURSOR LEX(cursor) #define YYMARKER LEX(marker) +#define YYCTXMARKER LEX(ctxmarker) #define yyleng LEX(len) #define yytext ((char*) LEX(text)) #undef YYDEBUG @@ -21,12 +22,13 @@ #define YYFILL(n) #define NORMAL 0 -#define RAW 1 -#define INITIAL 2 +#define PRE_RAW 1 +#define RAW 2 +#define INITIAL 3 -ZEND_EXTERN_MODULE_GLOBALS(phpdbg); +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) -void phpdbg_init_lexer (phpdbg_param_t *stack, char *input TSRMLS_DC) { +void phpdbg_init_lexer (phpdbg_param_t *stack, char *input) { PHPDBG_G(parser_stack) = stack; YYSETCONDITION(INITIAL); @@ -35,8 +37,26 @@ void phpdbg_init_lexer (phpdbg_param_t *stack, char *input TSRMLS_DC) { LEX(len) = strlen(input); } +static int unescape_string(char *s) { + switch (*s) { + case '\'': + case '\"': { + char start = *s; + size_t off = 1; + do { + if (s[off] == '\\') { + off++; + } + *s = s[off]; + } while ((++s)[off] != start); + return off + 1; + } + } + + return 0; +} + int phpdbg_lex (phpdbg_param_t* yylval) { - TSRMLS_FETCH(); /* Slow, but this is not a major problem here. TODO: Use TSRMLS_DC */ restart: LEX(text) = YYCURSOR; @@ -56,12 +76,13 @@ T_SHELL 'sh' T_IF 'if' T_RUN 'run' T_RUN_SHORT "r" -WS [ \r\n\t]+ +WS [ \r\t]+ DIGITS [-]?[0-9\.]+ ID [^ \r\n\t:#\000]+ +GENERIC_ID ([^ \r\n\t:#\000"']|":\\")+|["]([^\n\000"\\]|"\\\\"|"\\"["])+["]|[']([^\n\000'\\]|"\\\\"|"\\"['])+['] ADDR [0][x][a-fA-F0-9]+ OPCODE (ZEND_|zend_)([A-Za-z])+ -INPUT [^\n\000]+ +INPUT ([^\n\000#"']|["]([^\n\000"\\]|"\\\\"|"\\"["])+["]|[']([^\n\000'\\]|"\\\\"|"\\"['])+['])+ <!*> := yyleng = (size_t) YYCURSOR - (size_t) yytext; @@ -69,35 +90,50 @@ INPUT [^\n\000]+ return 0; } +<PRE_RAW, NORMAL>"-r"{WS}?{DIGITS} { + char *text = yytext + 2; + while (*++text < '0'); + yylval->num = atoi(text); + return T_REQ_ID; +} + <NORMAL>{T_IF}{WS} { YYSETCONDITION(RAW); phpdbg_init_param(yylval, EMPTY_PARAM); return T_IF; } -<NORMAL>{ID}[:]{1}[//]{2} { - phpdbg_init_param(yylval, STR_PARAM); - yylval->str = zend_strndup(yytext, yyleng); - yylval->len = yyleng; - return T_PROTO; -} -<NORMAL>[#]{1} { +<NORMAL>"#"/{DIGITS} { return T_POUND; } -<NORMAL>[:]{2} { + +<*>"#" { + YYSETCONDITION(INITIAL); + return T_SEPARATOR; +} + +<NORMAL>"::" { return T_DCOLON; } -<NORMAL>[:]{1} { + +<NORMAL>":"/[^\\] { return T_COLON; } -<NORMAL>({T_YES}|{T_ON}|{T_ENABLED}|{T_TRUE}){WS} { +<NORMAL>{ID}"://" { + phpdbg_init_param(yylval, STR_PARAM); + yylval->str = estrndup(yytext, yyleng); + yylval->len = yyleng; + return T_PROTO; +} + +<NORMAL>({T_YES}|{T_ON}|{T_ENABLED}|{T_TRUE})/[ \r\t\n\000] { phpdbg_init_param(yylval, NUMERIC_PARAM); - yylval->num = 1; + yylval->num = 1; return T_TRUTHY; } -<NORMAL>({T_NO}|{T_OFF}|{T_DISABLED}|{T_FALSE}){WS} { +<NORMAL>({T_NO}|{T_OFF}|{T_DISABLED}|{T_FALSE})/[ \r\t\n\000] { phpdbg_init_param(yylval, NUMERIC_PARAM); yylval->num = 0; return T_FALSY; @@ -117,21 +153,21 @@ INPUT [^\n\000]+ <NORMAL>{OPCODE} { phpdbg_init_param(yylval, OP_PARAM); - yylval->str = zend_strndup(yytext, yyleng); + yylval->str = estrndup(yytext, yyleng); yylval->len = yyleng; return T_OPCODE; } -<NORMAL>{ID} { +<NORMAL>{GENERIC_ID} { phpdbg_init_param(yylval, STR_PARAM); - yylval->str = zend_strndup(yytext, yyleng); + yylval->str = estrndup(yytext, yyleng - unescape_string(yytext)); yylval->len = yyleng; - return T_ID; + return T_ID; } <RAW>{INPUT} { phpdbg_init_param(yylval, STR_PARAM); - yylval->str = zend_strndup(yytext, yyleng); + yylval->str = estrndup(yytext, yyleng - unescape_string(yytext)); yylval->len = yyleng; return T_INPUT; } @@ -143,22 +179,31 @@ INPUT [^\n\000]+ } <INITIAL>{T_EVAL}{WS} { - YYSETCONDITION(RAW); + YYSETCONDITION(PRE_RAW); phpdbg_init_param(yylval, EMPTY_PARAM); return T_EVAL; } + <INITIAL>{T_SHELL}{WS} { - YYSETCONDITION(RAW); + YYSETCONDITION(PRE_RAW); phpdbg_init_param(yylval, EMPTY_PARAM); return T_SHELL; } + <INITIAL>({T_RUN}|{T_RUN_SHORT}){WS} { - YYSETCONDITION(RAW); + YYSETCONDITION(PRE_RAW); phpdbg_init_param(yylval, EMPTY_PARAM); return T_RUN; } -<INITIAL>. { +<PRE_RAW>[^ ] { + YYSETCONDITION(RAW); + + YYCURSOR = LEX(text); + goto restart; +} + +<INITIAL>[^ ] { YYSETCONDITION(NORMAL); YYCURSOR = LEX(text); diff --git a/sapi/phpdbg/phpdbg_list.c b/sapi/phpdbg/phpdbg_list.c index 8f5a1d86dc..e9cf1bc0b8 100644 --- a/sapi/phpdbg/phpdbg_list.c +++ b/sapi/phpdbg/phpdbg_list.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -31,38 +31,41 @@ #include "phpdbg_utils.h" #include "phpdbg_prompt.h" #include "php_streams.h" +#include "zend_exceptions.h" -ZEND_EXTERN_MODULE_GLOBALS(phpdbg); +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) -#define PHPDBG_LIST_COMMAND_D(f, h, a, m, l, s) \ - PHPDBG_COMMAND_D_EXP(f, h, a, m, l, s, &phpdbg_prompt_commands[13]) +#define PHPDBG_LIST_COMMAND_D(f, h, a, m, l, s, flags) \ + PHPDBG_COMMAND_D_EXP(f, h, a, m, l, s, &phpdbg_prompt_commands[12], flags) const phpdbg_command_t phpdbg_list_commands[] = { - PHPDBG_LIST_COMMAND_D(lines, "lists the specified lines", 'l', list_lines, NULL, "l"), - PHPDBG_LIST_COMMAND_D(class, "lists the specified class", 'c', list_class, NULL, "s"), - PHPDBG_LIST_COMMAND_D(method, "lists the specified method", 'm', list_method, NULL, "m"), - PHPDBG_LIST_COMMAND_D(func, "lists the specified function", 'f', list_func, NULL, "s"), + PHPDBG_LIST_COMMAND_D(lines, "lists the specified lines", 'l', list_lines, NULL, "l", PHPDBG_ASYNC_SAFE), + PHPDBG_LIST_COMMAND_D(class, "lists the specified class", 'c', list_class, NULL, "s", PHPDBG_ASYNC_SAFE), + PHPDBG_LIST_COMMAND_D(method, "lists the specified method", 'm', list_method, NULL, "m", PHPDBG_ASYNC_SAFE), + PHPDBG_LIST_COMMAND_D(func, "lists the specified function", 'f', list_func, NULL, "s", PHPDBG_ASYNC_SAFE), PHPDBG_END_COMMAND }; PHPDBG_LIST(lines) /* {{{ */ { - if (!PHPDBG_G(exec) && !zend_is_executing(TSRMLS_C)) { - phpdbg_error("Not executing, and execution context not set"); + if (!PHPDBG_G(exec) && !zend_is_executing()) { + phpdbg_error("inactive", "type=\"execution\"", "Not executing, and execution context not set"); return SUCCESS; } switch (param->type) { - case NUMERIC_PARAM: - phpdbg_list_file(phpdbg_current_file(TSRMLS_C), - (param->num < 0 ? 1 - param->num : param->num), - (param->num < 0 ? param->num : 0) + zend_get_executed_lineno(TSRMLS_C), - 0 TSRMLS_CC); - break; - - case FILE_PARAM: - phpdbg_list_file(param->file.name, param->file.line, 0, 0 TSRMLS_CC); - break; + case NUMERIC_PARAM: { + const char *char_file = phpdbg_current_file(); + zend_string *file = zend_string_init(char_file, strlen(char_file), 0); + phpdbg_list_file(file, param->num < 0 ? 1 - param->num : param->num, (param->num < 0 ? param->num : 0) + zend_get_executed_lineno(), 0); + efree(file); + } break; + + case FILE_PARAM: { + zend_string *file = zend_string_init(param->file.name, strlen(param->file.name), 0); + phpdbg_list_file(file, param->file.line, 0, 0); + efree(file); + } break; phpdbg_default_switch_case(); } @@ -72,28 +75,28 @@ PHPDBG_LIST(lines) /* {{{ */ PHPDBG_LIST(func) /* {{{ */ { - phpdbg_list_function_byname(param->str, param->len TSRMLS_CC); + phpdbg_list_function_byname(param->str, param->len); return SUCCESS; } /* }}} */ PHPDBG_LIST(method) /* {{{ */ { - zend_class_entry **ce; + zend_class_entry *ce; - if (zend_lookup_class(param->method.class, strlen(param->method.class), &ce TSRMLS_CC) == SUCCESS) { + if (phpdbg_safe_class_lookup(param->method.class, strlen(param->method.class), &ce) == SUCCESS) { zend_function *function; char *lcname = zend_str_tolower_dup(param->method.name, strlen(param->method.name)); - if (zend_hash_find(&(*ce)->function_table, lcname, strlen(lcname)+1, (void**) &function) == SUCCESS) { - phpdbg_list_function(function TSRMLS_CC); + if ((function = zend_hash_str_find_ptr(&ce->function_table, lcname, strlen(lcname)))) { + phpdbg_list_function(function); } else { - phpdbg_error("Could not find %s::%s", param->method.class, param->method.name); + phpdbg_error("list", "type=\"notfound\" method=\"%s::%s\"", "Could not find %s::%s", param->method.class, param->method.name); } efree(lcname); } else { - phpdbg_error("Could not find the class %s", param->method.class); + phpdbg_error("list", "type=\"notfound\" class=\"%s\"", "Could not find the class %s", param->method.class); } return SUCCESS; @@ -101,100 +104,94 @@ PHPDBG_LIST(method) /* {{{ */ PHPDBG_LIST(class) /* {{{ */ { - zend_class_entry **ce; - - if (zend_lookup_class(param->str, param->len, &ce TSRMLS_CC) == SUCCESS) { - if ((*ce)->type == ZEND_USER_CLASS) { - if ((*ce)->info.user.filename) { - phpdbg_list_file( - (*ce)->info.user.filename, - (*ce)->info.user.line_end - (*ce)->info.user.line_start + 1, - (*ce)->info.user.line_start, 0 TSRMLS_CC - ); + zend_class_entry *ce; + + if (phpdbg_safe_class_lookup(param->str, param->len, &ce) == SUCCESS) { + if (ce->type == ZEND_USER_CLASS) { + if (ce->info.user.filename) { + phpdbg_list_file(ce->info.user.filename, ce->info.user.line_end - ce->info.user.line_start + 1, ce->info.user.line_start, 0); } else { - phpdbg_error("The source of the requested class (%s) cannot be found", (*ce)->name); + phpdbg_error("list", "type=\"nosource\" class=\"%s\"", "The source of the requested class (%s) cannot be found", ZSTR_VAL(ce->name)); } } else { - phpdbg_error("The class requested (%s) is not user defined", (*ce)->name); + phpdbg_error("list", "type=\"internalclass\" class=\"%s\"", "The class requested (%s) is not user defined", ZSTR_VAL(ce->name)); } } else { - phpdbg_error("The requested class (%s) could not be found", param->str); + phpdbg_error("list", "type=\"notfound\" class=\"%s\"", "The requested class (%s) could not be found", param->str); } return SUCCESS; } /* }}} */ -void phpdbg_list_file(const char *filename, long count, long offset, int highlight TSRMLS_DC) /* {{{ */ +void phpdbg_list_file(zend_string *filename, uint count, int offset, uint highlight) /* {{{ */ { - struct stat st; - char *opened = NULL; - char buffer[8096] = {0,}; - long line = 0; - - php_stream *stream = NULL; - - if (VCWD_STAT(filename, &st) == FAILURE) { - phpdbg_error("Failed to stat file %s", filename); - return; + uint line, lastline; + phpdbg_file_source *data; + char resolved_path_buf[MAXPATHLEN]; + const char *abspath; + + if (VCWD_REALPATH(ZSTR_VAL(filename), resolved_path_buf)) { + abspath = resolved_path_buf; + } else { + abspath = ZSTR_VAL(filename); } - stream = php_stream_open_wrapper(filename, "rb", USE_PATH, &opened); - - if (!stream) { - phpdbg_error("Failed to open file %s to list", filename); + if (!(data = zend_hash_str_find_ptr(&PHPDBG_G(file_sources), abspath, strlen(abspath)))) { + phpdbg_error("list", "type=\"unknownfile\"", "Could not find information about included file..."); return; } - + if (offset < 0) { count += offset; offset = 0; } - - while (php_stream_gets(stream, buffer, sizeof(buffer)) != NULL) { - long linelen = strlen(buffer); - ++line; - - if (offset <= line) { - if (!highlight) { - phpdbg_write("%05ld: %s", line, buffer); - } else { - if (highlight != line) { - phpdbg_write(" %05ld: %s", line, buffer); - } else { - phpdbg_write(">%05ld: %s", line, buffer); - } - } + lastline = offset + count; + + if (lastline > data->lines) { + lastline = data->lines; + } + + phpdbg_xml("<list %r file=\"%s\">", ZSTR_VAL(filename)); - if (buffer[linelen - 1] != '\n') { - phpdbg_write("\n"); + for (line = offset; line < lastline;) { + uint linestart = data->line[line++]; + uint linelen = data->line[line] - linestart; + char *buffer = data->buf + linestart; + + if (!highlight) { + phpdbg_write("line", "line=\"%u\" code=\"%.*s\"", " %05u: %.*s", line, linelen, buffer); + } else { + if (highlight != line) { + phpdbg_write("line", "line=\"%u\" code=\"%.*s\"", " %05u: %.*s", line, linelen, buffer); + } else { + phpdbg_write("line", "line=\"%u\" code=\"%.*s\" current=\"current\"", ">%05u: %.*s", line, linelen, buffer); } } - if (count > 0 && count + offset - 1 < line) { - break; + if (*(buffer + linelen - 1) != '\n' || !linelen) { + phpdbg_out("\n"); } } - - php_stream_close(stream); + + phpdbg_xml("</list>"); } /* }}} */ -void phpdbg_list_function(const zend_function *fbc TSRMLS_DC) /* {{{ */ +void phpdbg_list_function(const zend_function *fbc) /* {{{ */ { const zend_op_array *ops; if (fbc->type != ZEND_USER_FUNCTION) { - phpdbg_error("The function requested (%s) is not user defined", fbc->common.function_name); + phpdbg_error("list", "type=\"internalfunction\" function=\"%s\"", "The function requested (%s) is not user defined", ZSTR_VAL(fbc->common.function_name)); return; } - ops = (zend_op_array*)fbc; + ops = (zend_op_array *) fbc; - phpdbg_list_file(ops->filename, - ops->line_end - ops->line_start + 1, ops->line_start, 0 TSRMLS_CC); + phpdbg_list_file(ops->filename, ops->line_end - ops->line_start + 1, ops->line_start, 0); } /* }}} */ -void phpdbg_list_function_byname(const char *str, size_t len TSRMLS_DC) /* {{{ */ +void phpdbg_list_function_byname(const char *str, size_t len) /* {{{ */ { HashTable *func_table = EG(function_table); zend_function* fbc; @@ -209,11 +206,11 @@ void phpdbg_list_function_byname(const char *str, size_t len TSRMLS_DC) /* {{{ * func_table = &EG(scope)->function_table; } else { - phpdbg_error("No active class"); + phpdbg_error("inactive", "type=\"noclasses\"", "No active class"); return; } } else if (!EG(function_table)) { - phpdbg_error("No function table loaded"); + phpdbg_error("inactive", "type=\"function_table\"", "No function table loaded"); return; } else { func_table = EG(function_table); @@ -222,12 +219,176 @@ void phpdbg_list_function_byname(const char *str, size_t len TSRMLS_DC) /* {{{ * /* use lowercase names, case insensitive */ func_name = zend_str_tolower_dup(func_name, func_name_len); - if (zend_hash_find(func_table, func_name, func_name_len+1, (void**)&fbc) == SUCCESS) { - phpdbg_list_function(fbc TSRMLS_CC); - } else { - phpdbg_error("Function %s not found", func_name); - } + phpdbg_try_access { + if ((fbc = zend_hash_str_find_ptr(func_table, func_name, func_name_len))) { + phpdbg_list_function(fbc); + } else { + phpdbg_error("list", "type=\"nofunction\" function=\"%s\"", "Function %s not found", func_name); + } + } phpdbg_catch_access { + phpdbg_error("signalsegv", "function=\"%s\"", "Could not list function %s, invalid data source", func_name); + } phpdbg_end_try_access(); efree(func_name); } /* }}} */ +zend_op_array *phpdbg_compile_file(zend_file_handle *file, int type) { + phpdbg_file_source data, *dataptr; + zend_file_handle fake; + zend_op_array *ret; + char *filename = (char *)(file->opened_path ? ZSTR_VAL(file->opened_path) : file->filename); + uint line; + char *bufptr, *endptr; + char resolved_path_buf[MAXPATHLEN]; + + if (zend_stream_fixup(file, &bufptr, &data.len) == FAILURE) { + zend_file_handle_dtor(file); + return NULL; + } + + data.buf = emalloc(data.len + ZEND_MMAP_AHEAD + 1); + if (data.len > 0) { + memcpy(data.buf, bufptr, data.len); + } + memset(data.buf + data.len, 0, ZEND_MMAP_AHEAD + 1); + data.filename = filename; + data.line[0] = 0; + + memset(&fake, 0, sizeof(fake)); + fake.type = ZEND_HANDLE_MAPPED; + fake.handle.stream.mmap.buf = data.buf; + fake.handle.stream.mmap.len = data.len; + fake.free_filename = 0; + fake.filename = filename; + fake.opened_path = file->opened_path; + + *(dataptr = emalloc(sizeof(phpdbg_file_source) + sizeof(uint) * data.len)) = data; + if (VCWD_REALPATH(filename, resolved_path_buf)) { + filename = resolved_path_buf; + } + + for (line = 0, bufptr = data.buf - 1, endptr = data.buf + data.len; ++bufptr < endptr;) { + if (*bufptr == '\n') { + dataptr->line[++line] = (uint)(bufptr - data.buf) + 1; + } + } + dataptr->lines = ++line; + dataptr->line[line] = endptr - data.buf; + + ret = PHPDBG_G(compile_file)(&fake, type); + + if (ret == NULL) { + efree(data.buf); + efree(dataptr); + return NULL; + } + + dataptr = erealloc(dataptr, sizeof(phpdbg_file_source) + sizeof(uint) * line); + zend_hash_str_add_ptr(&PHPDBG_G(file_sources), filename, strlen(filename), dataptr); + phpdbg_resolve_pending_file_break(filename); + + fake.opened_path = NULL; + zend_file_handle_dtor(&fake); + zend_file_handle_dtor(file); + + return ret; +} + +zend_op_array *phpdbg_init_compile_file(zend_file_handle *file, int type) { + char *filename = (char *)(file->opened_path ? ZSTR_VAL(file->opened_path) : file->filename); + char resolved_path_buf[MAXPATHLEN]; + zend_op_array *op_array; + phpdbg_file_source *dataptr; + + if (VCWD_REALPATH(filename, resolved_path_buf)) { + filename = resolved_path_buf; + } + + op_array = PHPDBG_G(init_compile_file)(file, type); + + if (op_array == NULL) { + return NULL; + } + + dataptr = zend_hash_str_find_ptr(&PHPDBG_G(file_sources), filename, strlen(filename)); + ZEND_ASSERT(dataptr != NULL); + + dataptr->op_array = *op_array; + if (dataptr->op_array.refcount) { + ++*dataptr->op_array.refcount; + } + + return op_array; +} + +zend_op_array *phpdbg_compile_string(zval *source_string, char *filename) { + zend_string *fake_name; + zend_op_array *op_array; + phpdbg_file_source *dataptr; + uint line; + char *bufptr, *endptr; + + if (PHPDBG_G(flags) & PHPDBG_IN_EVAL) { + return PHPDBG_G(compile_string)(source_string, filename); + } + + dataptr = emalloc(sizeof(phpdbg_file_source) + sizeof(uint) * Z_STRLEN_P(source_string)); + dataptr->buf = estrndup(Z_STRVAL_P(source_string), Z_STRLEN_P(source_string)); + dataptr->len = Z_STRLEN_P(source_string); + dataptr->line[0] = 0; + for (line = 0, bufptr = dataptr->buf - 1, endptr = dataptr->buf + dataptr->len; ++bufptr < endptr;) { + if (*bufptr == '\n') { + dataptr->line[++line] = (uint)(bufptr - dataptr->buf) + 1; + } + } + dataptr->lines = ++line; + dataptr->line[line] = endptr - dataptr->buf; + + op_array = PHPDBG_G(compile_string)(source_string, filename); + + if (op_array == NULL) { + efree(dataptr->buf); + efree(dataptr); + return NULL; + } + + fake_name = strpprintf(0, "%s\0%p", filename, op_array->opcodes); + + dataptr = erealloc(dataptr, sizeof(phpdbg_file_source) + sizeof(uint) * line); + zend_hash_add_ptr(&PHPDBG_G(file_sources), fake_name, dataptr); + + dataptr->filename = estrndup(ZSTR_VAL(fake_name), ZSTR_LEN(fake_name)); + zend_string_release(fake_name); + + dataptr->op_array = *op_array; + if (dataptr->op_array.refcount) { + ++*dataptr->op_array.refcount; + } + + return op_array; +} + +void phpdbg_free_file_source(zval *zv) { + phpdbg_file_source *data = Z_PTR_P(zv); + + if (data->buf) { + efree(data->buf); + } + + destroy_op_array(&data->op_array); + + efree(data); +} + +void phpdbg_init_list(void) { + PHPDBG_G(compile_file) = zend_compile_file; + PHPDBG_G(compile_string) = zend_compile_string; + zend_hash_init(&PHPDBG_G(file_sources), 1, NULL, (dtor_func_t) phpdbg_free_file_source, 0); + zend_compile_file = phpdbg_compile_file; + zend_compile_string = phpdbg_compile_string; +} + +void phpdbg_list_update(void) { + PHPDBG_G(init_compile_file) = zend_compile_file; + zend_compile_file = phpdbg_init_compile_file; +} diff --git a/sapi/phpdbg/phpdbg_list.h b/sapi/phpdbg/phpdbg_list.h index 9397313c13..c011b9598a 100644 --- a/sapi/phpdbg/phpdbg_list.h +++ b/sapi/phpdbg/phpdbg_list.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -32,10 +32,26 @@ PHPDBG_LIST(class); PHPDBG_LIST(method); PHPDBG_LIST(func); -void phpdbg_list_function_byname(const char *, size_t TSRMLS_DC); -void phpdbg_list_function(const zend_function* TSRMLS_DC); -void phpdbg_list_file(const char*, long, long, int TSRMLS_DC); +void phpdbg_list_function_byname(const char *, size_t); +void phpdbg_list_function(const zend_function *); +void phpdbg_list_file(zend_string *, uint, int, uint); extern const phpdbg_command_t phpdbg_list_commands[]; +void phpdbg_init_list(void); +void phpdbg_list_update(void); + +typedef struct { + char *filename; + char *buf; + size_t len; +#if HAVE_MMAP + void *map; +#endif + zend_op_array op_array; + zend_bool destroy_op_array; + uint lines; + uint line[1]; +} phpdbg_file_source; + #endif /* PHPDBG_LIST_H */ diff --git a/sapi/phpdbg/phpdbg_opcode.c b/sapi/phpdbg/phpdbg_opcode.c index fae55d2cd8..e64ab0d636 100644 --- a/sapi/phpdbg/phpdbg_opcode.c +++ b/sapi/phpdbg/phpdbg_opcode.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -23,124 +23,153 @@ #include "zend_compile.h" #include "phpdbg_opcode.h" #include "phpdbg_utils.h" +#include "ext/standard/php_string.h" -ZEND_EXTERN_MODULE_GLOBALS(phpdbg); +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) -static inline zend_uint phpdbg_decode_literal(zend_op_array *ops, zend_literal *literal TSRMLS_DC) /* {{{ */ +static inline const char *phpdbg_decode_opcode(zend_uchar opcode) /* {{{ */ { - int iter = 0; - - while (iter < ops->last_literal) { - if (literal == &ops->literals[iter]) { - return iter; - } - iter++; + const char *ret = zend_get_opcode_name(opcode); + if (ret) { + return ret + 5; /* Skip ZEND_ prefix */ } - - return 0; + return "UNKNOWN"; } /* }}} */ -static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, zend_uint type, HashTable *vars TSRMLS_DC) /* {{{ */ +static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, uint32_t type) /* {{{ */ { char *decode = NULL; - switch (type &~ EXT_TYPE_UNUSED) { - case IS_CV: - asprintf(&decode, "$%s", ops->vars[op->var].name); - break; - - case IS_VAR: - case IS_TMP_VAR: { - zend_ulong id = 0, *pid = NULL; - if (vars != NULL) { - if (zend_hash_index_find(vars, (zend_ulong) ops->vars - op->var, (void**) &pid) != SUCCESS) { - id = zend_hash_num_elements(vars); - zend_hash_index_update( - vars, (zend_ulong) ops->vars - op->var, - (void**) &id, - sizeof(zend_ulong), NULL); - } else id = *pid; - } - asprintf(&decode, "@%lu", id); + switch (type) { + case IS_CV: { + zend_string *var = ops->vars[EX_VAR_TO_NUM(op->var)]; + spprintf(&decode, 0, "$%.*s%c", + ZSTR_LEN(var) <= 19 ? (int) ZSTR_LEN(var) : 18, + ZSTR_VAL(var), ZSTR_LEN(var) <= 19 ? 0 : '+'); } break; - case IS_CONST: - asprintf(&decode, "C%u", phpdbg_decode_literal(ops, op->literal TSRMLS_CC)); + case IS_VAR: + spprintf(&decode, 0, "@%u", EX_VAR_TO_NUM(op->var) - ops->last_var); break; - - case IS_UNUSED: - asprintf(&decode, "<unused>"); + case IS_TMP_VAR: + spprintf(&decode, 0, "~%u", EX_VAR_TO_NUM(op->var) - ops->last_var); break; + case IS_CONST: { + zval *literal = RT_CONSTANT(ops, *op); + decode = phpdbg_short_zval_print(literal, 20); + } break; } return decode; } /* }}} */ -char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op, HashTable *vars TSRMLS_DC) /*{{{ */ +char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op) /*{{{ */ { - char *decode[4] = {NULL, NULL, NULL, NULL}; + const char *opcode_name = phpdbg_decode_opcode(op->opcode); + char *result, *decode[4] = {NULL, NULL, NULL, NULL}; + /* EX */ + switch (op->opcode) { + case ZEND_FAST_CALL: + if (op->extended_value == ZEND_FAST_CALL_FROM_FINALLY) { + decode[0] = estrdup("FAST_CALL<FROM_FINALLY>"); + } + break; + case ZEND_FAST_RET: + if (op->extended_value != 0) { + spprintf(&decode[0], 0, "FAST_RET<%s>", + op->extended_value == ZEND_FAST_RET_TO_CATCH ? "TO_CATCH" : "TO_FINALLY"); + } + break; + } + + /* OP1 */ switch (op->opcode) { case ZEND_JMP: -#ifdef ZEND_GOTO - case ZEND_GOTO: -#endif -#ifdef ZEND_FAST_CALL case ZEND_FAST_CALL: -#endif - asprintf(&decode[1], "J%ld", op->op1.jmp_addr - ops->opcodes); - goto format; + spprintf(&decode[1], 0, "J%td", OP_JMP_ADDR(op, op->op1) - ops->opcodes); + break; + + case ZEND_INIT_FCALL: + case ZEND_RECV: + case ZEND_RECV_INIT: + case ZEND_RECV_VARIADIC: + spprintf(&decode[1], 0, "%" PRIu32, op->op1.num); + break; + + default: + decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type); + break; + } + /* OP2 */ + switch (op->opcode) { case ZEND_JMPZNZ: - decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC); - asprintf( - &decode[2], "J%u or J%lu", op->op2.opline_num, op->extended_value); - goto result; + spprintf(&decode[2], 0, "J%td or J%td", + OP_JMP_ADDR(op, op->op2) - ops->opcodes, + ZEND_OFFSET_TO_OPLINE(op, op->extended_value) - ops->opcodes); + break; case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: - -#ifdef ZEND_JMP_SET case ZEND_JMP_SET: -#endif -#ifdef ZEND_JMP_SET_VAR - case ZEND_JMP_SET_VAR: -#endif - decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC); - asprintf( - &decode[2], "J%ld", op->op2.jmp_addr - ops->opcodes); - goto result; - - case ZEND_RECV_INIT: - goto result; + case ZEND_ASSERT_CHECK: + spprintf(&decode[2], 0, "J%td", OP_JMP_ADDR(op, op->op2) - ops->opcodes); + break; - default: { - decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars TSRMLS_CC); - decode[2] = phpdbg_decode_op(ops, &op->op2, op->op2_type, vars TSRMLS_CC); -result: - decode[3] = phpdbg_decode_op(ops, &op->result, op->result_type, vars TSRMLS_CC); -format: - asprintf( - &decode[0], - "%-20s %-20s %-20s", - decode[1] ? decode[1] : "", - decode[2] ? decode[2] : "", - decode[3] ? decode[3] : ""); + case ZEND_FAST_CALL: + case ZEND_FAST_RET: + if (op->extended_value != 0) { + spprintf(&decode[2], 0, "J%" PRIu32, op->op2.opline_num); } + break; + + case ZEND_SEND_VAL: + case ZEND_SEND_VAL_EX: + case ZEND_SEND_VAR: + case ZEND_SEND_VAR_NO_REF: + case ZEND_SEND_REF: + case ZEND_SEND_VAR_EX: + case ZEND_SEND_USER: + spprintf(&decode[2], 0, "%" PRIu32, op->op2.num); + break; + + default: + decode[2] = phpdbg_decode_op(ops, &op->op2, op->op2_type); + break; } + /* RESULT */ + switch (op->opcode) { + case ZEND_CATCH: + spprintf(&decode[3], 0, "%" PRIu32, op->result.num); + break; + default: + decode[3] = phpdbg_decode_op(ops, &op->result, op->result_type); + break; + } + + spprintf(&result, 0, + "%-23s %-20s %-20s %-20s", + decode[0] ? decode[0] : opcode_name, + decode[1] ? decode[1] : "", + decode[2] ? decode[2] : "", + decode[3] ? decode[3] : ""); + + if (decode[0]) + efree(decode[0]); if (decode[1]) - free(decode[1]); + efree(decode[1]); if (decode[2]) - free(decode[2]); + efree(decode[2]); if (decode[3]) - free(decode[3]); + efree(decode[3]); - return decode[0]; + return result; } /* }}} */ -void phpdbg_print_opline_ex(zend_execute_data *execute_data, HashTable *vars, zend_bool ignore_flags TSRMLS_DC) /* {{{ */ +void phpdbg_print_opline_ex(zend_execute_data *execute_data, zend_bool ignore_flags) /* {{{ */ { /* force out a line while stepping so the user knows what is happening */ if (ignore_flags || @@ -148,221 +177,44 @@ void phpdbg_print_opline_ex(zend_execute_data *execute_data, HashTable *vars, ze (PHPDBG_G(flags) & PHPDBG_IS_STEPPING) || (PHPDBG_G(oplog)))) { - zend_op *opline = execute_data->opline; - char *decode = phpdbg_decode_opline(execute_data->op_array, opline, vars TSRMLS_CC); + zend_op *opline = (zend_op *) execute_data->opline; + char *decode = phpdbg_decode_opline(&execute_data->func->op_array, opline); if (ignore_flags || (!(PHPDBG_G(flags) & PHPDBG_IS_QUIET) || (PHPDBG_G(flags) & PHPDBG_IS_STEPPING))) { /* output line info */ - phpdbg_notice("L%-5u %16p %-30s %s %s", + phpdbg_notice("opline", "line=\"%u\" opline=\"%p\" op=\"%s\" file=\"%s\"", "L%-5u %16p %s %s", opline->lineno, opline, - phpdbg_decode_opcode(opline->opcode), decode, - execute_data->op_array->filename ? execute_data->op_array->filename : "unknown"); + execute_data->func->op_array.filename ? ZSTR_VAL(execute_data->func->op_array.filename) : "unknown"); } if (!ignore_flags && PHPDBG_G(oplog)) { - phpdbg_log_ex(PHPDBG_G(oplog), "L%-5u %16p %-30s %s %s", + phpdbg_log_ex(fileno(PHPDBG_G(oplog)), "L%-5u %16p %s %s\n", opline->lineno, opline, - phpdbg_decode_opcode(opline->opcode), decode, - execute_data->op_array->filename ? execute_data->op_array->filename : "unknown"); + execute_data->func->op_array.filename ? ZSTR_VAL(execute_data->func->op_array.filename) : "unknown"); } - if (decode) { - free(decode); - } + efree(decode); } -} /* }}} */ -void phpdbg_print_opline(zend_execute_data *execute_data, zend_bool ignore_flags TSRMLS_DC) /* {{{ */ -{ - phpdbg_print_opline_ex(execute_data, NULL, ignore_flags TSRMLS_CC); + if (PHPDBG_G(oplog_list)) { + phpdbg_oplog_entry *cur = zend_arena_alloc(&PHPDBG_G(oplog_arena), sizeof(phpdbg_oplog_entry)); + zend_op_array *op_array = &execute_data->func->op_array; + cur->op = (zend_op *) execute_data->opline; + cur->opcodes = op_array->opcodes; + cur->filename = op_array->filename; + cur->scope = op_array->scope; + cur->function_name = op_array->function_name; + cur->next = NULL; + PHPDBG_G(oplog_cur)->next = cur; + PHPDBG_G(oplog_cur) = cur; + } } /* }}} */ -const char *phpdbg_decode_opcode(zend_uchar opcode) /* {{{ */ +void phpdbg_print_opline(zend_execute_data *execute_data, zend_bool ignore_flags) /* {{{ */ { -#if ZEND_EXTENSION_API_NO <= PHP_5_5_API_NO -#define CASE(s) case s: return #s - switch (opcode) { - CASE(ZEND_NOP); - CASE(ZEND_ADD); - CASE(ZEND_SUB); - CASE(ZEND_MUL); - CASE(ZEND_DIV); - CASE(ZEND_MOD); - CASE(ZEND_SL); - CASE(ZEND_SR); - CASE(ZEND_CONCAT); - CASE(ZEND_BW_OR); - CASE(ZEND_BW_AND); - CASE(ZEND_BW_XOR); - CASE(ZEND_BW_NOT); - CASE(ZEND_BOOL_NOT); - CASE(ZEND_BOOL_XOR); - CASE(ZEND_IS_IDENTICAL); - CASE(ZEND_IS_NOT_IDENTICAL); - CASE(ZEND_IS_EQUAL); - CASE(ZEND_IS_NOT_EQUAL); - CASE(ZEND_IS_SMALLER); - CASE(ZEND_IS_SMALLER_OR_EQUAL); - CASE(ZEND_CAST); - CASE(ZEND_QM_ASSIGN); - CASE(ZEND_ASSIGN_ADD); - CASE(ZEND_ASSIGN_SUB); - CASE(ZEND_ASSIGN_MUL); - CASE(ZEND_ASSIGN_DIV); - CASE(ZEND_ASSIGN_MOD); - CASE(ZEND_ASSIGN_SL); - CASE(ZEND_ASSIGN_SR); - CASE(ZEND_ASSIGN_CONCAT); - CASE(ZEND_ASSIGN_BW_OR); - CASE(ZEND_ASSIGN_BW_AND); - CASE(ZEND_ASSIGN_BW_XOR); - CASE(ZEND_PRE_INC); - CASE(ZEND_PRE_DEC); - CASE(ZEND_POST_INC); - CASE(ZEND_POST_DEC); - CASE(ZEND_ASSIGN); - CASE(ZEND_ASSIGN_REF); - CASE(ZEND_ECHO); - CASE(ZEND_PRINT); - CASE(ZEND_JMP); - CASE(ZEND_JMPZ); - CASE(ZEND_JMPNZ); - CASE(ZEND_JMPZNZ); - CASE(ZEND_JMPZ_EX); - CASE(ZEND_JMPNZ_EX); - CASE(ZEND_CASE); - CASE(ZEND_SWITCH_FREE); - CASE(ZEND_BRK); - CASE(ZEND_CONT); - CASE(ZEND_BOOL); - CASE(ZEND_INIT_STRING); - CASE(ZEND_ADD_CHAR); - CASE(ZEND_ADD_STRING); - CASE(ZEND_ADD_VAR); - CASE(ZEND_BEGIN_SILENCE); - CASE(ZEND_END_SILENCE); - CASE(ZEND_INIT_FCALL_BY_NAME); - CASE(ZEND_DO_FCALL); - CASE(ZEND_DO_FCALL_BY_NAME); - CASE(ZEND_RETURN); - CASE(ZEND_RECV); - CASE(ZEND_RECV_INIT); - CASE(ZEND_SEND_VAL); - CASE(ZEND_SEND_VAR); - CASE(ZEND_SEND_REF); - CASE(ZEND_NEW); - CASE(ZEND_INIT_NS_FCALL_BY_NAME); - CASE(ZEND_FREE); - CASE(ZEND_INIT_ARRAY); - CASE(ZEND_ADD_ARRAY_ELEMENT); - CASE(ZEND_INCLUDE_OR_EVAL); - CASE(ZEND_UNSET_VAR); - CASE(ZEND_UNSET_DIM); - CASE(ZEND_UNSET_OBJ); - CASE(ZEND_FE_RESET); - CASE(ZEND_FE_FETCH); - CASE(ZEND_EXIT); - CASE(ZEND_FETCH_R); - CASE(ZEND_FETCH_DIM_R); - CASE(ZEND_FETCH_OBJ_R); - CASE(ZEND_FETCH_W); - CASE(ZEND_FETCH_DIM_W); - CASE(ZEND_FETCH_OBJ_W); - CASE(ZEND_FETCH_RW); - CASE(ZEND_FETCH_DIM_RW); - CASE(ZEND_FETCH_OBJ_RW); - CASE(ZEND_FETCH_IS); - CASE(ZEND_FETCH_DIM_IS); - CASE(ZEND_FETCH_OBJ_IS); - CASE(ZEND_FETCH_FUNC_ARG); - CASE(ZEND_FETCH_DIM_FUNC_ARG); - CASE(ZEND_FETCH_OBJ_FUNC_ARG); - CASE(ZEND_FETCH_UNSET); - CASE(ZEND_FETCH_DIM_UNSET); - CASE(ZEND_FETCH_OBJ_UNSET); - CASE(ZEND_FETCH_DIM_TMP_VAR); - CASE(ZEND_FETCH_CONSTANT); - CASE(ZEND_GOTO); - CASE(ZEND_EXT_STMT); - CASE(ZEND_EXT_FCALL_BEGIN); - CASE(ZEND_EXT_FCALL_END); - CASE(ZEND_EXT_NOP); - CASE(ZEND_TICKS); - CASE(ZEND_SEND_VAR_NO_REF); - CASE(ZEND_CATCH); - CASE(ZEND_THROW); - CASE(ZEND_FETCH_CLASS); - CASE(ZEND_CLONE); - CASE(ZEND_RETURN_BY_REF); - CASE(ZEND_INIT_METHOD_CALL); - CASE(ZEND_INIT_STATIC_METHOD_CALL); - CASE(ZEND_ISSET_ISEMPTY_VAR); - CASE(ZEND_ISSET_ISEMPTY_DIM_OBJ); - CASE(ZEND_PRE_INC_OBJ); - CASE(ZEND_PRE_DEC_OBJ); - CASE(ZEND_POST_INC_OBJ); - CASE(ZEND_POST_DEC_OBJ); - CASE(ZEND_ASSIGN_OBJ); - CASE(ZEND_INSTANCEOF); - CASE(ZEND_DECLARE_CLASS); - CASE(ZEND_DECLARE_INHERITED_CLASS); - CASE(ZEND_DECLARE_FUNCTION); - CASE(ZEND_RAISE_ABSTRACT_ERROR); - CASE(ZEND_DECLARE_CONST); - CASE(ZEND_ADD_INTERFACE); - CASE(ZEND_DECLARE_INHERITED_CLASS_DELAYED); - CASE(ZEND_VERIFY_ABSTRACT_CLASS); - CASE(ZEND_ASSIGN_DIM); - CASE(ZEND_ISSET_ISEMPTY_PROP_OBJ); - CASE(ZEND_HANDLE_EXCEPTION); - CASE(ZEND_USER_OPCODE); -#ifdef ZEND_JMP_SET - CASE(ZEND_JMP_SET); -#endif - CASE(ZEND_DECLARE_LAMBDA_FUNCTION); -#ifdef ZEND_ADD_TRAIT - CASE(ZEND_ADD_TRAIT); -#endif -#ifdef ZEND_BIND_TRAITS - CASE(ZEND_BIND_TRAITS); -#endif -#ifdef ZEND_SEPARATE - CASE(ZEND_SEPARATE); -#endif -#ifdef ZEND_QM_ASSIGN_VAR - CASE(ZEND_QM_ASSIGN_VAR); -#endif -#ifdef ZEND_JMP_SET_VAR - CASE(ZEND_JMP_SET_VAR); -#endif -#ifdef ZEND_DISCARD_EXCEPTION - CASE(ZEND_DISCARD_EXCEPTION); -#endif -#ifdef ZEND_YIELD - CASE(ZEND_YIELD); -#endif -#ifdef ZEND_GENERATOR_RETURN - CASE(ZEND_GENERATOR_RETURN); -#endif -#ifdef ZEND_FAST_CALL - CASE(ZEND_FAST_CALL); -#endif -#ifdef ZEND_FAST_RET - CASE(ZEND_FAST_RET); -#endif -#ifdef ZEND_RECV_VARIADIC - CASE(ZEND_RECV_VARIADIC); -#endif - CASE(ZEND_OP_DATA); - default: - return "UNKNOWN"; - } -#else - const char *ret = zend_get_opcode_name(opcode); - return ret?ret:"UNKNOWN"; -#endif + phpdbg_print_opline_ex(execute_data, ignore_flags); } /* }}} */ diff --git a/sapi/phpdbg/phpdbg_opcode.h b/sapi/phpdbg/phpdbg_opcode.h index 1afd81ad75..2831748236 100644 --- a/sapi/phpdbg/phpdbg_opcode.h +++ b/sapi/phpdbg/phpdbg_opcode.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -23,9 +23,24 @@ #include "zend_types.h" -const char *phpdbg_decode_opcode(zend_uchar); -char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op, HashTable *vars TSRMLS_DC); -void phpdbg_print_opline(zend_execute_data *execute_data, zend_bool ignore_flags TSRMLS_DC); -void phpdbg_print_opline_ex(zend_execute_data *execute_data, HashTable *vars, zend_bool ignore_flags TSRMLS_DC); +char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op); +void phpdbg_print_opline(zend_execute_data *execute_data, zend_bool ignore_flags); +void phpdbg_print_opline_ex(zend_execute_data *execute_data, zend_bool ignore_flags); + +typedef struct _phpdbg_oplog_entry phpdbg_oplog_entry; +struct _phpdbg_oplog_entry { + phpdbg_oplog_entry *next; + zend_string *function_name; + zend_class_entry *scope; + zend_string *filename; + zend_op *opcodes; + zend_op *op; +}; + +typedef struct _phpdbg_oplog_list phpdbg_oplog_list; +struct _phpdbg_oplog_list { + phpdbg_oplog_list *prev; + phpdbg_oplog_entry *start; +}; #endif /* PHPDBG_OPCODE_H */ diff --git a/sapi/phpdbg/phpdbg_out.c b/sapi/phpdbg/phpdbg_out.c new file mode 100644 index 0000000000..90940ca68c --- /dev/null +++ b/sapi/phpdbg/phpdbg_out.c @@ -0,0 +1,1321 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2016 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: Felipe Pena <felipe@php.net> | + | Authors: Joe Watkins <joe.watkins@live.co.uk> | + | Authors: Bob Weinand <bwoebi@php.net> | + +----------------------------------------------------------------------+ +*/ + +#include "zend.h" +#include "php.h" +#include "spprintf.h" +#include "phpdbg.h" +#include "phpdbg_io.h" +#include "phpdbg_eol.h" +#include "ext/standard/html.h" + +#ifdef _WIN32 +# include "win32/time.h" +#endif + +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) + +/* copied from php-src/main/snprintf.c and slightly modified */ +/* + * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions + * + * XXX: this is a magic number; do not decrease it + * Emax = 1023 + * NDIG = 320 + * NUM_BUF_SIZE >= strlen("-") + Emax + strlrn(".") + NDIG + strlen("E+1023") + 1; + */ +#define NUM_BUF_SIZE 2048 + +/* + * Descriptor for buffer area + */ +struct buf_area { + char *buf_end; + char *nextb; /* pointer to next byte to read/write */ +}; + +typedef struct buf_area buffy; + +/* + * The INS_CHAR macro inserts a character in the buffer and writes + * the buffer back to disk if necessary + * It uses the char pointers sp and bep: + * sp points to the next available character in the buffer + * bep points to the end-of-buffer+1 + * While using this macro, note that the nextb pointer is NOT updated. + * + * NOTE: Evaluation of the c argument should not have any side-effects + */ +#define INS_CHAR(c, sp, bep, cc) \ + { \ + if (sp < bep) \ + { \ + *sp++ = c; \ + } \ + cc++; \ + } + +#define NUM( c ) ( c - '0' ) + +#define STR_TO_DEC( str, num ) \ + num = NUM( *str++ ) ; \ + while ( isdigit((int)*str ) ) \ + { \ + num *= 10 ; \ + num += NUM( *str++ ) ; \ + } + +/* + * This macro does zero padding so that the precision + * requirement is satisfied. The padding is done by + * adding '0's to the left of the string that is going + * to be printed. + */ +#define FIX_PRECISION( adjust, precision, s, s_len ) \ + if ( adjust ) \ + while ( s_len < precision ) \ + { \ + *--s = '0' ; \ + s_len++ ; \ + } + +/* + * Macro that does padding. The padding is done by printing + * the character ch. + */ +#define PAD( width, len, ch ) do \ + { \ + INS_CHAR( ch, sp, bep, cc ) ; \ + width-- ; \ + } \ + while ( width > len ) + +/* + * Prefix the character ch to the string str + * Increase length + * Set the has_prefix flag + */ +#define PREFIX( str, length, ch ) *--str = ch ; length++ ; has_prefix = YES + + +#ifdef HAVE_LOCALE_H +#include <locale.h> +#define LCONV_DECIMAL_POINT (*lconv->decimal_point) +#else +#define LCONV_DECIMAL_POINT '.' +#endif +#define NUL '\0' +#define S_NULL "(null)" +#define S_NULL_LEN 6 +#define FLOAT_DIGITS 6 + +/* + * Do format conversion placing the output in buffer + */ +static int format_converter(register buffy *odp, const char *fmt, zend_bool escape_xml, va_list ap) { + char *sp; + char *bep; + int cc = 0; + int i; + + char *s = NULL, *free_s = NULL; + size_t s_len; + zend_bool free_zcopy; + zval *zvp, zcopy; + + int min_width = 0; + int precision = 0; + enum { + LEFT, RIGHT + } adjust; + char pad_char; + char prefix_char; + + double fp_num; + wide_int i_num = (wide_int) 0; + u_wide_int ui_num; + + char num_buf[NUM_BUF_SIZE]; + char char_buf[2]; /* for printing %% and %<unknown> */ + +#ifdef HAVE_LOCALE_H + struct lconv *lconv = NULL; +#endif + + /* + * Flag variables + */ + length_modifier_e modifier; + boolean_e alternate_form; + boolean_e print_sign; + boolean_e print_blank; + boolean_e adjust_precision; + boolean_e adjust_width; + bool_int is_negative; + + sp = odp->nextb; + bep = odp->buf_end; + + while (*fmt) { + if (*fmt != '%') { + INS_CHAR(*fmt, sp, bep, cc); + } else { + /* + * Default variable settings + */ + adjust = RIGHT; + alternate_form = print_sign = print_blank = NO; + pad_char = ' '; + prefix_char = NUL; + free_zcopy = 0; + + fmt++; + + /* + * Try to avoid checking for flags, width or precision + */ + if (isascii((int)*fmt) && !islower((int)*fmt)) { + /* + * Recognize flags: -, #, BLANK, + + */ + for (;; fmt++) { + if (*fmt == '-') + adjust = LEFT; + else if (*fmt == '+') + print_sign = YES; + else if (*fmt == '#') + alternate_form = YES; + else if (*fmt == ' ') + print_blank = YES; + else if (*fmt == '0') + pad_char = '0'; + else + break; + } + + /* + * Check if a width was specified + */ + if (isdigit((int)*fmt)) { + STR_TO_DEC(fmt, min_width); + adjust_width = YES; + } else if (*fmt == '*') { + min_width = va_arg(ap, int); + fmt++; + adjust_width = YES; + if (min_width < 0) { + adjust = LEFT; + min_width = -min_width; + } + } else + adjust_width = NO; + + /* + * Check if a precision was specified + */ + if (*fmt == '.') { + adjust_precision = YES; + fmt++; + if (isdigit((int)*fmt)) { + STR_TO_DEC(fmt, precision); + } else if (*fmt == '*') { + precision = va_arg(ap, int); + fmt++; + if (precision < 0) + precision = 0; + } else + precision = 0; + + if (precision > FORMAT_CONV_MAX_PRECISION && *fmt != 's' && *fmt != 'v' && *fmt != 'b') { + precision = FORMAT_CONV_MAX_PRECISION; + } + } else + adjust_precision = NO; + } else + adjust_precision = adjust_width = NO; + + /* + * Modifier check + */ + switch (*fmt) { + case 'L': + fmt++; + modifier = LM_LONG_DOUBLE; + break; + case 'I': + fmt++; +#if SIZEOF_LONG_LONG + if (*fmt == '6' && *(fmt+1) == '4') { + fmt += 2; + modifier = LM_LONG_LONG; + } else +#endif + if (*fmt == '3' && *(fmt+1) == '2') { + fmt += 2; + modifier = LM_LONG; + } else { +#ifdef _WIN64 + modifier = LM_LONG_LONG; +#else + modifier = LM_LONG; +#endif + } + break; + case 'l': + fmt++; +#if SIZEOF_LONG_LONG + if (*fmt == 'l') { + fmt++; + modifier = LM_LONG_LONG; + } else +#endif + modifier = LM_LONG; + break; + case 'z': + fmt++; + modifier = LM_SIZE_T; + break; + case 'j': + fmt++; +#if SIZEOF_INTMAX_T + modifier = LM_INTMAX_T; +#else + modifier = LM_SIZE_T; +#endif + break; + case 't': + fmt++; +#if SIZEOF_PTRDIFF_T + modifier = LM_PTRDIFF_T; +#else + modifier = LM_SIZE_T; +#endif + break; + case 'h': + fmt++; + if (*fmt == 'h') { + fmt++; + } + /* these are promoted to int, so no break */ + default: + modifier = LM_STD; + break; + } + + /* + * Argument extraction and printing. + * First we determine the argument type. + * Then, we convert the argument to a string. + * On exit from the switch, s points to the string that + * must be printed, s_len has the length of the string + * The precision requirements, if any, are reflected in s_len. + * + * NOTE: pad_char may be set to '0' because of the 0 flag. + * It is reset to ' ' by non-numeric formats + */ + switch (*fmt) { + case 'Z': + zvp = (zval *) va_arg(ap, zval *); + free_zcopy = zend_make_printable_zval(zvp, &zcopy); + if (free_zcopy) { + zvp = &zcopy; + } + s_len = Z_STRLEN_P(zvp); + s = Z_STRVAL_P(zvp); + if (adjust_precision && precision < s_len) { + s_len = precision; + } + break; + case 'u': + switch(modifier) { + default: + i_num = (wide_int) va_arg(ap, unsigned int); + break; + case LM_LONG_DOUBLE: + goto fmt_error; + case LM_LONG: + i_num = (wide_int) va_arg(ap, unsigned long int); + break; + case LM_SIZE_T: + i_num = (wide_int) va_arg(ap, size_t); + break; +#if SIZEOF_LONG_LONG + case LM_LONG_LONG: + i_num = (wide_int) va_arg(ap, u_wide_int); + break; +#endif +#if SIZEOF_INTMAX_T + case LM_INTMAX_T: + i_num = (wide_int) va_arg(ap, uintmax_t); + break; +#endif +#if SIZEOF_PTRDIFF_T + case LM_PTRDIFF_T: + i_num = (wide_int) va_arg(ap, ptrdiff_t); + break; +#endif + } + /* + * The rest also applies to other integer formats, so fall + * into that case. + */ + case 'd': + case 'i': + /* + * Get the arg if we haven't already. + */ + if ((*fmt) != 'u') { + switch(modifier) { + default: + i_num = (wide_int) va_arg(ap, int); + break; + case LM_LONG_DOUBLE: + goto fmt_error; + case LM_LONG: + i_num = (wide_int) va_arg(ap, long int); + break; + case LM_SIZE_T: +#if SIZEOF_SSIZE_T + i_num = (wide_int) va_arg(ap, ssize_t); +#else + i_num = (wide_int) va_arg(ap, size_t); +#endif + break; +#if SIZEOF_LONG_LONG + case LM_LONG_LONG: + i_num = (wide_int) va_arg(ap, wide_int); + break; +#endif +#if SIZEOF_INTMAX_T + case LM_INTMAX_T: + i_num = (wide_int) va_arg(ap, intmax_t); + break; +#endif +#if SIZEOF_PTRDIFF_T + case LM_PTRDIFF_T: + i_num = (wide_int) va_arg(ap, ptrdiff_t); + break; +#endif + } + } + s = ap_php_conv_10(i_num, (*fmt) == 'u', &is_negative, + &num_buf[NUM_BUF_SIZE], &s_len); + FIX_PRECISION(adjust_precision, precision, s, s_len); + + if (*fmt != 'u') { + if (is_negative) { + prefix_char = '-'; + } else if (print_sign) { + prefix_char = '+'; + } else if (print_blank) { + prefix_char = ' '; + } + } + break; + + + case 'o': + switch(modifier) { + default: + ui_num = (u_wide_int) va_arg(ap, unsigned int); + break; + case LM_LONG_DOUBLE: + goto fmt_error; + case LM_LONG: + ui_num = (u_wide_int) va_arg(ap, unsigned long int); + break; + case LM_SIZE_T: + ui_num = (u_wide_int) va_arg(ap, size_t); + break; +#if SIZEOF_LONG_LONG + case LM_LONG_LONG: + ui_num = (u_wide_int) va_arg(ap, u_wide_int); + break; +#endif +#if SIZEOF_INTMAX_T + case LM_INTMAX_T: + ui_num = (u_wide_int) va_arg(ap, uintmax_t); + break; +#endif +#if SIZEOF_PTRDIFF_T + case LM_PTRDIFF_T: + ui_num = (u_wide_int) va_arg(ap, ptrdiff_t); + break; +#endif + } + s = ap_php_conv_p2(ui_num, 3, *fmt, &num_buf[NUM_BUF_SIZE], &s_len); + FIX_PRECISION(adjust_precision, precision, s, s_len); + if (alternate_form && *s != '0') { + *--s = '0'; + s_len++; + } + break; + + + case 'x': + case 'X': + switch(modifier) { + default: + ui_num = (u_wide_int) va_arg(ap, unsigned int); + break; + case LM_LONG_DOUBLE: + goto fmt_error; + case LM_LONG: + ui_num = (u_wide_int) va_arg(ap, unsigned long int); + break; + case LM_SIZE_T: + ui_num = (u_wide_int) va_arg(ap, size_t); + break; +#if SIZEOF_LONG_LONG + case LM_LONG_LONG: + ui_num = (u_wide_int) va_arg(ap, u_wide_int); + break; +#endif +#if SIZEOF_INTMAX_T + case LM_INTMAX_T: + ui_num = (u_wide_int) va_arg(ap, uintmax_t); + break; +#endif +#if SIZEOF_PTRDIFF_T + case LM_PTRDIFF_T: + ui_num = (u_wide_int) va_arg(ap, ptrdiff_t); + break; +#endif + } + s = ap_php_conv_p2(ui_num, 4, *fmt, &num_buf[NUM_BUF_SIZE], &s_len); + FIX_PRECISION(adjust_precision, precision, s, s_len); + if (alternate_form && i_num != 0) { + *--s = *fmt; /* 'x' or 'X' */ + *--s = '0'; + s_len += 2; + } + break; + + + case 's': + case 'v': + s = va_arg(ap, char *); + if (s != NULL) { + if (adjust_precision) { + s_len = precision; + } else { + s_len = strlen(s); + } + + if (escape_xml) { + /* added: support for xml escaping */ + + int old_slen = s_len, i = 0; + char *old_s = s, *s_ptr; + free_s = s_ptr = s = emalloc(old_slen * 6 + 1); + do { + if (old_s[i] == '&' || old_s[i] == '"' || old_s[i] == '<') { + *s_ptr++ = '&'; + switch (old_s[i]) { + case '"': + s_len += 5; + *s_ptr++ = 'q'; + *s_ptr++ = 'u'; + *s_ptr++ = 'o'; + *s_ptr++ = 't'; + break; + case '<': + s_len += 3; + *s_ptr++ = 'l'; + *s_ptr++ = 't'; + break; + case '&': + s_len += 4; + *s_ptr++ = 'a'; + *s_ptr++ = 'm'; + *s_ptr++ = 'p'; + break; + } + *s_ptr++ = ';'; + } else { + *s_ptr++ = old_s[i]; + } + } while (i++ < old_slen); + } + } else { + s = S_NULL; + s_len = S_NULL_LEN; + } + pad_char = ' '; + break; + + + case 'b': + if (escape_xml) { + s = PHPDBG_G(err_buf).xml; + } else { + s = PHPDBG_G(err_buf).msg; + } + + if (s != NULL) { + if (escape_xml) { + s_len = PHPDBG_G(err_buf).xmllen; + } else { + s_len = PHPDBG_G(err_buf).msglen; + } + + if (adjust_precision && precision != s_len) { + s_len = precision; + } + } else { + s = ""; + s_len = 0; + } + pad_char = ' '; + break; + + + case 'r': + if (PHPDBG_G(req_id)) { + s_len = spprintf(&s, 0, "req=\"%lu\"", PHPDBG_G(req_id)); + free_s = s; + } else { + s = ""; + s_len = 0; + } + break; + + + case 'f': + case 'F': + case 'e': + case 'E': + + switch(modifier) { + case LM_LONG_DOUBLE: + fp_num = (double) va_arg(ap, long double); + break; + case LM_STD: + fp_num = va_arg(ap, double); + break; + default: + goto fmt_error; + } + + if (zend_isnan(fp_num)) { + s = "NAN"; + s_len = 3; + } else if (zend_isinf(fp_num)) { + s = "INF"; + s_len = 3; + } else { +#ifdef HAVE_LOCALE_H + if (!lconv) { + lconv = localeconv(); + } +#endif + s = php_conv_fp((*fmt == 'f')?'F':*fmt, fp_num, alternate_form, + (adjust_precision == NO) ? FLOAT_DIGITS : precision, + (*fmt == 'f')?LCONV_DECIMAL_POINT:'.', + &is_negative, &num_buf[1], &s_len); + if (is_negative) + prefix_char = '-'; + else if (print_sign) + prefix_char = '+'; + else if (print_blank) + prefix_char = ' '; + } + break; + + + case 'g': + case 'k': + case 'G': + case 'H': + switch(modifier) { + case LM_LONG_DOUBLE: + fp_num = (double) va_arg(ap, long double); + break; + case LM_STD: + fp_num = va_arg(ap, double); + break; + default: + goto fmt_error; + } + + if (zend_isnan(fp_num)) { + s = "NAN"; + s_len = 3; + break; + } else if (zend_isinf(fp_num)) { + if (fp_num > 0) { + s = "INF"; + s_len = 3; + } else { + s = "-INF"; + s_len = 4; + } + break; + } + + if (adjust_precision == NO) { + precision = FLOAT_DIGITS; + } else if (precision == 0) { + precision = 1; + } + /* + * * We use &num_buf[ 1 ], so that we have room for the sign + */ +#ifdef HAVE_LOCALE_H + if (!lconv) { + lconv = localeconv(); + } +#endif + s = php_gcvt(fp_num, precision, (*fmt=='H' || *fmt == 'k') ? '.' : LCONV_DECIMAL_POINT, (*fmt == 'G' || *fmt == 'H')?'E':'e', &num_buf[1]); + if (*s == '-') { + prefix_char = *s++; + } else if (print_sign) { + prefix_char = '+'; + } else if (print_blank) { + prefix_char = ' '; + } + + s_len = strlen(s); + + if (alternate_form && (strchr(s, '.')) == NULL) { + s[s_len++] = '.'; + } + break; + + + case 'c': + char_buf[0] = (char) (va_arg(ap, int)); + s = &char_buf[0]; + s_len = 1; + pad_char = ' '; + break; + + + case '%': + char_buf[0] = '%'; + s = &char_buf[0]; + s_len = 1; + pad_char = ' '; + break; + + + case 'n': + *(va_arg(ap, int *)) = cc; + goto skip_output; + + /* + * Always extract the argument as a "char *" pointer. We + * should be using "void *" but there are still machines + * that don't understand it. + * If the pointer size is equal to the size of an unsigned + * integer we convert the pointer to a hex number, otherwise + * we print "%p" to indicate that we don't handle "%p". + */ + case 'p': + if (sizeof(char *) <= sizeof(u_wide_int)) { + ui_num = (u_wide_int)((size_t) va_arg(ap, char *)); + s = ap_php_conv_p2(ui_num, 4, 'x', + &num_buf[NUM_BUF_SIZE], &s_len); + if (ui_num != 0) { + *--s = 'x'; + *--s = '0'; + s_len += 2; + } + } else { + s = "%p"; + s_len = 2; + } + pad_char = ' '; + break; + + + case NUL: + /* + * The last character of the format string was %. + * We ignore it. + */ + continue; + + +fmt_error: + php_error(E_ERROR, "Illegal length modifier specified '%c' in s[np]printf call", *fmt); + /* + * The default case is for unrecognized %'s. + * We print %<char> to help the user identify what + * option is not understood. + * This is also useful in case the user wants to pass + * the output of format_converter to another function + * that understands some other %<char> (like syslog). + * Note that we can't point s inside fmt because the + * unknown <char> could be preceded by width etc. + */ + default: + char_buf[0] = '%'; + char_buf[1] = *fmt; + s = char_buf; + s_len = 2; + pad_char = ' '; + break; + } + + if (prefix_char != NUL) { + *--s = prefix_char; + s_len++; + } + if (adjust_width && adjust == RIGHT && min_width > s_len) { + if (pad_char == '0' && prefix_char != NUL) { + INS_CHAR(*s, sp, bep, cc) + s++; + s_len--; + min_width--; + } + PAD(min_width, s_len, pad_char); + } + /* + * Print the string s. + */ + for (i = s_len; i != 0; i--) { + INS_CHAR(*s, sp, bep, cc); + s++; + } + + if (adjust_width && adjust == LEFT && min_width > s_len) + PAD(min_width, s_len, pad_char); + if (free_zcopy) { + zval_dtor(&zcopy); + } + } +skip_output: + if (free_s) { + efree(free_s); + free_s = NULL; + } + + fmt++; + } + odp->nextb = sp; + return (cc); +} + +static void strx_printv(int *ccp, char *buf, size_t len, const char *format, zend_bool escape_xml, va_list ap) { + buffy od; + int cc; + + /* + * First initialize the descriptor + * Notice that if no length is given, we initialize buf_end to the + * highest possible address. + */ + if (len == 0) { + od.buf_end = (char *) ~0; + od.nextb = (char *) ~0; + } else { + od.buf_end = &buf[len-1]; + od.nextb = buf; + } + + /* + * Do the conversion + */ + cc = format_converter(&od, format, escape_xml, ap); + if (len != 0 && od.nextb <= od.buf_end) { + *(od.nextb) = '\0'; + } + if (ccp) { + *ccp = cc; + } +} + +static int phpdbg_xml_vsnprintf(char *buf, size_t len, const char *format, zend_bool escape_xml, va_list ap) { + int cc; + + strx_printv(&cc, buf, len, format, escape_xml, ap); + return (cc); +} + +PHPDBG_API int phpdbg_xml_vasprintf(char **buf, const char *format, zend_bool escape_xml, va_list ap) { + va_list ap2; + int cc; + + va_copy(ap2, ap); + cc = phpdbg_xml_vsnprintf(NULL, 0, format, escape_xml, ap2); + va_end(ap2); + + *buf = NULL; + + if (cc >= 0) { + if ((*buf = emalloc(++cc)) != NULL) { + if ((cc = phpdbg_xml_vsnprintf(*buf, cc, format, escape_xml, ap)) < 0) { + efree(*buf); + *buf = NULL; + } + } + } + + return cc; +} +/* copy end */ + +PHPDBG_API int _phpdbg_xml_asprintf(char **buf, const char *format, zend_bool escape_xml, ...) { + int ret; + va_list va; + + va_start(va, escape_xml); + ret = phpdbg_xml_vasprintf(buf, format, escape_xml, va); + va_end(va); + + return ret; +} + +PHPDBG_API int _phpdbg_asprintf(char **buf, const char *format, ...) { + int ret; + va_list va; + + va_start(va, format); + ret = phpdbg_xml_vasprintf(buf, format, 0, va); + va_end(va); + + return ret; +} + +static int phpdbg_encode_xml(char **buf, char *msg, int msglen, int from, char *to) { + int i; + int tolen = to ? strlen(to) : 5; + char *tmp = *buf = emalloc(msglen * tolen); + for (i = 0; i++ < msglen; msg++) { + if (*msg == '&') { + memcpy(tmp, ZEND_STRL("&")); + tmp += sizeof("&") - 1; + } else if (*msg == '<') { + memcpy(tmp, ZEND_STRL("<")); + tmp += sizeof("<") - 1; + } else if (((int) *msg) == from) { + memcpy(tmp, to, tolen); + tmp += tolen; + } else { + *tmp++ = *msg; + } + } + + { + int len = tmp - *buf; + *buf = erealloc(*buf, len + 1); + return len; + } +} + +static void phpdbg_encode_ctrl_chars(char **buf, int *buflen) { + char *tmp, *tmpptr; + int len; + int i; + + tmp = tmpptr = emalloc(*buflen * 5); + + for (i = 0; i < *buflen; i++) { + if ((*buf)[i] < 0x20) { + *tmpptr++ = '&'; + *tmpptr++ = '#'; + if ((unsigned int) ((*buf)[i]) > 9) { + *tmpptr++ = ((*buf)[i] / 10) + '0'; + } + *tmpptr++ = ((*buf)[i] % 10) + '0'; + *tmpptr++ = ';'; + } else { + *tmpptr++ = (*buf)[i]; + } + } + + len = tmpptr - tmp; + + efree(*buf); + *buf = erealloc(tmp, len + 1); + *buflen = len; +} + +static int phpdbg_process_print(int fd, int type, const char *tag, const char *msg, int msglen, const char *xml, int xmllen) { + char *msgout = NULL, *buf; + int msgoutlen, xmloutlen, buflen; + const char *severity; + + if ((PHPDBG_G(flags) & PHPDBG_WRITE_XML) && PHPDBG_G(in_script_xml) && PHPDBG_G(in_script_xml) != type) { + phpdbg_mixed_write(fd, ZEND_STRL("</stream>")); + PHPDBG_G(in_script_xml) = 0; + } + + switch (type) { + case P_ERROR: + severity = "error"; + if (!PHPDBG_G(last_was_newline)) { + if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) { + phpdbg_mixed_write(fd, ZEND_STRL("<phpdbg>\n" "</phpdbg>")); + } else { + phpdbg_mixed_write(fd, ZEND_STRL("\n")); + } + PHPDBG_G(last_was_newline) = 1; + } + if (PHPDBG_G(flags) & PHPDBG_IS_COLOURED) { + msgoutlen = phpdbg_asprintf(&msgout, "\033[%sm[%.*s]\033[0m\n", PHPDBG_G(colors)[PHPDBG_COLOR_ERROR]->code, msglen, msg); + } else { + msgoutlen = phpdbg_asprintf(&msgout, "[%.*s]\n", msglen, msg); + } + break; + + case P_NOTICE: + severity = "notice"; + if (!PHPDBG_G(last_was_newline)) { + if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) { + phpdbg_mixed_write(fd, ZEND_STRL("<phpdbg>\n" "</phpdbg>")); + } else { + phpdbg_mixed_write(fd, ZEND_STRL("\n")); + } + PHPDBG_G(last_was_newline) = 1; + } + if (PHPDBG_G(flags) & PHPDBG_IS_COLOURED) { + msgoutlen = phpdbg_asprintf(&msgout, "\033[%sm[%.*s]\033[0m\n", PHPDBG_G(colors)[PHPDBG_COLOR_NOTICE]->code, msglen, msg); + } else { + msgoutlen = phpdbg_asprintf(&msgout, "[%.*s]\n", msglen, msg); + } + break; + + case P_WRITELN: + severity = "normal"; + if (msg) { + msgoutlen = phpdbg_asprintf(&msgout, "%.*s\n", msglen, msg); + } else { + msgoutlen = 1; + msgout = estrdup("\n"); + } + PHPDBG_G(last_was_newline) = 1; + break; + + case P_WRITE: + severity = "normal"; + if (msg) { + msgout = estrndup(msg, msglen); + msgoutlen = msglen; + PHPDBG_G(last_was_newline) = msg[msglen - 1] == '\n'; + } else { + msgoutlen = 0; + msgout = estrdup(""); + } + break; + + case P_STDOUT: + case P_STDERR: + if (msg) { + PHPDBG_G(last_was_newline) = msg[msglen - 1] == '\n'; + if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) { + zend_string *encoded; + + if (PHPDBG_G(in_script_xml) != type) { + char *stream_buf; + int stream_buflen = phpdbg_asprintf(&stream_buf, "<stream type=\"%s\">", type == P_STDERR ? "stderr" : "stdout"); + phpdbg_mixed_write(fd, stream_buf, stream_buflen); + efree(stream_buf); + PHPDBG_G(in_script_xml) = type; + } + encoded = php_escape_html_entities((unsigned char *) msg, msglen, 0, ENT_NOQUOTES, PG(internal_encoding) && PG(internal_encoding)[0] ? PG(internal_encoding) : (SG(default_charset) ? SG(default_charset) : "UTF-8")); + buflen = ZSTR_LEN(encoded); + memcpy(buf = emalloc(buflen + 1), ZSTR_VAL(encoded), buflen); + phpdbg_encode_ctrl_chars(&buf, &buflen); + phpdbg_mixed_write(fd, buf, buflen); + efree(buf); + } else { + phpdbg_mixed_write(fd, msg, msglen); + } + return msglen; + } + break; + + /* no formatting on logging output */ + case P_LOG: + severity = "log"; + if (msg) { + struct timeval tp; + if (gettimeofday(&tp, NULL) == SUCCESS) { + msgoutlen = phpdbg_asprintf(&msgout, "[%ld %.8F]: %.*s\n", tp.tv_sec, tp.tv_usec / 1000000., msglen, msg); + } else { + msgoutlen = FAILURE; + } + } + break; + } + + if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) { + char *xmlout; + + if (PHPDBG_G(req_id)) { + char *xmlbuf = NULL; + xmllen = phpdbg_asprintf(&xmlbuf, "req=\"%lu\" %.*s", PHPDBG_G(req_id), xmllen, xml); + xml = xmlbuf; + } + if (msgout) { + buflen = phpdbg_encode_xml(&buf, msgout, msgoutlen, '"', """); + xmloutlen = phpdbg_asprintf(&xmlout, "<%s severity=\"%s\" %.*s msgout=\"%.*s\" />", tag, severity, xmllen, xml, buflen, buf); + + efree(buf); + } else { + xmloutlen = phpdbg_asprintf(&xmlout, "<%s severity=\"%s\" %.*s msgout=\"\" />", tag, severity, xmllen, xml); + } + + phpdbg_encode_ctrl_chars(&xmlout, &xmloutlen); + phpdbg_eol_convert(&xmlout, &xmloutlen); + phpdbg_mixed_write(fd, xmlout, xmloutlen); + efree(xmlout); + } else if (msgout) { + phpdbg_eol_convert(&msgout, &msgoutlen); + phpdbg_mixed_write(fd, msgout, msgoutlen); + } + + if (PHPDBG_G(req_id) && (PHPDBG_G(flags) & PHPDBG_WRITE_XML)) { + efree((char *) xml); + } + + if (msgout) { + efree(msgout); + } + + return msgout ? msgoutlen : xmloutlen; +} /* }}} */ + +PHPDBG_API int phpdbg_vprint(int type, int fd, const char *tag, const char *xmlfmt, const char *strfmt, va_list args) { + char *msg = NULL, *xml = NULL; + int msglen = 0, xmllen = 0; + int len; + va_list argcpy; + + if (strfmt != NULL && strlen(strfmt) > 0L) { + va_copy(argcpy, args); + msglen = phpdbg_xml_vasprintf(&msg, strfmt, 0, argcpy); + va_end(argcpy); + } + + if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) { + if (xmlfmt != NULL && strlen(xmlfmt) > 0L) { + va_copy(argcpy, args); + xmllen = phpdbg_xml_vasprintf(&xml, xmlfmt, 1, argcpy); + va_end(argcpy); + } else { + xml = estrdup(""); + } + } + + if (PHPDBG_G(err_buf).active && type != P_STDOUT && type != P_STDERR) { + phpdbg_free_err_buf(); + + PHPDBG_G(err_buf).type = type; + PHPDBG_G(err_buf).fd = fd; + PHPDBG_G(err_buf).tag = estrdup(tag); + PHPDBG_G(err_buf).msg = msg; + PHPDBG_G(err_buf).msglen = msglen; + if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) { + PHPDBG_G(err_buf).xml = xml; + PHPDBG_G(err_buf).xmllen = xmllen; + } + + return msglen; + } + + len = phpdbg_process_print(fd, type, tag, msg, msglen, xml, xmllen); + + if (msg) { + efree(msg); + } + + if (xml) { + efree(xml); + } + + return len; +} + +PHPDBG_API void phpdbg_free_err_buf(void) { + if (PHPDBG_G(err_buf).type == 0) { + return; + } + + PHPDBG_G(err_buf).type = 0; + + efree(PHPDBG_G(err_buf).tag); + efree(PHPDBG_G(err_buf).msg); + if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) { + efree(PHPDBG_G(err_buf).xml); + } +} + +PHPDBG_API void phpdbg_activate_err_buf(zend_bool active) { + PHPDBG_G(err_buf).active = active; +} + +PHPDBG_API int phpdbg_output_err_buf(const char *tag, const char *xmlfmt, const char *strfmt, ...) { + int len; + va_list args; + int errbuf_active = PHPDBG_G(err_buf).active; + + if (PHPDBG_G(flags) & PHPDBG_DISCARD_OUTPUT) { + return 0; + } + + PHPDBG_G(err_buf).active = 0; + + va_start(args, strfmt); + len = phpdbg_vprint(PHPDBG_G(err_buf).type, PHPDBG_G(err_buf).fd, tag ? tag : PHPDBG_G(err_buf).tag, xmlfmt, strfmt, args); + va_end(args); + + PHPDBG_G(err_buf).active = errbuf_active; + phpdbg_free_err_buf(); + + return len; +} + +PHPDBG_API int phpdbg_print(int type, int fd, const char *tag, const char *xmlfmt, const char *strfmt, ...) { + va_list args; + int len; + + if (PHPDBG_G(flags) & PHPDBG_DISCARD_OUTPUT) { + return 0; + } + + va_start(args, strfmt); + len = phpdbg_vprint(type, fd, tag, xmlfmt, strfmt, args); + va_end(args); + + return len; +} + +PHPDBG_API int phpdbg_xml_internal(int fd, const char *fmt, ...) { + int len = 0; + + if (PHPDBG_G(flags) & PHPDBG_DISCARD_OUTPUT) { + return 0; + } + + if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) { + va_list args; + char *buffer; + int buflen; + + va_start(args, fmt); + buflen = phpdbg_xml_vasprintf(&buffer, fmt, 1, args); + va_end(args); + + phpdbg_encode_ctrl_chars(&buffer, &buflen); + + if (PHPDBG_G(in_script_xml)) { + phpdbg_mixed_write(fd, ZEND_STRL("</stream>")); + PHPDBG_G(in_script_xml) = 0; + } + + len = phpdbg_mixed_write(fd, buffer, buflen); + efree(buffer); + } + + return len; +} + +PHPDBG_API int phpdbg_log_internal(int fd, const char *fmt, ...) { + va_list args; + char *buffer; + int buflen; + int len = 0; + + va_start(args, fmt); + buflen = phpdbg_xml_vasprintf(&buffer, fmt, 0, args); + va_end(args); + + len = phpdbg_mixed_write(fd, buffer, buflen); + efree(buffer); + + return len; +} + +PHPDBG_API int phpdbg_out_internal(int fd, const char *fmt, ...) { + va_list args; + char *buffer; + int buflen; + int len = 0; + + if (PHPDBG_G(flags) & PHPDBG_DISCARD_OUTPUT) { + return 0; + } + + va_start(args, fmt); + buflen = phpdbg_xml_vasprintf(&buffer, fmt, 0, args); + va_end(args); + + if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) { + char *msg; + int msglen; + + msglen = phpdbg_encode_xml(&msg, buffer, buflen, 256, NULL); + phpdbg_encode_ctrl_chars(&msg, &msglen); + phpdbg_eol_convert(&msg, &msglen); + + if (PHPDBG_G(in_script_xml)) { + phpdbg_mixed_write(fd, ZEND_STRL("</stream>")); + PHPDBG_G(in_script_xml) = 0; + } + + phpdbg_mixed_write(fd, ZEND_STRL("<phpdbg>")); + len = phpdbg_mixed_write(fd, msg, msglen); + phpdbg_mixed_write(fd, ZEND_STRL("</phpdbg>")); + } else { + phpdbg_eol_convert(&buffer, &buflen); + len = phpdbg_mixed_write(fd, buffer, buflen); + } + + efree(buffer); + return len; +} + + +PHPDBG_API int phpdbg_rlog_internal(int fd, const char *fmt, ...) { /* {{{ */ + int rc = 0; + + va_list args; + struct timeval tp; + + va_start(args, fmt); + if (gettimeofday(&tp, NULL) == SUCCESS) { + char friendly[100]; + char *format = NULL, *buffer = NULL, *outbuf = NULL; + const time_t tt = tp.tv_sec; + +#ifdef PHP_WIN32 + strftime(friendly, 100, "%a %b %d %H.%%04d %Y", localtime(&tt)); +#else + strftime(friendly, 100, "%a %b %d %T.%%04d %Y", localtime(&tt)); +#endif + phpdbg_asprintf(&buffer, friendly, tp.tv_usec/1000); + phpdbg_asprintf(&format, "[%s]: %s\n", buffer, fmt); + rc = phpdbg_xml_vasprintf(&outbuf, format, 0, args); + + if (outbuf) { + rc = phpdbg_mixed_write(fd, outbuf, rc); + efree(outbuf); + } + + efree(format); + efree(buffer); + } + va_end(args); + + return rc; +} /* }}} */ diff --git a/sapi/phpdbg/phpdbg_out.h b/sapi/phpdbg/phpdbg_out.h new file mode 100644 index 0000000000..a6f28da14d --- /dev/null +++ b/sapi/phpdbg/phpdbg_out.h @@ -0,0 +1,84 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2016 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: Felipe Pena <felipe@php.net> | + | Authors: Joe Watkins <joe.watkins@live.co.uk> | + | Authors: Bob Weinand <bwoebi@php.net> | + +----------------------------------------------------------------------+ +*/ + +#ifndef PHPDBG_OUT_H +#define PHPDBG_OUT_H + +/** + * Error/notice/formatting helpers + */ +enum { + P_ERROR = 1, + P_NOTICE, + P_WRITELN, + P_WRITE, + P_STDOUT, + P_STDERR, + P_LOG +}; + +PHPDBG_API int phpdbg_print(int severity, int fd, const char *tag, const char *xmlfmt, const char *strfmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 5, 6); +PHPDBG_API int phpdbg_xml_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3); +PHPDBG_API int phpdbg_log_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3); +PHPDBG_API int phpdbg_out_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3); +PHPDBG_API int phpdbg_rlog_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3); + +#define phpdbg_error(tag, xmlfmt, strfmt, ...) phpdbg_print(P_ERROR , PHPDBG_G(io)[PHPDBG_STDOUT].fd, tag, xmlfmt, strfmt, ##__VA_ARGS__) +#define phpdbg_notice(tag, xmlfmt, strfmt, ...) phpdbg_print(P_NOTICE , PHPDBG_G(io)[PHPDBG_STDOUT].fd, tag, xmlfmt, strfmt, ##__VA_ARGS__) +#define phpdbg_writeln(tag, xmlfmt, strfmt, ...) phpdbg_print(P_WRITELN, PHPDBG_G(io)[PHPDBG_STDOUT].fd, tag, xmlfmt, strfmt, ##__VA_ARGS__) +#define phpdbg_write(tag, xmlfmt, strfmt, ...) phpdbg_print(P_WRITE , PHPDBG_G(io)[PHPDBG_STDOUT].fd, tag, xmlfmt, strfmt, ##__VA_ARGS__) +#define phpdbg_script(type, fmt, ...) phpdbg_print(type , PHPDBG_G(io)[PHPDBG_STDOUT].fd, NULL, NULL, fmt, ##__VA_ARGS__) +#define phpdbg_log(fmt, ...) phpdbg_log_internal(PHPDBG_G(io)[PHPDBG_STDOUT].fd, fmt, ##__VA_ARGS__) +#define phpdbg_xml(fmt, ...) phpdbg_xml_internal(PHPDBG_G(io)[PHPDBG_STDOUT].fd, fmt, ##__VA_ARGS__) +#define phpdbg_out(fmt, ...) phpdbg_out_internal(PHPDBG_G(io)[PHPDBG_STDOUT].fd, fmt, ##__VA_ARGS__) + +#define phpdbg_error_ex(out, tag, xmlfmt, strfmt, ...) phpdbg_print(P_ERROR , out, tag, xmlfmt, strfmt, ##__VA_ARGS__) +#define phpdbg_notice_ex(out, tag, xmlfmt, strfmt, ...) phpdbg_print(P_NOTICE , out, tag, xmlfmt, strfmt, ##__VA_ARGS__) +#define phpdbg_writeln_ex(out, tag, xmlfmt, strfmt, ...) phpdbg_print(P_WRITELN, out, tag, xmlfmt, strfmt, ##__VA_ARGS__) +#define phpdbg_write_ex(out, tag, xmlfmt, strfmt, ...) phpdbg_print(P_WRITE , out, tag, xmlfmt, strfmt, ##__VA_ARGS__) +#define phpdbg_script_ex(out, type, fmt, ...) phpdbg_print(type , out, NULL, NULL, fmt, ##__VA_ARGS__) +#define phpdbg_log_ex(out, fmt, ...) phpdbg_log_internal(out, fmt, ##__VA_ARGS__) +#define phpdbg_xml_ex(out, fmt, ...) phpdbg_xml_internal(out, fmt, ##__VA_ARGS__) +#define phpdbg_out_ex(out, fmt, ...) phpdbg_out_internal(out, fmt, ##__VA_ARGS__) + +#define phpdbg_rlog(fd, fmt, ...) phpdbg_rlog_internal(fd, fmt, ##__VA_ARGS__) + +#define phpdbg_xml_asprintf(buf, ...) _phpdbg_xml_asprintf(buf, ##__VA_ARGS__) +PHPDBG_API int _phpdbg_xml_asprintf(char **buf, const char *format, zend_bool escape_xml, ...); + +#define phpdbg_asprintf(buf, ...) _phpdbg_asprintf(buf, ##__VA_ARGS__) +PHPDBG_API int _phpdbg_asprintf(char **buf, const char *format, ...); + + +#if PHPDBG_DEBUG +# define phpdbg_debug(fmt, ...) phpdbg_log_ex(PHPDBG_G(io)[PHPDBG_STDERR].fd, fmt, ##__VA_ARGS__) +#else +# define phpdbg_debug(fmt, ...) +#endif + +PHPDBG_API void phpdbg_free_err_buf(void); +PHPDBG_API void phpdbg_activate_err_buf(zend_bool active); +PHPDBG_API int phpdbg_output_err_buf(const char *tag, const char *xmlfmt, const char *strfmt, ...); + + +/* {{{ For separation */ +#define SEPARATE "------------------------------------------------" /* }}} */ + +#endif /* PHPDBG_OUT_H */ diff --git a/sapi/phpdbg/phpdbg_parser.c b/sapi/phpdbg/phpdbg_parser.c index 5537dfd330..c5222a0289 100644 --- a/sapi/phpdbg/phpdbg_parser.c +++ b/sapi/phpdbg/phpdbg_parser.c @@ -72,14 +72,14 @@ /* Line 371 of yacc.c */ #line 1 "sapi/phpdbg/phpdbg_parser.y" - + /* * phpdbg_parser.y * (from php-src root) * flex sapi/phpdbg/dev/phpdbg_lexer.l * bison sapi/phpdbg/dev/phpdbg_parser.y */ - + #include "phpdbg.h" #include "phpdbg_cmd.h" #include "phpdbg_utils.h" @@ -92,13 +92,18 @@ #include "phpdbg_lexer.h" #undef yyerror -static int yyerror(void ***tsrm_ls, const char *msg); +static int yyerror(const char *msg); + +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) -ZEND_EXTERN_MODULE_GLOBALS(phpdbg); +#ifdef _MSC_VER +#define YYMALLOC malloc +#define YYFREE free +#endif /* Line 371 of yacc.c */ -#line 102 "sapi/phpdbg/phpdbg_parser.c" +#line 107 "sapi/phpdbg/phpdbg_parser.c" # ifndef YY_NULL # if defined __cplusplus && 201103L <= __cplusplus @@ -129,7 +134,7 @@ extern int phpdbg_debug; #endif /* "%code requires" blocks. */ /* Line 387 of yacc.c */ -#line 31 "sapi/phpdbg/phpdbg_parser.y" +#line 36 "sapi/phpdbg/phpdbg_parser.y" #include "phpdbg.h" #ifndef YY_TYPEDEF_YY_SCANNER_T @@ -139,7 +144,7 @@ typedef void* yyscan_t; /* Line 387 of yacc.c */ -#line 143 "sapi/phpdbg/phpdbg_parser.c" +#line 148 "sapi/phpdbg/phpdbg_parser.c" /* Tokens. */ #ifndef YYTOKENTYPE @@ -157,14 +162,16 @@ typedef void* yyscan_t; T_COLON = 265, T_DCOLON = 266, T_POUND = 267, - T_PROTO = 268, - T_DIGITS = 269, - T_LITERAL = 270, - T_ADDR = 271, - T_OPCODE = 272, - T_ID = 273, - T_INPUT = 274, - T_UNEXPECTED = 275 + T_SEPARATOR = 268, + T_PROTO = 269, + T_DIGITS = 270, + T_LITERAL = 271, + T_ADDR = 272, + T_OPCODE = 273, + T_ID = 274, + T_INPUT = 275, + T_UNEXPECTED = 276, + T_REQ_ID = 277 }; #endif /* Tokens. */ @@ -178,14 +185,16 @@ typedef void* yyscan_t; #define T_COLON 265 #define T_DCOLON 266 #define T_POUND 267 -#define T_PROTO 268 -#define T_DIGITS 269 -#define T_LITERAL 270 -#define T_ADDR 271 -#define T_OPCODE 272 -#define T_ID 273 -#define T_INPUT 274 -#define T_UNEXPECTED 275 +#define T_SEPARATOR 268 +#define T_PROTO 269 +#define T_DIGITS 270 +#define T_LITERAL 271 +#define T_ADDR 272 +#define T_OPCODE 273 +#define T_ID 274 +#define T_INPUT 275 +#define T_UNEXPECTED 276 +#define T_REQ_ID 277 @@ -205,7 +214,7 @@ int phpdbg_parse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus -int phpdbg_parse (void *tsrm_ls); +int phpdbg_parse (void); #else int phpdbg_parse (); #endif @@ -216,7 +225,7 @@ int phpdbg_parse (); /* Copy the second part of user declarations. */ /* Line 390 of yacc.c */ -#line 220 "sapi/phpdbg/phpdbg_parser.c" +#line 229 "sapi/phpdbg/phpdbg_parser.c" #ifdef short # undef short @@ -443,22 +452,22 @@ union yyalloc #endif /* !YYCOPY_NEEDED */ /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 25 +#define YYFINAL 27 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 42 +#define YYLAST 50 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 21 +#define YYNTOKENS 23 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 5 +#define YYNNTS 7 /* YYNRULES -- Number of rules. */ -#define YYNRULES 25 +#define YYNRULES 30 /* YYNRULES -- Number of states. */ -#define YYNSTATES 38 +#define YYNSTATES 46 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 275 +#define YYMAXUTOK 277 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -493,7 +502,7 @@ static const yytype_uint8 yytranslate[] = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20 + 15, 16, 17, 18, 19, 20, 21, 22 }; #if YYDEBUG @@ -501,30 +510,34 @@ static const yytype_uint8 yytranslate[] = YYRHS. */ static const yytype_uint8 yyprhs[] = { - 0, 0, 3, 5, 7, 8, 10, 13, 17, 22, - 27, 33, 37, 43, 47, 50, 52, 54, 56, 58, - 60, 62, 64, 67, 70, 72 + 0, 0, 3, 5, 9, 10, 12, 14, 16, 19, + 22, 26, 31, 36, 42, 46, 52, 56, 59, 61, + 63, 65, 67, 69, 71, 73, 75, 76, 80, 84, + 87 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { - 22, 0, -1, 23, -1, 25, -1, -1, 24, -1, - 23, 24, -1, 18, 10, 14, -1, 18, 10, 12, - 14, -1, 13, 18, 10, 14, -1, 13, 18, 10, - 12, 14, -1, 18, 11, 18, -1, 18, 11, 18, - 12, 14, -1, 18, 12, 14, -1, 6, 19, -1, - 17, -1, 16, -1, 15, -1, 7, -1, 8, -1, - 14, -1, 18, -1, 3, 19, -1, 5, 19, -1, - 4, -1, 4, 19, -1 + 24, 0, -1, 25, -1, 24, 13, 25, -1, -1, + 26, -1, 29, -1, 27, -1, 26, 27, -1, 26, + 28, -1, 19, 10, 15, -1, 19, 10, 12, 15, + -1, 14, 19, 10, 15, -1, 14, 19, 10, 12, + 15, -1, 19, 11, 19, -1, 19, 11, 19, 12, + 15, -1, 19, 12, 15, -1, 6, 20, -1, 18, + -1, 17, -1, 16, -1, 7, -1, 8, -1, 15, + -1, 19, -1, 22, -1, -1, 3, 28, 20, -1, + 5, 28, 20, -1, 4, 28, -1, 4, 28, 20, + -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { - 0, 66, 66, 67, 68, 72, 73, 77, 82, 87, - 97, 107, 112, 118, 124, 129, 130, 131, 132, 133, - 134, 135, 139, 144, 149, 153 + 0, 71, 71, 72, 73, 77, 78, 82, 83, 84, + 88, 93, 98, 108, 118, 123, 129, 135, 140, 141, + 142, 143, 144, 145, 146, 150, 151, 155, 160, 165, + 169 }; #endif @@ -537,11 +550,13 @@ static const char *const yytname[] = "\"if (condition)\"", "\"truthy (true, on, yes or enabled)\"", "\"falsy (false, off, no or disabled)\"", "\"string (some input, perhaps)\"", "\": (colon)\"", - "\":: (double colon)\"", "\"# (pound sign)\"", "\"protocol (file://)\"", - "\"digits (numbers)\"", "\"literal (string)\"", "\"address\"", - "\"opcode\"", "\"identifier (command or function name)\"", - "\"input (input string or data)\"", "\"input\"", "$accept", "input", - "parameters", "parameter", "full_expression", YY_NULL + "\":: (double colon)\"", "\"# (pound sign followed by digits)\"", + "\"# (pound sign)\"", "\"protocol (file://)\"", "\"digits (numbers)\"", + "\"literal (string)\"", "\"address\"", "\"opcode\"", + "\"identifier (command or function name)\"", + "\"input (input string or data)\"", "\"input\"", + "\"request id (-r %d)\"", "$accept", "input", "command", "parameters", + "parameter", "req_id", "full_expression", YY_NULL }; #endif @@ -552,24 +567,26 @@ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275 + 275, 276, 277 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { - 0, 21, 22, 22, 22, 23, 23, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 25, 25, 25, 25 + 0, 23, 24, 24, 24, 25, 25, 26, 26, 26, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 28, 28, 29, 29, 29, + 29 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { - 0, 2, 1, 1, 0, 1, 2, 3, 4, 4, - 5, 3, 5, 3, 2, 1, 1, 1, 1, 1, - 1, 1, 2, 2, 1, 2 + 0, 2, 1, 3, 0, 1, 1, 1, 2, 2, + 3, 4, 4, 5, 3, 5, 3, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 3, 3, 2, + 3 }; /* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. @@ -577,33 +594,35 @@ static const yytype_uint8 yyr2[] = means the default is an error. */ static const yytype_uint8 yydefact[] = { - 4, 0, 24, 0, 0, 18, 19, 0, 20, 17, - 16, 15, 21, 0, 2, 5, 3, 22, 25, 23, - 14, 0, 0, 0, 0, 1, 6, 0, 0, 7, - 11, 13, 0, 9, 8, 0, 10, 12 + 4, 26, 26, 26, 0, 21, 22, 0, 23, 20, + 19, 18, 24, 0, 2, 5, 7, 6, 25, 0, + 29, 0, 17, 0, 0, 0, 0, 1, 0, 8, + 9, 27, 30, 28, 0, 0, 10, 14, 16, 3, + 0, 12, 11, 0, 13, 15 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { - -1, 13, 14, 15, 16 + -1, 13, 14, 15, 16, 19, 17 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -11 +#define YYPACT_NINF -17 static const yytype_int8 yypact[] = { - -3, -10, 11, 12, 13, -11, -11, 15, -11, -11, - -11, -11, -4, 29, 10, -11, -11, -11, -11, -11, - -11, 24, 7, 17, 22, -11, -11, 8, 23, -11, - 26, -11, 25, -11, -11, 27, -11, -11 + -3, -16, -16, -16, -10, -17, -17, 2, -17, -17, + -17, -17, 26, 9, -17, 11, -17, -17, -17, 3, + 4, 21, -17, 29, 19, 23, 25, -17, -3, -17, + -17, -17, -17, -17, 20, 28, -17, 32, -17, -17, + 30, -17, -17, 31, -17, -17 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { - -11, -11, -11, 28, -11 + -17, -17, 22, -17, 33, 5, -17 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If @@ -612,36 +631,39 @@ static const yytype_int8 yypgoto[] = #define YYTABLE_NINF -1 static const yytype_uint8 yytable[] = { - 1, 2, 3, 4, 5, 6, 22, 23, 24, 17, - 7, 8, 9, 10, 11, 12, 4, 5, 6, 28, - 32, 29, 33, 7, 8, 9, 10, 11, 12, 25, - 18, 19, 20, 21, 27, 30, 31, 34, 35, 36, - 0, 37, 26 + 1, 2, 3, 4, 5, 6, 18, 20, 21, 27, + 22, 7, 8, 9, 10, 11, 12, 4, 5, 6, + 30, 23, 28, 31, 32, 7, 8, 9, 10, 11, + 12, 35, 40, 18, 36, 41, 24, 25, 26, 34, + 38, 33, 37, 42, 43, 44, 45, 0, 29, 0, + 39 }; #define yypact_value_is_default(Yystate) \ - (!!((Yystate) == (-11))) + (!!((Yystate) == (-17))) #define yytable_value_is_error(Yytable_value) \ YYID (0) static const yytype_int8 yycheck[] = { - 3, 4, 5, 6, 7, 8, 10, 11, 12, 19, - 13, 14, 15, 16, 17, 18, 6, 7, 8, 12, - 12, 14, 14, 13, 14, 15, 16, 17, 18, 0, - 19, 19, 19, 18, 10, 18, 14, 14, 12, 14, - -1, 14, 14 + 3, 4, 5, 6, 7, 8, 22, 2, 3, 0, + 20, 14, 15, 16, 17, 18, 19, 6, 7, 8, + 15, 19, 13, 20, 20, 14, 15, 16, 17, 18, + 19, 12, 12, 22, 15, 15, 10, 11, 12, 10, + 15, 20, 19, 15, 12, 15, 15, -1, 15, -1, + 28 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { - 0, 3, 4, 5, 6, 7, 8, 13, 14, 15, - 16, 17, 18, 22, 23, 24, 25, 19, 19, 19, - 19, 18, 10, 11, 12, 0, 24, 10, 12, 14, - 18, 14, 12, 14, 14, 12, 14, 14 + 0, 3, 4, 5, 6, 7, 8, 14, 15, 16, + 17, 18, 19, 24, 25, 26, 27, 29, 22, 28, + 28, 28, 20, 19, 10, 11, 12, 0, 13, 27, + 28, 20, 20, 20, 10, 12, 15, 19, 15, 25, + 12, 15, 15, 12, 15, 15 }; #define yyerrok (yyerrstatus = 0) @@ -683,7 +705,7 @@ do \ } \ else \ { \ - yyerror (tsrm_ls, YY_("syntax error: cannot back up")); \ + yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) @@ -726,7 +748,7 @@ do { \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ - Type, Value, tsrm_ls); \ + Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) @@ -740,21 +762,19 @@ do { \ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, void *tsrm_ls) +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep, tsrm_ls) +yy_symbol_value_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; - void *tsrm_ls; #endif { FILE *yyo = yyoutput; YYUSE (yyo); if (!yyvaluep) return; - YYUSE (tsrm_ls); # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); @@ -772,14 +792,13 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep, tsrm_ls) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, void *tsrm_ls) +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void -yy_symbol_print (yyoutput, yytype, yyvaluep, tsrm_ls) +yy_symbol_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; - void *tsrm_ls; #endif { if (yytype < YYNTOKENS) @@ -787,7 +806,7 @@ yy_symbol_print (yyoutput, yytype, yyvaluep, tsrm_ls) else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); - yy_symbol_value_print (yyoutput, yytype, yyvaluep, tsrm_ls); + yy_symbol_value_print (yyoutput, yytype, yyvaluep); YYFPRINTF (yyoutput, ")"); } @@ -830,13 +849,12 @@ do { \ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yy_reduce_print (YYSTYPE *yyvsp, int yyrule, void *tsrm_ls) +yy_reduce_print (YYSTYPE *yyvsp, int yyrule) #else static void -yy_reduce_print (yyvsp, yyrule, tsrm_ls) +yy_reduce_print (yyvsp, yyrule) YYSTYPE *yyvsp; int yyrule; - void *tsrm_ls; #endif { int yynrhs = yyr2[yyrule]; @@ -850,7 +868,7 @@ yy_reduce_print (yyvsp, yyrule, tsrm_ls) YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) - , tsrm_ls); + ); YYFPRINTF (stderr, "\n"); } } @@ -858,7 +876,7 @@ yy_reduce_print (yyvsp, yyrule, tsrm_ls) # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ - yy_reduce_print (yyvsp, Rule, tsrm_ls); \ + yy_reduce_print (yyvsp, Rule); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that @@ -1138,18 +1156,16 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, void *tsrm_ls) +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) #else static void -yydestruct (yymsg, yytype, yyvaluep, tsrm_ls) +yydestruct (yymsg, yytype, yyvaluep) const char *yymsg; int yytype; YYSTYPE *yyvaluep; - void *tsrm_ls; #endif { YYUSE (yyvaluep); - YYUSE (tsrm_ls); if (!yymsg) yymsg = "Deleting"; @@ -1179,11 +1195,11 @@ yyparse (YYPARSE_PARAM) #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int -yyparse (void *tsrm_ls) +yyparse (void) #else int -yyparse (tsrm_ls) - void *tsrm_ls; +yyparse () + #endif #endif { @@ -1451,37 +1467,61 @@ yyreduce: YY_REDUCE_PRINT (yyn); switch (yyn) { - case 3: + case 2: +/* Line 1802 of yacc.c */ +#line 71 "sapi/phpdbg/phpdbg_parser.y" + { (yyval) = (yyvsp[(1) - (1)]); } + break; + + case 3: /* Line 1802 of yacc.c */ -#line 67 "sapi/phpdbg/phpdbg_parser.y" - { phpdbg_stack_push(PHPDBG_G(parser_stack), &(yyvsp[(1) - (1)])); } +#line 72 "sapi/phpdbg/phpdbg_parser.y" + { phpdbg_stack_separate((yyvsp[(1) - (3)]).top); (yyval) = (yyvsp[(3) - (3)]); } break; case 5: /* Line 1802 of yacc.c */ -#line 72 "sapi/phpdbg/phpdbg_parser.y" - { phpdbg_stack_push(PHPDBG_G(parser_stack), &(yyvsp[(1) - (1)])); } +#line 77 "sapi/phpdbg/phpdbg_parser.y" + { (yyval).top = PHPDBG_G(parser_stack)->top; } break; case 6: /* Line 1802 of yacc.c */ -#line 73 "sapi/phpdbg/phpdbg_parser.y" - { phpdbg_stack_push(PHPDBG_G(parser_stack), &(yyvsp[(2) - (2)])); } +#line 78 "sapi/phpdbg/phpdbg_parser.y" + { phpdbg_stack_push(PHPDBG_G(parser_stack), &(yyvsp[(1) - (1)])); (yyval).top = PHPDBG_G(parser_stack)->top; } break; case 7: /* Line 1802 of yacc.c */ -#line 77 "sapi/phpdbg/phpdbg_parser.y" - { +#line 82 "sapi/phpdbg/phpdbg_parser.y" + { phpdbg_stack_push(PHPDBG_G(parser_stack), &(yyvsp[(1) - (1)])); (yyval).top = PHPDBG_G(parser_stack)->top; } + break; + + case 8: +/* Line 1802 of yacc.c */ +#line 83 "sapi/phpdbg/phpdbg_parser.y" + { phpdbg_stack_push(PHPDBG_G(parser_stack), &(yyvsp[(2) - (2)])); (yyval).top = PHPDBG_G(parser_stack)->top; } + break; + + case 9: +/* Line 1802 of yacc.c */ +#line 84 "sapi/phpdbg/phpdbg_parser.y" + { (yyval) = (yyvsp[(1) - (2)]); } + break; + + case 10: +/* Line 1802 of yacc.c */ +#line 88 "sapi/phpdbg/phpdbg_parser.y" + { (yyval).type = FILE_PARAM; (yyval).file.name = (yyvsp[(2) - (3)]).str; (yyval).file.line = (yyvsp[(3) - (3)]).num; } break; - case 8: + case 11: /* Line 1802 of yacc.c */ -#line 82 "sapi/phpdbg/phpdbg_parser.y" +#line 93 "sapi/phpdbg/phpdbg_parser.y" { (yyval).type = NUMERIC_FILE_PARAM; (yyval).file.name = (yyvsp[(1) - (4)]).str; @@ -1489,9 +1529,9 @@ yyreduce: } break; - case 9: + case 12: /* Line 1802 of yacc.c */ -#line 87 "sapi/phpdbg/phpdbg_parser.y" +#line 98 "sapi/phpdbg/phpdbg_parser.y" { (yyval).type = FILE_PARAM; (yyval).file.name = malloc((yyvsp[(1) - (4)]).len + (yyvsp[(2) - (4)]).len + 1); @@ -1504,9 +1544,9 @@ yyreduce: } break; - case 10: + case 13: /* Line 1802 of yacc.c */ -#line 97 "sapi/phpdbg/phpdbg_parser.y" +#line 108 "sapi/phpdbg/phpdbg_parser.y" { (yyval).type = NUMERIC_FILE_PARAM; (yyval).file.name = malloc((yyvsp[(1) - (5)]).len + (yyvsp[(2) - (5)]).len + 1); @@ -1519,132 +1559,138 @@ yyreduce: } break; - case 11: + case 14: /* Line 1802 of yacc.c */ -#line 107 "sapi/phpdbg/phpdbg_parser.y" - { +#line 118 "sapi/phpdbg/phpdbg_parser.y" + { (yyval).type = METHOD_PARAM; (yyval).method.class = (yyvsp[(1) - (3)]).str; (yyval).method.name = (yyvsp[(3) - (3)]).str; } break; - case 12: + case 15: /* Line 1802 of yacc.c */ -#line 112 "sapi/phpdbg/phpdbg_parser.y" - { +#line 123 "sapi/phpdbg/phpdbg_parser.y" + { (yyval).type = NUMERIC_METHOD_PARAM; (yyval).method.class = (yyvsp[(1) - (5)]).str; (yyval).method.name = (yyvsp[(3) - (5)]).str; - (yyval).num = (yyvsp[(5) - (5)]).num; + (yyval).num = (yyvsp[(5) - (5)]).num; } break; - case 13: + case 16: /* Line 1802 of yacc.c */ -#line 118 "sapi/phpdbg/phpdbg_parser.y" +#line 129 "sapi/phpdbg/phpdbg_parser.y" { (yyval).type = NUMERIC_FUNCTION_PARAM; (yyval).str = (yyvsp[(1) - (3)]).str; (yyval).len = (yyvsp[(1) - (3)]).len; - (yyval).num = (yyvsp[(3) - (3)]).num; + (yyval).num = (yyvsp[(3) - (3)]).num; } break; - case 14: + case 17: /* Line 1802 of yacc.c */ -#line 124 "sapi/phpdbg/phpdbg_parser.y" +#line 135 "sapi/phpdbg/phpdbg_parser.y" { - (yyval).type = COND_PARAM; + (yyval).type = COND_PARAM; (yyval).str = (yyvsp[(2) - (2)]).str; (yyval).len = (yyvsp[(2) - (2)]).len; } break; - case 15: + case 18: /* Line 1802 of yacc.c */ -#line 129 "sapi/phpdbg/phpdbg_parser.y" +#line 140 "sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; - case 16: + case 19: /* Line 1802 of yacc.c */ -#line 130 "sapi/phpdbg/phpdbg_parser.y" +#line 141 "sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; - case 17: + case 20: /* Line 1802 of yacc.c */ -#line 131 "sapi/phpdbg/phpdbg_parser.y" +#line 142 "sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; - case 18: + case 21: /* Line 1802 of yacc.c */ -#line 132 "sapi/phpdbg/phpdbg_parser.y" +#line 143 "sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; - case 19: + case 22: /* Line 1802 of yacc.c */ -#line 133 "sapi/phpdbg/phpdbg_parser.y" +#line 144 "sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; - case 20: + case 23: /* Line 1802 of yacc.c */ -#line 134 "sapi/phpdbg/phpdbg_parser.y" +#line 145 "sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; - case 21: + case 24: /* Line 1802 of yacc.c */ -#line 135 "sapi/phpdbg/phpdbg_parser.y" +#line 146 "sapi/phpdbg/phpdbg_parser.y" { (yyval) = (yyvsp[(1) - (1)]); } break; - case 22: + case 25: /* Line 1802 of yacc.c */ -#line 139 "sapi/phpdbg/phpdbg_parser.y" - { - (yyval).type = EVAL_PARAM; - (yyval).str = (yyvsp[(2) - (2)]).str; - (yyval).len = (yyvsp[(2) - (2)]).len; +#line 150 "sapi/phpdbg/phpdbg_parser.y" + { PHPDBG_G(req_id) = (yyvsp[(1) - (1)]).num; } + break; + + case 27: +/* Line 1802 of yacc.c */ +#line 155 "sapi/phpdbg/phpdbg_parser.y" + { + (yyval).type = EVAL_PARAM; + (yyval).str = (yyvsp[(3) - (3)]).str; + (yyval).len = (yyvsp[(3) - (3)]).len; } break; - case 23: + case 28: /* Line 1802 of yacc.c */ -#line 144 "sapi/phpdbg/phpdbg_parser.y" - { - (yyval).type = SHELL_PARAM; - (yyval).str = (yyvsp[(2) - (2)]).str; - (yyval).len = (yyvsp[(2) - (2)]).len; +#line 160 "sapi/phpdbg/phpdbg_parser.y" + { + (yyval).type = SHELL_PARAM; + (yyval).str = (yyvsp[(3) - (3)]).str; + (yyval).len = (yyvsp[(3) - (3)]).len; } break; - case 24: + case 29: /* Line 1802 of yacc.c */ -#line 149 "sapi/phpdbg/phpdbg_parser.y" +#line 165 "sapi/phpdbg/phpdbg_parser.y" { (yyval).type = RUN_PARAM; (yyval).len = 0; } break; - case 25: + case 30: /* Line 1802 of yacc.c */ -#line 153 "sapi/phpdbg/phpdbg_parser.y" - { - (yyval).type = RUN_PARAM; - (yyval).str = (yyvsp[(2) - (2)]).str; - (yyval).len = (yyvsp[(2) - (2)]).len; +#line 169 "sapi/phpdbg/phpdbg_parser.y" + { + (yyval).type = RUN_PARAM; + (yyval).str = (yyvsp[(3) - (3)]).str; + (yyval).len = (yyvsp[(3) - (3)]).len; } break; /* Line 1802 of yacc.c */ -#line 1648 "sapi/phpdbg/phpdbg_parser.c" +#line 1694 "sapi/phpdbg/phpdbg_parser.c" default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -1694,7 +1740,7 @@ yyerrlab: { ++yynerrs; #if ! YYERROR_VERBOSE - yyerror (tsrm_ls, YY_("syntax error")); + yyerror (YY_("syntax error")); #else # define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ yyssp, yytoken) @@ -1721,7 +1767,7 @@ yyerrlab: yymsgp = yymsg; } } - yyerror (tsrm_ls, yymsgp); + yyerror (yymsgp); if (yysyntax_error_status == 2) goto yyexhaustedlab; } @@ -1745,7 +1791,7 @@ yyerrlab: else { yydestruct ("Error: discarding", - yytoken, &yylval, tsrm_ls); + yytoken, &yylval); yychar = YYEMPTY; } } @@ -1801,7 +1847,7 @@ yyerrlab1: yydestruct ("Error: popping", - yystos[yystate], yyvsp, tsrm_ls); + yystos[yystate], yyvsp); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); @@ -1838,7 +1884,7 @@ yyabortlab: | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: - yyerror (tsrm_ls, YY_("memory exhausted")); + yyerror (YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif @@ -1850,7 +1896,7 @@ yyreturn: user semantic actions for why this is necessary. */ yytoken = YYTRANSLATE (yychar); yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, tsrm_ls); + yytoken, &yylval); } /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ @@ -1859,7 +1905,7 @@ yyreturn: while (yyssp != yyss) { yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp, tsrm_ls); + yystos[*yyssp], yyvsp); YYPOPSTACK (1); } #ifndef yyoverflow @@ -1876,15 +1922,15 @@ yyreturn: /* Line 2050 of yacc.c */ -#line 160 "sapi/phpdbg/phpdbg_parser.y" +#line 176 "sapi/phpdbg/phpdbg_parser.y" -static int yyerror(void ***tsrm_ls, const char *msg) { - phpdbg_error("Parse Error: %s", msg); +static int yyerror(const char *msg) { + phpdbg_error("command", "type=\"parseerror\" msg=\"%s\"", "Parse Error: %s", msg); { const phpdbg_param_t *top = PHPDBG_G(parser_stack); - + while (top) { phpdbg_param_debug(top, "--> "); top = top->next; @@ -1893,12 +1939,12 @@ static int yyerror(void ***tsrm_ls, const char *msg) { return 0; } -int phpdbg_do_parse(phpdbg_param_t *stack, char *input TSRMLS_DC) { - phpdbg_init_lexer(stack, input TSRMLS_CC); +int phpdbg_do_parse(phpdbg_param_t *stack, char *input) { + if (!*input) { + return 0; + } -#ifdef ZTS - return yyparse(TSRMLS_C); -#else - return yyparse(NULL); -#endif + phpdbg_init_lexer(stack, input); + + return yyparse(); } diff --git a/sapi/phpdbg/phpdbg_parser.h b/sapi/phpdbg/phpdbg_parser.h index da5892ac99..38d3ecbf70 100644 --- a/sapi/phpdbg/phpdbg_parser.h +++ b/sapi/phpdbg/phpdbg_parser.h @@ -41,7 +41,7 @@ extern int phpdbg_debug; #endif /* "%code requires" blocks. */ /* Line 2060 of yacc.c */ -#line 31 "/Users/Bob/php-src-5.6/sapi/phpdbg/phpdbg_parser.y" +#line 36 "/Users/Bob/php-src-X/sapi/phpdbg/phpdbg_parser.y" #include "phpdbg.h" #ifndef YY_TYPEDEF_YY_SCANNER_T @@ -69,14 +69,16 @@ typedef void* yyscan_t; T_COLON = 265, T_DCOLON = 266, T_POUND = 267, - T_PROTO = 268, - T_DIGITS = 269, - T_LITERAL = 270, - T_ADDR = 271, - T_OPCODE = 272, - T_ID = 273, - T_INPUT = 274, - T_UNEXPECTED = 275 + T_SEPARATOR = 268, + T_PROTO = 269, + T_DIGITS = 270, + T_LITERAL = 271, + T_ADDR = 272, + T_OPCODE = 273, + T_ID = 274, + T_INPUT = 275, + T_UNEXPECTED = 276, + T_REQ_ID = 277 }; #endif /* Tokens. */ @@ -90,14 +92,16 @@ typedef void* yyscan_t; #define T_COLON 265 #define T_DCOLON 266 #define T_POUND 267 -#define T_PROTO 268 -#define T_DIGITS 269 -#define T_LITERAL 270 -#define T_ADDR 271 -#define T_OPCODE 272 -#define T_ID 273 -#define T_INPUT 274 -#define T_UNEXPECTED 275 +#define T_SEPARATOR 268 +#define T_PROTO 269 +#define T_DIGITS 270 +#define T_LITERAL 271 +#define T_ADDR 272 +#define T_OPCODE 273 +#define T_ID 274 +#define T_INPUT 275 +#define T_UNEXPECTED 276 +#define T_REQ_ID 277 @@ -117,7 +121,7 @@ int phpdbg_parse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus -int phpdbg_parse (void *tsrm_ls); +int phpdbg_parse (void); #else int phpdbg_parse (); #endif diff --git a/sapi/phpdbg/phpdbg_parser.y b/sapi/phpdbg/phpdbg_parser.y index 702bf78455..df9be36eee 100644 --- a/sapi/phpdbg/phpdbg_parser.y +++ b/sapi/phpdbg/phpdbg_parser.y @@ -1,12 +1,12 @@ %{ - + /* * phpdbg_parser.y * (from php-src root) * flex sapi/phpdbg/dev/phpdbg_lexer.l * bison sapi/phpdbg/dev/phpdbg_parser.y */ - + #include "phpdbg.h" #include "phpdbg_cmd.h" #include "phpdbg_utils.h" @@ -19,15 +19,20 @@ #include "phpdbg_lexer.h" #undef yyerror -static int yyerror(void ***tsrm_ls, const char *msg); +static int yyerror(const char *msg); -ZEND_EXTERN_MODULE_GLOBALS(phpdbg); +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) + +#ifdef _MSC_VER +#define YYMALLOC malloc +#define YYFREE free +#endif %} %pure-parser %error-verbose - + %code requires { #include "phpdbg.h" #ifndef YY_TYPEDEF_YY_SCANNER_T @@ -36,8 +41,6 @@ typedef void* yyscan_t; #endif } -%parse-param { void *tsrm_ls } - %output "sapi/phpdbg/phpdbg_parser.c" %defines "sapi/phpdbg/phpdbg_parser.h" @@ -50,7 +53,8 @@ typedef void* yyscan_t; %token T_STRING "string (some input, perhaps)" %token T_COLON ": (colon)" %token T_DCOLON ":: (double colon)" -%token T_POUND "# (pound sign)" +%token T_POUND "# (pound sign followed by digits)" +%token T_SEPARATOR "# (pound sign)" %token T_PROTO "protocol (file://)" %token T_DIGITS "digits (numbers)" %token T_LITERAL "literal (string)" @@ -59,22 +63,29 @@ typedef void* yyscan_t; %token T_ID "identifier (command or function name)" %token T_INPUT "input (input string or data)" %token T_UNEXPECTED "input" +%token T_REQ_ID "request id (-r %d)" %% /* Rules */ input - : parameters - | full_expression { phpdbg_stack_push(PHPDBG_G(parser_stack), &$1); } + : command { $$ = $1; } + | input T_SEPARATOR command { phpdbg_stack_separate($1.top); $$ = $3; } | /* nothing */ ; +command + : parameters { $$.top = PHPDBG_G(parser_stack)->top; } + | full_expression { phpdbg_stack_push(PHPDBG_G(parser_stack), &$1); $$.top = PHPDBG_G(parser_stack)->top; } + ; + parameters - : parameter { phpdbg_stack_push(PHPDBG_G(parser_stack), &$1); } - | parameters parameter { phpdbg_stack_push(PHPDBG_G(parser_stack), &$2); } + : parameter { phpdbg_stack_push(PHPDBG_G(parser_stack), &$1); $$.top = PHPDBG_G(parser_stack)->top; } + | parameters parameter { phpdbg_stack_push(PHPDBG_G(parser_stack), &$2); $$.top = PHPDBG_G(parser_stack)->top; } + | parameters req_id { $$ = $1; } ; parameter - : T_ID T_COLON T_DIGITS { + : T_ID T_COLON T_DIGITS { $$.type = FILE_PARAM; $$.file.name = $2.str; $$.file.line = $3.num; @@ -104,25 +115,25 @@ parameter } $$.file.line = $5.num; } - | T_ID T_DCOLON T_ID { + | T_ID T_DCOLON T_ID { $$.type = METHOD_PARAM; $$.method.class = $1.str; $$.method.name = $3.str; } - | T_ID T_DCOLON T_ID T_POUND T_DIGITS { + | T_ID T_DCOLON T_ID T_POUND T_DIGITS { $$.type = NUMERIC_METHOD_PARAM; $$.method.class = $1.str; $$.method.name = $3.str; - $$.num = $5.num; + $$.num = $5.num; } | T_ID T_POUND T_DIGITS { $$.type = NUMERIC_FUNCTION_PARAM; $$.str = $1.str; $$.len = $1.len; - $$.num = $3.num; + $$.num = $3.num; } | T_IF T_INPUT { - $$.type = COND_PARAM; + $$.type = COND_PARAM; $$.str = $2.str; $$.len = $2.len; } @@ -135,36 +146,41 @@ parameter | T_ID { $$ = $1; } ; +req_id + : T_REQ_ID { PHPDBG_G(req_id) = $1.num; } + | /* empty */ +; + full_expression - : T_EVAL T_INPUT { - $$.type = EVAL_PARAM; - $$.str = $2.str; - $$.len = $2.len; + : T_EVAL req_id T_INPUT { + $$.type = EVAL_PARAM; + $$.str = $3.str; + $$.len = $3.len; } - | T_SHELL T_INPUT { - $$.type = SHELL_PARAM; - $$.str = $2.str; - $$.len = $2.len; + | T_SHELL req_id T_INPUT { + $$.type = SHELL_PARAM; + $$.str = $3.str; + $$.len = $3.len; } - | T_RUN { + | T_RUN req_id { $$.type = RUN_PARAM; $$.len = 0; } - | T_RUN T_INPUT { - $$.type = RUN_PARAM; - $$.str = $2.str; - $$.len = $2.len; + | T_RUN req_id T_INPUT { + $$.type = RUN_PARAM; + $$.str = $3.str; + $$.len = $3.len; } ; %% -static int yyerror(void ***tsrm_ls, const char *msg) { - phpdbg_error("Parse Error: %s", msg); +static int yyerror(const char *msg) { + phpdbg_error("command", "type=\"parseerror\" msg=\"%s\"", "Parse Error: %s", msg); { const phpdbg_param_t *top = PHPDBG_G(parser_stack); - + while (top) { phpdbg_param_debug(top, "--> "); top = top->next; @@ -173,12 +189,12 @@ static int yyerror(void ***tsrm_ls, const char *msg) { return 0; } -int phpdbg_do_parse(phpdbg_param_t *stack, char *input TSRMLS_DC) { - phpdbg_init_lexer(stack, input TSRMLS_CC); +int phpdbg_do_parse(phpdbg_param_t *stack, char *input) { + if (!*input) { + return 0; + } -#ifdef ZTS - return yyparse(TSRMLS_C); -#else - return yyparse(NULL); -#endif + phpdbg_init_lexer(stack, input); + + return yyparse(); } diff --git a/sapi/phpdbg/phpdbg_print.c b/sapi/phpdbg/phpdbg_print.c index 3cab7a6951..3725bf6083 100644 --- a/sapi/phpdbg/phpdbg_print.c +++ b/sapi/phpdbg/phpdbg_print.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -24,82 +24,79 @@ #include "phpdbg_opcode.h" #include "phpdbg_prompt.h" -ZEND_EXTERN_MODULE_GLOBALS(phpdbg); +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) -#define PHPDBG_PRINT_COMMAND_D(f, h, a, m, l, s) \ - PHPDBG_COMMAND_D_EXP(f, h, a, m, l, s, &phpdbg_prompt_commands[9]) +#define PHPDBG_PRINT_COMMAND_D(f, h, a, m, l, s, flags) \ + PHPDBG_COMMAND_D_EXP(f, h, a, m, l, s, &phpdbg_prompt_commands[8], flags) const phpdbg_command_t phpdbg_print_commands[] = { - PHPDBG_PRINT_COMMAND_D(exec, "print out the instructions in the execution context", 'e', print_exec, NULL, 0), - PHPDBG_PRINT_COMMAND_D(opline, "print out the instruction in the current opline", 'o', print_opline, NULL, 0), - PHPDBG_PRINT_COMMAND_D(class, "print out the instructions in the specified class", 'c', print_class, NULL, "s"), - PHPDBG_PRINT_COMMAND_D(method, "print out the instructions in the specified method", 'm', print_method, NULL, "m"), - PHPDBG_PRINT_COMMAND_D(func, "print out the instructions in the specified function", 'f', print_func, NULL, "s"), - PHPDBG_PRINT_COMMAND_D(stack, "print out the instructions in the current stack", 's', print_stack, NULL, 0), + PHPDBG_PRINT_COMMAND_D(exec, "print out the instructions in the main execution context", 'e', print_exec, NULL, 0, PHPDBG_ASYNC_SAFE), + PHPDBG_PRINT_COMMAND_D(opline, "print out the instruction in the current opline", 'o', print_opline, NULL, 0, PHPDBG_ASYNC_SAFE), + PHPDBG_PRINT_COMMAND_D(class, "print out the instructions in the specified class", 'c', print_class, NULL, "s", PHPDBG_ASYNC_SAFE), + PHPDBG_PRINT_COMMAND_D(method, "print out the instructions in the specified method", 'm', print_method, NULL, "m", PHPDBG_ASYNC_SAFE), + PHPDBG_PRINT_COMMAND_D(func, "print out the instructions in the specified function", 'f', print_func, NULL, "s", PHPDBG_ASYNC_SAFE), + PHPDBG_PRINT_COMMAND_D(stack, "print out the instructions in the current stack", 's', print_stack, NULL, 0, PHPDBG_ASYNC_SAFE), PHPDBG_END_COMMAND }; PHPDBG_PRINT(opline) /* {{{ */ { - if (EG(in_execution) && EG(current_execute_data)) { - phpdbg_print_opline(EG(current_execute_data), 1 TSRMLS_CC); + if (PHPDBG_G(in_execution) && EG(current_execute_data)) { + phpdbg_print_opline(phpdbg_user_execute_data(EG(current_execute_data)), 1); } else { - phpdbg_error("Not Executing!"); + phpdbg_error("inactive", "type=\"execution\"", "Not Executing!"); } return SUCCESS; } /* }}} */ -static inline void phpdbg_print_function_helper(zend_function *method TSRMLS_DC) /* {{{ */ +static inline void phpdbg_print_function_helper(zend_function *method) /* {{{ */ { switch (method->type) { case ZEND_USER_FUNCTION: { zend_op_array* op_array = &(method->op_array); - HashTable vars; - + if (op_array) { zend_op *opline = &(op_array->opcodes[0]); - zend_uint opcode = 0, + uint32_t opcode = 0, end = op_array->last-1; if (method->common.scope) { - phpdbg_writeln("\tL%d-%d %s::%s() %s", - op_array->line_start, op_array->line_end, - method->common.scope->name, - method->common.function_name, - op_array->filename ? op_array->filename : "unknown"); + phpdbg_writeln("printoplineinfo", "type=\"User\" startline=\"%d\" endline=\"%d\" method=\"%s::%s\" file=\"%s\" opline=\"%p\"", "L%d-%d %s::%s() %s - %p + %d ops", + op_array->line_start, + op_array->line_end, + ZSTR_VAL(method->common.scope->name), + ZSTR_VAL(method->common.function_name), + op_array->filename ? ZSTR_VAL(op_array->filename) : "unknown", + opline, + op_array->last); } else { - phpdbg_writeln("\tL%d-%d %s() %s", - method->common.function_name ? op_array->line_start : 0, - method->common.function_name ? op_array->line_end : 0, - method->common.function_name ? method->common.function_name : "{main}", - op_array->filename ? op_array->filename : "unknown"); + phpdbg_writeln("printoplineinfo", "type=\"User\" startline=\"%d\" endline=\"%d\" function=\"%s\" file=\"%s\" opline=\"%p\"", "L%d-%d %s() %s - %p + %d ops", + op_array->line_start, + op_array->line_end, + method->common.function_name ? ZSTR_VAL(method->common.function_name) : "{main}", + op_array->filename ? ZSTR_VAL(op_array->filename) : "unknown", + opline, + op_array->last); } - zend_hash_init(&vars, op_array->last, NULL, NULL, 0); do { - char *decode = phpdbg_decode_opline(op_array, opline, &vars TSRMLS_CC); - if (decode != NULL) { - phpdbg_writeln("\t\tL%u\t%p %-30s %s", - opline->lineno, - opline, - phpdbg_decode_opcode(opline->opcode), - decode); - free(decode); - } else { - phpdbg_error("\tFailed to decode opline %16p", opline); - } + char *decode = phpdbg_decode_opline(op_array, opline); + phpdbg_writeln("print", "line=\"%u\" opnum=\"%u\" op=\"%s\"", " L%-4u #%-5u %s", + opline->lineno, + opcode, + decode); + efree(decode); opline++; } while (opcode++ < end); - zend_hash_destroy(&vars); } } break; default: { if (method->common.scope) { - phpdbg_writeln("\tInternal %s::%s()", method->common.scope->name, method->common.function_name); + phpdbg_writeln("printoplineinfo", "type=\"Internal\" method=\"%s::%s\"", "\tInternal %s::%s()", ZSTR_VAL(method->common.scope->name), ZSTR_VAL(method->common.function_name)); } else { - phpdbg_writeln("\tInternal %s()", method->common.function_name); + phpdbg_writeln("printoplineinfo", "type=\"Internal\" function=\"%s\"", "\tInternal %s()", ZSTR_VAL(method->common.function_name)); } } } @@ -108,17 +105,17 @@ static inline void phpdbg_print_function_helper(zend_function *method TSRMLS_DC) PHPDBG_PRINT(exec) /* {{{ */ { if (PHPDBG_G(exec)) { - if (!PHPDBG_G(ops)) { - phpdbg_compile(TSRMLS_C); + if (!PHPDBG_G(ops) && !(PHPDBG_G(flags) & PHPDBG_IN_SIGNAL_HANDLER)) { + phpdbg_compile(); } if (PHPDBG_G(ops)) { - phpdbg_notice("Context %s", PHPDBG_G(exec)); + phpdbg_notice("printinfo", "file=\"%s\" num=\"%d\"", "Context %s (%d ops)", PHPDBG_G(exec), PHPDBG_G(ops)->last); - phpdbg_print_function_helper((zend_function*) PHPDBG_G(ops) TSRMLS_CC); + phpdbg_print_function_helper((zend_function*) PHPDBG_G(ops)); } } else { - phpdbg_error("No execution context set"); + phpdbg_error("inactive", "type=\"nocontext\"", "No execution context set"); } return SUCCESS; @@ -126,25 +123,24 @@ return SUCCESS; PHPDBG_PRINT(stack) /* {{{ */ { - zend_op_array *ops = EG(active_op_array); - - if (EG(in_execution) && ops) { + if (PHPDBG_G(in_execution) && EG(current_execute_data)) { + zend_op_array *ops = &phpdbg_user_execute_data(EG(current_execute_data))->func->op_array; if (ops->function_name) { if (ops->scope) { - phpdbg_notice("Stack in %s::%s()", ops->scope->name, ops->function_name); + phpdbg_notice("printinfo", "method=\"%s::%s\" num=\"%d\"", "Stack in %s::%s() (%d ops)", ZSTR_VAL(ops->scope->name), ZSTR_VAL(ops->function_name), ops->last); } else { - phpdbg_notice("Stack in %s()", ops->function_name); + phpdbg_notice("printinfo", "function=\"%s\" num=\"%d\"", "Stack in %s() (%d ops)", ZSTR_VAL(ops->function_name), ops->last); } } else { if (ops->filename) { - phpdbg_notice("Stack in %s", ops->filename); + phpdbg_notice("printinfo", "file=\"%s\" num=\"%d\"", "Stack in %s (%d ops)", ZSTR_VAL(ops->filename), ops->last); } else { - phpdbg_notice("Stack @ %p", ops); + phpdbg_notice("printinfo", "opline=\"%p\" num=\"%d\"", "Stack @ %p (%d ops)", ops, ops->last); } } - phpdbg_print_function_helper((zend_function*) ops TSRMLS_CC); + phpdbg_print_function_helper((zend_function*) ops); } else { - phpdbg_error("Not Executing!"); + phpdbg_error("inactive", "type=\"execution\"", "Not Executing!"); } return SUCCESS; @@ -152,32 +148,33 @@ PHPDBG_PRINT(stack) /* {{{ */ PHPDBG_PRINT(class) /* {{{ */ { - zend_class_entry **ce; + zend_class_entry *ce; - if (zend_lookup_class(param->str, param->len, &ce TSRMLS_CC) == SUCCESS) { - phpdbg_notice("%s %s: %s", - ((*ce)->type == ZEND_USER_CLASS) ? + if (phpdbg_safe_class_lookup(param->str, param->len, &ce) == SUCCESS) { + phpdbg_notice("printinfo", "type=\"%s\" flag=\"%s\" class=\"%s\" num=\"%d\"", "%s %s: %s (%d methods)", + (ce->type == ZEND_USER_CLASS) ? "User" : "Internal", - ((*ce)->ce_flags & ZEND_ACC_INTERFACE) ? + (ce->ce_flags & ZEND_ACC_INTERFACE) ? "Interface" : - ((*ce)->ce_flags & ZEND_ACC_ABSTRACT) ? + (ce->ce_flags & ZEND_ACC_ABSTRACT) ? "Abstract Class" : "Class", - (*ce)->name); + ZSTR_VAL(ce->name), + zend_hash_num_elements(&ce->function_table)); + + phpdbg_xml("<printmethods %r>"); - phpdbg_writeln("Methods (%d):", zend_hash_num_elements(&(*ce)->function_table)); - if (zend_hash_num_elements(&(*ce)->function_table)) { - HashPosition position; + if (zend_hash_num_elements(&ce->function_table)) { zend_function *method; - for (zend_hash_internal_pointer_reset_ex(&(*ce)->function_table, &position); - zend_hash_get_current_data_ex(&(*ce)->function_table, (void**) &method, &position) == SUCCESS; - zend_hash_move_forward_ex(&(*ce)->function_table, &position)) { - phpdbg_print_function_helper(method TSRMLS_CC); - } + ZEND_HASH_FOREACH_PTR(&ce->function_table, method) { + phpdbg_print_function_helper(method); + } ZEND_HASH_FOREACH_END(); } + + phpdbg_xml("</printmethods>"); } else { - phpdbg_error("The class %s could not be found", param->str); + phpdbg_error("print", "type=\"noclass\" class=\"%s\"", "The class %s could not be found", param->str); } return SUCCESS; @@ -185,25 +182,27 @@ PHPDBG_PRINT(class) /* {{{ */ PHPDBG_PRINT(method) /* {{{ */ { - zend_class_entry **ce; + zend_class_entry *ce; - if (zend_lookup_class(param->method.class, strlen(param->method.class), &ce TSRMLS_CC) == SUCCESS) { + if (phpdbg_safe_class_lookup(param->method.class, strlen(param->method.class), &ce) == SUCCESS) { zend_function *fbc; - char *lcname = zend_str_tolower_dup(param->method.name, strlen(param->method.name)); + zend_string *lcname = zend_string_alloc(strlen(param->method.name), 0); + zend_str_tolower_copy(ZSTR_VAL(lcname), param->method.name, ZSTR_LEN(lcname)); - if (zend_hash_find(&(*ce)->function_table, lcname, strlen(lcname)+1, (void**)&fbc) == SUCCESS) { - phpdbg_notice("%s Method %s", + if ((fbc = zend_hash_find_ptr(&ce->function_table, lcname))) { + phpdbg_notice("printinfo", "type=\"%s\" flags=\"Method\" symbol=\"%s\" num=\"%d\"", "%s Method %s (%d ops)", (fbc->type == ZEND_USER_FUNCTION) ? "User" : "Internal", - fbc->common.function_name); + ZSTR_VAL(fbc->common.function_name), + (fbc->type == ZEND_USER_FUNCTION) ? fbc->op_array.last : 0); - phpdbg_print_function_helper(fbc TSRMLS_CC); + phpdbg_print_function_helper(fbc); } else { - phpdbg_error("The method %s could not be found", param->method.name); + phpdbg_error("print", "type=\"nomethod\" method=\"%s::%s\"", "The method %s::%s could not be found", param->method.class, param->method.name); } - efree(lcname); + zend_string_release(lcname); } else { - phpdbg_error("The class %s could not be found", param->method.class); + phpdbg_error("print", "type=\"noclass\" class=\"%s\"", "The class %s could not be found", param->method.class); } return SUCCESS; @@ -215,7 +214,7 @@ PHPDBG_PRINT(func) /* {{{ */ zend_function* fbc; const char *func_name = param->str; size_t func_name_len = param->len; - char *lcname; + zend_string *lcname; /* search active scope if begins with period */ if (func_name[0] == '.') { if (EG(scope)) { @@ -224,30 +223,197 @@ PHPDBG_PRINT(func) /* {{{ */ func_table = &EG(scope)->function_table; } else { - phpdbg_error("No active class"); + phpdbg_error("inactive", "type=\"noclasses\"", "No active class"); return SUCCESS; } } else if (!EG(function_table)) { - phpdbg_error("No function table loaded"); + phpdbg_error("inactive", "type=\"function_table\"", "No function table loaded"); return SUCCESS; } else { func_table = EG(function_table); } - lcname = zend_str_tolower_dup(func_name, func_name_len); + lcname = zend_string_alloc(func_name_len, 0); + zend_str_tolower_copy(ZSTR_VAL(lcname), func_name, ZSTR_LEN(lcname)); - if (zend_hash_find(func_table, lcname, strlen(lcname)+1, (void**)&fbc) == SUCCESS) { - phpdbg_notice("%s %s %s", - (fbc->type == ZEND_USER_FUNCTION) ? "User" : "Internal", - (fbc->common.scope) ? "Method" : "Function", - fbc->common.function_name); + phpdbg_try_access { + if ((fbc = zend_hash_find_ptr(func_table, lcname))) { + phpdbg_notice("printinfo", "type=\"%s\" flags=\"%s\" symbol=\"%s\" num=\"%d\"", "%s %s %s (%d ops)", + (fbc->type == ZEND_USER_FUNCTION) ? "User" : "Internal", + (fbc->common.scope) ? "Method" : "Function", + ZSTR_VAL(fbc->common.function_name), + (fbc->type == ZEND_USER_FUNCTION) ? fbc->op_array.last : 0); - phpdbg_print_function_helper(fbc TSRMLS_CC); - } else { - phpdbg_error("The function %s could not be found", func_name); - } + phpdbg_print_function_helper(fbc); + } else { + phpdbg_error("print", "type=\"nofunction\" function=\"%s\"", "The function %s could not be found", func_name); + } + } phpdbg_catch_access { + phpdbg_error("signalsegv", "function=\"%.*s\"", "Couldn't fetch function %.*s, invalid data source", (int) func_name_len, func_name); + } phpdbg_end_try_access(); efree(lcname); return SUCCESS; } /* }}} */ + +void phpdbg_print_opcodes_main() { + phpdbg_out("function name: (null)\n"); + phpdbg_print_function_helper((zend_function *) PHPDBG_G(ops)); +} + +void phpdbg_print_opcodes_function(const char *function, size_t len) { + zend_function *func = zend_hash_str_find_ptr(EG(function_table), function, len); + + if (!func) { + zend_string *rt_name; + ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), rt_name, func) { + if (func->type == ZEND_USER_FUNCTION && *rt_name->val == '\0') { + if (func->op_array.function_name->len == len && !zend_binary_strcasecmp(function, len, func->op_array.function_name->val, func->op_array.function_name->len)) { + phpdbg_print_opcodes_function(rt_name->val, rt_name->len); + } + } + } ZEND_HASH_FOREACH_END(); + + return; + } + + phpdbg_out("function name: %.*s\n", (int) ZSTR_LEN(func->op_array.function_name), ZSTR_VAL(func->op_array.function_name)); + phpdbg_print_function_helper(func); +} + +static void phpdbg_print_opcodes_method_ce(zend_class_entry *ce, const char *function) { + zend_function *func; + + if (ce->type != ZEND_USER_CLASS) { + phpdbg_out("function name: %s::%s (internal)\n", ce->name->val, function); + return; + } + + if (!(func = zend_hash_str_find_ptr(&ce->function_table, function, strlen(function)))) { + return; + } + + phpdbg_out("function name: %s::%s\n", ce->name->val, function); + phpdbg_print_function_helper(func); +} + +void phpdbg_print_opcodes_method(const char *class, const char *function) { + zend_class_entry *ce; + + if (phpdbg_safe_class_lookup(class, strlen(class), &ce) != SUCCESS) { + zend_string *rt_name; + ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), rt_name, ce) { + if (ce->type == ZEND_USER_CLASS && *rt_name->val == '\0') { + if (ce->name->len == strlen(class) && !zend_binary_strcasecmp(class, strlen(class), ce->name->val, ce->name->len)) { + phpdbg_print_opcodes_method_ce(ce, function); + } + } + } ZEND_HASH_FOREACH_END(); + + return; + } + + phpdbg_print_opcodes_method_ce(ce, function); +} + +static void phpdbg_print_opcodes_ce(zend_class_entry *ce) { + zend_function *method; + zend_string *method_name; + zend_bool first = 1; + + phpdbg_out("%s %s: %s\n", + (ce->type == ZEND_USER_CLASS) ? + "user" : "internal", + (ce->ce_flags & ZEND_ACC_INTERFACE) ? + "interface" : + (ce->ce_flags & ZEND_ACC_ABSTRACT) ? + "abstract Class" : + "class", + ZSTR_VAL(ce->name)); + + if (ce->type != ZEND_USER_CLASS) { + return; + } + + phpdbg_out("%d methods: ", zend_hash_num_elements(&ce->function_table)); + ZEND_HASH_FOREACH_PTR(&ce->function_table, method) { + if (first) { + first = 0; + } else { + phpdbg_out(", "); + } + phpdbg_out("%s", ZSTR_VAL(method->common.function_name)); + } ZEND_HASH_FOREACH_END(); + if (first) { + phpdbg_out("-"); + } + phpdbg_out("\n"); + + ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, method_name, method) { + phpdbg_out("\nfunction name: %s\n", ZSTR_VAL(method_name)); + phpdbg_print_function_helper(method); + } ZEND_HASH_FOREACH_END(); +} + +void phpdbg_print_opcodes_class(const char *class) { + zend_class_entry *ce; + + if (phpdbg_safe_class_lookup(class, strlen(class), &ce) != SUCCESS) { + zend_string *rt_name; + ZEND_HASH_FOREACH_STR_KEY_PTR(EG(class_table), rt_name, ce) { + if (ce->type == ZEND_USER_CLASS && *rt_name->val == '\0') { + if (ce->name->len == strlen(class) && !zend_binary_strcasecmp(class, strlen(class), ce->name->val, ce->name->len)) { + phpdbg_print_opcodes_ce(ce); + } + } + } ZEND_HASH_FOREACH_END(); + + return; + } + + phpdbg_print_opcodes_ce(ce); +} + +PHPDBG_API void phpdbg_print_opcodes(char *function) +{ + if (function == NULL) { + phpdbg_print_opcodes_main(); + } else if (function[0] == '*' && function[1] == 0) { + /* all */ + zend_string *name; + zend_function *func; + zend_class_entry *ce; + + phpdbg_print_opcodes_main(); + + ZEND_HASH_FOREACH_STR_KEY_PTR(EG(function_table), name, func) { + if (func->type == ZEND_USER_FUNCTION) { + phpdbg_out("\n"); + phpdbg_print_opcodes_function(ZSTR_VAL(name), ZSTR_LEN(name)); + } + } ZEND_HASH_FOREACH_END(); + + ZEND_HASH_FOREACH_PTR(EG(class_table), ce) { + if (ce->type == ZEND_USER_CLASS) { + phpdbg_out("\n\n"); + phpdbg_print_opcodes_ce(ce); + } + } ZEND_HASH_FOREACH_END(); + } else { + function = zend_str_tolower_dup(function, strlen(function)); + + if (strstr(function, "::") == NULL) { + phpdbg_print_opcodes_function(function, strlen(function)); + } else { + char *method_name, *class_name = strtok(function, "::"); + if ((method_name = strtok(NULL, "::")) == NULL) { + phpdbg_print_opcodes_class(class_name); + } else { + phpdbg_print_opcodes_method(class_name, method_name); + } + } + + efree(function); + } +} diff --git a/sapi/phpdbg/phpdbg_print.h b/sapi/phpdbg/phpdbg_print.h index a0166241fa..b8e18fedaf 100644 --- a/sapi/phpdbg/phpdbg_print.h +++ b/sapi/phpdbg/phpdbg_print.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -35,6 +35,8 @@ PHPDBG_PRINT(method); PHPDBG_PRINT(func); PHPDBG_PRINT(stack); +PHPDBG_API void phpdbg_print_opcodes(char *function); + extern const phpdbg_command_t phpdbg_print_commands[]; #endif /* PHPDBG_PRINT_H */ diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index b63018b1ee..a01c8a399f 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -22,12 +22,16 @@ #include <string.h> #include "zend.h" #include "zend_compile.h" +#include "zend_exceptions.h" +#include "zend_vm.h" +#include "zend_generators.h" +#include "zend_interfaces.h" #include "phpdbg.h" + #include "phpdbg_help.h" #include "phpdbg_print.h" #include "phpdbg_info.h" #include "phpdbg_break.h" -#include "phpdbg_bp.h" #include "phpdbg_opcode.h" #include "phpdbg_list.h" #include "phpdbg_utils.h" @@ -37,253 +41,301 @@ #include "phpdbg_frame.h" #include "phpdbg_lexer.h" #include "phpdbg_parser.h" +#include "phpdbg_wait.h" +#include "phpdbg_eol.h" + +#if ZEND_VM_KIND != ZEND_VM_KIND_CALL +#error "phpdbg can only be built with CALL zend vm kind" +#endif + +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) +extern int phpdbg_startup_run; + +#ifdef HAVE_LIBDL +#ifdef PHP_WIN32 +#include "win32/param.h" +#include "win32/winutil.h" +#define GET_DL_ERROR() php_win_err() +#elif defined(NETWARE) +#include <sys/param.h> +#define GET_DL_ERROR() dlerror() +#else +#include <sys/param.h> +#define GET_DL_ERROR() DL_ERROR() +#endif +#endif /* {{{ command declarations */ const phpdbg_command_t phpdbg_prompt_commands[] = { - PHPDBG_COMMAND_D(exec, "set execution context", 'e', NULL, "s"), - PHPDBG_COMMAND_D(step, "step through execution", 's', NULL, 0), - PHPDBG_COMMAND_D(continue,"continue execution", 'c', NULL, 0), - PHPDBG_COMMAND_D(run, "attempt execution", 'r', NULL, "|s"), - PHPDBG_COMMAND_D(ev, "evaluate some code", 0, NULL, "i"), - PHPDBG_COMMAND_D(until, "continue past the current line", 'u', NULL, 0), - PHPDBG_COMMAND_D(finish, "continue past the end of the stack", 'F', NULL, 0), - PHPDBG_COMMAND_D(leave, "continue until the end of the stack", 'L', NULL, 0), - PHPDBG_COMMAND_D(print, "print something", 'p', phpdbg_print_commands, 0), - PHPDBG_COMMAND_D(break, "set breakpoint", 'b', phpdbg_break_commands, "|*c"), - PHPDBG_COMMAND_D(back, "show trace", 't', NULL, "|n"), - PHPDBG_COMMAND_D(frame, "switch to a frame", 'f', NULL, "|n"), - PHPDBG_COMMAND_D(list, "lists some code", 'l', phpdbg_list_commands, "*"), - PHPDBG_COMMAND_D(info, "displays some informations", 'i', phpdbg_info_commands, "s"), - PHPDBG_COMMAND_D(clean, "clean the execution environment", 'X', NULL, 0), - PHPDBG_COMMAND_D(clear, "clear breakpoints", 'C', NULL, 0), - PHPDBG_COMMAND_D(help, "show help menu", 'h', phpdbg_help_commands, "|s"), - PHPDBG_COMMAND_D(set, "set phpdbg configuration", 'S', phpdbg_set_commands, "s"), - PHPDBG_COMMAND_D(register,"register a function", 'R', NULL, "s"), - PHPDBG_COMMAND_D(source, "execute a phpdbginit", '<', NULL, "s"), - PHPDBG_COMMAND_D(export, "export breaks to a .phpdbginit script", '>', NULL, "s"), - PHPDBG_COMMAND_D(sh, "shell a command", 0, NULL, "i"), - PHPDBG_COMMAND_D(quit, "exit phpdbg", 'q', NULL, 0), - PHPDBG_COMMAND_D(watch, "set watchpoint", 'w', phpdbg_watch_commands, "|ss"), + PHPDBG_COMMAND_D(exec, "set execution context", 'e', NULL, "s", 0), + PHPDBG_COMMAND_D(step, "step through execution", 's', NULL, 0, PHPDBG_ASYNC_SAFE), + PHPDBG_COMMAND_D(continue,"continue execution", 'c', NULL, 0, PHPDBG_ASYNC_SAFE), + PHPDBG_COMMAND_D(run, "attempt execution", 'r', NULL, "|s", 0), + PHPDBG_COMMAND_D(ev, "evaluate some code", 0 , NULL, "i", PHPDBG_ASYNC_SAFE), /* restricted ASYNC_SAFE */ + PHPDBG_COMMAND_D(until, "continue past the current line", 'u', NULL, 0, 0), + PHPDBG_COMMAND_D(finish, "continue past the end of the stack", 'F', NULL, 0, 0), + PHPDBG_COMMAND_D(leave, "continue until the end of the stack", 'L', NULL, 0, 0), + PHPDBG_COMMAND_D(print, "print something", 'p', phpdbg_print_commands, "|*c", 0), + PHPDBG_COMMAND_D(break, "set breakpoint", 'b', phpdbg_break_commands, "|*c", 0), + PHPDBG_COMMAND_D(back, "show trace", 't', NULL, "|n", PHPDBG_ASYNC_SAFE), + PHPDBG_COMMAND_D(frame, "switch to a frame", 'f', NULL, "|n", PHPDBG_ASYNC_SAFE), + PHPDBG_COMMAND_D(list, "lists some code", 'l', phpdbg_list_commands, "*", PHPDBG_ASYNC_SAFE), + PHPDBG_COMMAND_D(info, "displays some informations", 'i', phpdbg_info_commands, "|s", PHPDBG_ASYNC_SAFE), + PHPDBG_COMMAND_D(clean, "clean the execution environment", 'X', NULL, 0, 0), + PHPDBG_COMMAND_D(clear, "clear breakpoints", 'C', NULL, 0, 0), + PHPDBG_COMMAND_D(help, "show help menu", 'h', phpdbg_help_commands, "|s", PHPDBG_ASYNC_SAFE), + PHPDBG_COMMAND_D(set, "set phpdbg configuration", 'S', phpdbg_set_commands, "s", PHPDBG_ASYNC_SAFE), + PHPDBG_COMMAND_D(register,"register a function", 'R', NULL, "s", 0), + PHPDBG_COMMAND_D(source, "execute a phpdbginit", '<', NULL, "s", 0), + PHPDBG_COMMAND_D(export, "export breaks to a .phpdbginit script", '>', NULL, "s", PHPDBG_ASYNC_SAFE), + PHPDBG_COMMAND_D(sh, "shell a command", 0 , NULL, "i", 0), + PHPDBG_COMMAND_D(quit, "exit phpdbg", 'q', NULL, 0, PHPDBG_ASYNC_SAFE), + PHPDBG_COMMAND_D(wait, "wait for other process", 'W', NULL, 0, 0), + PHPDBG_COMMAND_D(watch, "set watchpoint", 'w', phpdbg_watch_commands, "|ss", 0), + PHPDBG_COMMAND_D(next, "step over next line", 'n', NULL, 0, PHPDBG_ASYNC_SAFE), + PHPDBG_COMMAND_D(eol, "set EOL", 'E', NULL, "|s", 0), PHPDBG_END_COMMAND }; /* }}} */ -ZEND_EXTERN_MODULE_GLOBALS(phpdbg); - -static inline int phpdbg_call_register(phpdbg_param_t *stack TSRMLS_DC) /* {{{ */ +static inline int phpdbg_call_register(phpdbg_param_t *stack) /* {{{ */ { phpdbg_param_t *name = NULL; if (stack->type == STACK_PARAM) { + char *lc_name; + name = stack->next; - + if (!name || name->type != STR_PARAM) { return FAILURE; } - - if (zend_hash_exists( - &PHPDBG_G(registered), name->str, name->len+1)) { - zval fname, *fretval; - zend_fcall_info fci; + lc_name = zend_str_tolower_dup(name->str, name->len); - ZVAL_STRINGL(&fname, name->str, name->len, 1); + if (zend_hash_str_exists(&PHPDBG_G(registered), lc_name, name->len)) { + zval fretval; + zend_fcall_info fci; memset(&fci, 0, sizeof(zend_fcall_info)); + ZVAL_STRINGL(&fci.function_name, lc_name, name->len); fci.size = sizeof(zend_fcall_info); fci.function_table = &PHPDBG_G(registered); - fci.function_name = &fname; - fci.symbol_table = EG(active_symbol_table); - fci.object_ptr = NULL; - fci.retval_ptr_ptr = &fretval; + //???fci.symbol_table = zend_rebuild_symbol_table(); + fci.symbol_table = NULL; + fci.object = NULL; + fci.retval = &fretval; fci.no_separation = 1; if (name->next) { zval params; phpdbg_param_t *next = name->next; - + array_init(¶ms); while (next) { char *buffered = NULL; - + switch (next->type) { case OP_PARAM: case COND_PARAM: case STR_PARAM: - add_next_index_stringl( - ¶ms, - next->str, - next->len, 1); + add_next_index_stringl(¶ms, next->str, next->len); break; - + case NUMERIC_PARAM: add_next_index_long(¶ms, next->num); break; - + case METHOD_PARAM: - spprintf(&buffered, 0, "%s::%s", - next->method.class, next->method.name); - add_next_index_string(¶ms, buffered, 0); + spprintf(&buffered, 0, "%s::%s", next->method.class, next->method.name); + add_next_index_string(¶ms, buffered); break; - + case NUMERIC_METHOD_PARAM: - spprintf(&buffered, 0, "%s::%s#%ld", - next->method.class, next->method.name, next->num); - add_next_index_string(¶ms, buffered, 0); + spprintf(&buffered, 0, "%s::%s#%ld", next->method.class, next->method.name, next->num); + add_next_index_string(¶ms, buffered); break; - + case NUMERIC_FUNCTION_PARAM: - spprintf(&buffered, 0, "%s#%ld", - next->str, next->num); - add_next_index_string(¶ms, buffered, 0); + spprintf(&buffered, 0, "%s#%ld", next->str, next->num); + add_next_index_string(¶ms, buffered); break; - + case FILE_PARAM: - spprintf(&buffered, 0, "%s:%ld", - next->file.name, next->file.line); - add_next_index_string(¶ms, buffered, 0); + spprintf(&buffered, 0, "%s:%ld", next->file.name, next->file.line); + add_next_index_string(¶ms, buffered); break; - + case NUMERIC_FILE_PARAM: - spprintf(&buffered, 0, "%s:#%ld", - next->file.name, next->file.line); - add_next_index_string(¶ms, buffered, 0); + spprintf(&buffered, 0, "%s:#%ld", next->file.name, next->file.line); + add_next_index_string(¶ms, buffered); break; - + default: { /* not yet */ } } - - next = next->next; + + next = next->next; } - zend_fcall_info_args(&fci, ¶ms TSRMLS_CC); + zend_fcall_info_args(&fci, ¶ms); } else { fci.params = NULL; fci.param_count = 0; } - phpdbg_debug( - "created %d params from arguments", - fci.param_count); + phpdbg_activate_err_buf(0); + phpdbg_free_err_buf(); - zend_call_function(&fci, NULL TSRMLS_CC); + phpdbg_debug("created %d params from arguments", fci.param_count); - if (fretval) { - zend_print_zval_r( - fretval, 0 TSRMLS_CC); - phpdbg_writeln(EMPTY); + if (zend_call_function(&fci, NULL) == SUCCESS) { + zend_print_zval_r(&fretval, 0); + phpdbg_out("\n"); + zval_ptr_dtor(&fretval); } - zval_dtor(&fname); + zval_dtor(&fci.function_name); + efree(lc_name); return SUCCESS; - } + } + + efree(lc_name); } return FAILURE; } /* }}} */ -void phpdbg_try_file_init(char *init_file, size_t init_file_len, zend_bool free_init TSRMLS_DC) /* {{{ */ -{ - struct stat sb; - - if (init_file && VCWD_STAT(init_file, &sb) != -1) { - FILE *fp = fopen(init_file, "r"); - if (fp) { - int line = 1; +struct phpdbg_init_state { + int line; + zend_bool in_code; + char *code; + size_t code_len; + const char *init_file; +}; - char cmd[PHPDBG_MAX_CMD]; - size_t cmd_len = 0L; - char *code = NULL; - size_t code_len = 0L; - zend_bool in_code = 0; +static void phpdbg_line_init(char *cmd, struct phpdbg_init_state *state) { + size_t cmd_len = strlen(cmd); - while (fgets(cmd, PHPDBG_MAX_CMD, fp) != NULL) { - cmd_len = strlen(cmd)-1; - - while (cmd_len > 0L && isspace(cmd[cmd_len-1])) - cmd_len--; - - cmd[cmd_len] = '\0'; - - if (*cmd && cmd_len > 0L && cmd[0] != '#') { - if (cmd_len == 2) { - if (memcmp(cmd, "<:", sizeof("<:")-1) == SUCCESS) { - in_code = 1; - goto next_line; - } else { - if (memcmp(cmd, ":>", sizeof(":>")-1) == SUCCESS) { - in_code = 0; - code[code_len] = '\0'; - { - zend_eval_stringl( - code, code_len, NULL, "phpdbginit code" TSRMLS_CC); - } - free(code); - code = NULL; - goto next_line; - } - } - } + state->line++; - if (in_code) { - if (code == NULL) { - code = malloc(cmd_len + 1); - } else code = realloc(code, code_len + cmd_len + 1); + while (cmd_len > 0L && isspace(cmd[cmd_len-1])) { + cmd_len--; + } - if (code) { - memcpy( - &code[code_len], cmd, cmd_len); - code_len += cmd_len; - } - goto next_line; - } + cmd[cmd_len] = '\0'; + + if (*cmd && cmd_len > 0L && cmd[0] != '#') { + if (cmd_len == 2) { + if (memcmp(cmd, "<:", sizeof("<:")-1) == SUCCESS) { + state->in_code = 1; + return; + } else { + if (memcmp(cmd, ":>", sizeof(":>")-1) == SUCCESS) { + state->in_code = 0; + state->code[state->code_len] = '\0'; + zend_eval_stringl(state->code, state->code_len, NULL, "phpdbginit code"); + free(state->code); + state->code = NULL; + return; + } + } + } - { - char *why = NULL; - char *input = phpdbg_read_input(cmd TSRMLS_CC); - phpdbg_param_t stack; - - phpdbg_init_param(&stack, STACK_PARAM); - - if (phpdbg_do_parse(&stack, input TSRMLS_CC) <= 0) { - switch (phpdbg_stack_execute(&stack, &why TSRMLS_CC)) { - case FAILURE: -// if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) { - if (phpdbg_call_register(&stack TSRMLS_CC) == FAILURE) { - phpdbg_error( - "Unrecognized command in %s:%d: %s, %s!", - init_file, line, input, why); - } -// } - break; + if (state->in_code) { + if (state->code == NULL) { + state->code = malloc(cmd_len + 1); + } else { + state->code = realloc(state->code, state->code_len + cmd_len + 1); + } + + if (state->code) { + memcpy(&state->code[state->code_len], cmd, cmd_len); + state->code_len += cmd_len; + } + + return; + } + + zend_try { + char *input = phpdbg_read_input(cmd); + phpdbg_param_t stack; + + phpdbg_init_param(&stack, STACK_PARAM); + + phpdbg_activate_err_buf(1); + + if (phpdbg_do_parse(&stack, input) <= 0) { + switch (phpdbg_stack_execute(&stack, 1 /* allow_async_unsafe == 1 */)) { + case FAILURE: + phpdbg_activate_err_buf(0); + if (phpdbg_call_register(&stack) == FAILURE) { + if (state->init_file) { + phpdbg_output_err_buf("initfailure", "%b file=\"%s\" line=\"%d\" input=\"%s\"", "Unrecognized command in %s:%d: %s, %b!", state->init_file, state->line, input); + } else { + phpdbg_output_err_buf("initfailure", "%b line=\"%d\" input=\"%s\"", "Unrecognized command on line %d: %s, %b!", state->line, input); } } + break; + } + } - if (why) { - free(why); - why = NULL; - } + phpdbg_activate_err_buf(0); + phpdbg_free_err_buf(); - phpdbg_stack_free(&stack); - phpdbg_destroy_input(&input TSRMLS_CC); - } - } -next_line: - line++; + phpdbg_stack_free(&stack); + phpdbg_destroy_input(&input); + } zend_catch { + PHPDBG_G(flags) &= ~(PHPDBG_IS_RUNNING | PHPDBG_IS_CLEANING); + if (PHPDBG_G(flags) & PHPDBG_IS_QUITTING) { + zend_bailout(); } + } zend_end_try(); + } + +} + +void phpdbg_string_init(char *buffer) { + struct phpdbg_init_state state = {0}; + char *str = strtok(buffer, "\n"); + + while (str) { + phpdbg_line_init(str, &state); - if (code) { - free(code); + str = strtok(NULL, "\n"); + } + + if (state.code) { + free(state.code); + } +} + +void phpdbg_try_file_init(char *init_file, size_t init_file_len, zend_bool free_init) /* {{{ */ +{ + zend_stat_t sb; + + if (init_file && VCWD_STAT(init_file, &sb) != -1) { + FILE *fp = fopen(init_file, "r"); + if (fp) { + char cmd[PHPDBG_MAX_CMD]; + struct phpdbg_init_state state = {0}; + + state.init_file = init_file; + + while (fgets(cmd, PHPDBG_MAX_CMD, fp) != NULL) { + phpdbg_line_init(cmd, &state); + } + + if (state.code) { + free(state.code); } fclose(fp); } else { - phpdbg_error( - "Failed to open %s for initialization", init_file); + phpdbg_error("initfailure", "type=\"openfile\" file=\"%s\"", "Failed to open %s for initialization", init_file); } if (free_init) { @@ -292,13 +344,16 @@ next_line: } } /* }}} */ -void phpdbg_init(char *init_file, size_t init_file_len, zend_bool use_default TSRMLS_DC) /* {{{ */ +void phpdbg_init(char *init_file, size_t init_file_len, zend_bool use_default) /* {{{ */ { if (!init_file && use_default) { char *scan_dir = getenv("PHP_INI_SCAN_DIR"); + char *sys_ini; int i; - phpdbg_try_file_init(PHPDBG_STRL(PHP_CONFIG_FILE_PATH "/" PHPDBG_INIT_FILENAME), 0 TSRMLS_CC); + ZEND_IGNORE_VALUE(asprintf(&sys_ini, "%s/" PHPDBG_INIT_FILENAME, PHP_CONFIG_FILE_PATH)); + phpdbg_try_file_init(sys_ini, strlen(sys_ini), 0); + free(sys_ini); if (!scan_dir) { scan_dir = PHP_CONFIG_FILE_SCAN_DIR; @@ -315,93 +370,135 @@ void phpdbg_init(char *init_file, size_t init_file_len, zend_bool use_default TS scan_dir[i] = 0; } - asprintf( - &init_file, "%s/%s", scan_dir, PHPDBG_INIT_FILENAME); - phpdbg_try_file_init(init_file, strlen(init_file), 1 TSRMLS_CC); + ZEND_IGNORE_VALUE(asprintf(&init_file, "%s/%s", scan_dir, PHPDBG_INIT_FILENAME)); + phpdbg_try_file_init(init_file, strlen(init_file), 1); if (i == -1) { break; } scan_dir += i + 1; } - phpdbg_try_file_init(PHPDBG_STRL(PHPDBG_INIT_FILENAME), 0 TSRMLS_CC); + phpdbg_try_file_init(PHPDBG_STRL(PHPDBG_INIT_FILENAME), 0); } else { - phpdbg_try_file_init(init_file, init_file_len, 1 TSRMLS_CC); + phpdbg_try_file_init(init_file, init_file_len, 1); } } +/* }}} */ + +void phpdbg_clean(zend_bool full) /* {{{ */ +{ + /* this is implicitly required */ + if (PHPDBG_G(ops)) { + destroy_op_array(PHPDBG_G(ops)); + efree(PHPDBG_G(ops)); + PHPDBG_G(ops) = NULL; + } + + if (full) { + PHPDBG_G(flags) |= PHPDBG_IS_CLEANING; + } +} /* }}} */ PHPDBG_COMMAND(exec) /* {{{ */ { - struct stat sb; + zend_stat_t sb; if (VCWD_STAT(param->str, &sb) != FAILURE) { if (sb.st_mode & (S_IFREG|S_IFLNK)) { - char *res = phpdbg_resolve_path(param->str TSRMLS_CC); + char *res = phpdbg_resolve_path(param->str); size_t res_len = strlen(res); if ((res_len != PHPDBG_G(exec_len)) || (memcmp(res, PHPDBG_G(exec), res_len) != SUCCESS)) { + if (PHPDBG_G(in_execution)) { + if (phpdbg_ask_user_permission("Do you really want to stop execution to set a new execution context?") == FAILURE) { + return FAILURE; + } + } if (PHPDBG_G(exec)) { - phpdbg_notice("Unsetting old execution context: %s", PHPDBG_G(exec)); + phpdbg_notice("exec", "type=\"unset\" context=\"%s\"", "Unsetting old execution context: %s", PHPDBG_G(exec)); efree(PHPDBG_G(exec)); PHPDBG_G(exec) = NULL; PHPDBG_G(exec_len) = 0L; } if (PHPDBG_G(ops)) { - phpdbg_notice("Destroying compiled opcodes"); - phpdbg_clean(0 TSRMLS_CC); + phpdbg_notice("exec", "type=\"unsetops\"", "Destroying compiled opcodes"); + phpdbg_clean(0); } PHPDBG_G(exec) = res; PHPDBG_G(exec_len) = res_len; - + + VCWD_CHDIR_FILE(res); + *SG(request_info).argv = PHPDBG_G(exec); - php_hash_environment(TSRMLS_C); + php_build_argv(NULL, &PG(http_globals)[TRACK_VARS_SERVER]); - phpdbg_notice("Set execution context: %s", PHPDBG_G(exec)); + phpdbg_notice("exec", "type=\"set\" context=\"%s\"", "Set execution context: %s", PHPDBG_G(exec)); - if (phpdbg_compile(TSRMLS_C) == FAILURE) { - phpdbg_error("Failed to compile %s", PHPDBG_G(exec)); + if (PHPDBG_G(in_execution)) { + phpdbg_clean(1); + return SUCCESS; } + + phpdbg_compile(); } else { - phpdbg_notice("Execution context not changed"); + phpdbg_notice("exec", "type=\"unchanged\"", "Execution context not changed"); } } else { - phpdbg_error("Cannot use %s as execution context, not a valid file or symlink", param->str); + phpdbg_error("exec", "type=\"invalid\" context=\"%s\"", "Cannot use %s as execution context, not a valid file or symlink", param->str); } } else { - phpdbg_error("Cannot stat %s, ensure the file exists", param->str); + phpdbg_error("exec", "type=\"notfound\" context=\"%s\"", "Cannot stat %s, ensure the file exists", param->str); } return SUCCESS; } /* }}} */ -int phpdbg_compile(TSRMLS_D) /* {{{ */ +int phpdbg_compile(void) /* {{{ */ { zend_file_handle fh; + char *buf; + size_t len; if (!PHPDBG_G(exec)) { - phpdbg_error("No execution context"); - return SUCCESS; - } - - if (EG(in_execution)) { - phpdbg_error("Cannot compile while in execution"); + phpdbg_error("inactive", "type=\"nocontext\"", "No execution context"); return FAILURE; } - phpdbg_notice("Attempting compilation of %s", PHPDBG_G(exec)); + if (php_stream_open_for_zend_ex(PHPDBG_G(exec), &fh, USE_PATH|STREAM_OPEN_FOR_INCLUDE) == SUCCESS && zend_stream_fixup(&fh, &buf, &len) == SUCCESS) { + /* Skip #! line */ + if (len >= 3 && buf[0] == '#' && buf[1] == '!') { + char *end = buf + len; + do { + switch (fh.handle.stream.mmap.buf++[0]) { + case '\r': + if (fh.handle.stream.mmap.buf[0] == '\n') { + fh.handle.stream.mmap.buf++; + } + case '\n': + CG(start_lineno) = 2; + fh.handle.stream.mmap.len -= fh.handle.stream.mmap.buf - buf; + end = fh.handle.stream.mmap.buf; + } + } while (fh.handle.stream.mmap.buf + 1 < end); + } + + PHPDBG_G(ops) = zend_compile_file(&fh, ZEND_INCLUDE); - if (php_stream_open_for_zend_ex(PHPDBG_G(exec), &fh, - USE_PATH|STREAM_OPEN_FOR_INCLUDE TSRMLS_CC) == SUCCESS) { + fh.handle.stream.mmap.buf = buf; + fh.handle.stream.mmap.len = len; + zend_destroy_file_handle(&fh); + if (EG(exception)) { + zend_exception_error(EG(exception), E_ERROR); + zend_bailout(); + } - PHPDBG_G(ops) = zend_compile_file(&fh, ZEND_INCLUDE TSRMLS_CC); - zend_destroy_file_handle(&fh TSRMLS_CC); + phpdbg_notice("compile", "context=\"%s\"", "Successful compilation of %s", PHPDBG_G(exec)); - phpdbg_notice("Success"); return SUCCESS; } else { - phpdbg_error("Could not open file %s", PHPDBG_G(exec)); + phpdbg_error("compile", "type=\"openfailure\" context=\"%s\"", "Could not open file %s", PHPDBG_G(exec)); } return FAILURE; @@ -409,7 +506,7 @@ int phpdbg_compile(TSRMLS_D) /* {{{ */ PHPDBG_COMMAND(step) /* {{{ */ { - if (EG(in_execution)) { + if (PHPDBG_G(in_execution)) { PHPDBG_G(flags) |= PHPDBG_IS_STEPPING; } @@ -421,62 +518,83 @@ PHPDBG_COMMAND(continue) /* {{{ */ return PHPDBG_NEXT; } /* }}} */ +int phpdbg_skip_line_helper() /* {{{ */ { + zend_execute_data *ex = phpdbg_user_execute_data(EG(current_execute_data)); + const zend_op_array *op_array = &ex->func->op_array; + const zend_op *opline = op_array->opcodes; + + PHPDBG_G(flags) |= PHPDBG_IN_UNTIL; + PHPDBG_G(seek_ex) = ex; + do { + if (opline->lineno != ex->opline->lineno + || opline->opcode == ZEND_RETURN + || opline->opcode == ZEND_FAST_RET + || opline->opcode == ZEND_GENERATOR_RETURN + || opline->opcode == ZEND_EXIT + || opline->opcode == ZEND_YIELD + || opline->opcode == ZEND_YIELD_FROM + ) { + zend_hash_index_update_ptr(&PHPDBG_G(seek), (zend_ulong) opline, (void *) opline); + } + } while (++opline < op_array->opcodes + op_array->last); + + return PHPDBG_UNTIL; +} +/* }}} */ + PHPDBG_COMMAND(until) /* {{{ */ { - if (!EG(in_execution)) { - phpdbg_error("Not executing"); + if (!PHPDBG_G(in_execution)) { + phpdbg_error("inactive", "type=\"noexec\"", "Not executing"); return SUCCESS; } - PHPDBG_G(flags) |= PHPDBG_IN_UNTIL; - { - zend_uint next = 0, - self = (EG(current_execute_data)->opline - EG(active_op_array)->opcodes); - zend_op *opline = &EG(active_op_array)->opcodes[self]; - - for (next = self; next < EG(active_op_array)->last; next++) { - if (EG(active_op_array)->opcodes[next].lineno != opline->lineno) { - zend_hash_index_update( - &PHPDBG_G(seek), - (zend_ulong) &EG(active_op_array)->opcodes[next], - &EG(active_op_array)->opcodes[next], - sizeof(zend_op), NULL); - break; - } - } + return phpdbg_skip_line_helper(); +} /* }}} */ + +PHPDBG_COMMAND(next) /* {{{ */ +{ + if (!PHPDBG_G(in_execution)) { + phpdbg_error("inactive", "type=\"noexec\"", "Not executing"); + return SUCCESS; } - return PHPDBG_UNTIL; + PHPDBG_G(flags) |= PHPDBG_IS_STEPPING; + return phpdbg_skip_line_helper(); } /* }}} */ +static void phpdbg_seek_to_end(void) /* {{{ */ { + zend_execute_data *ex = phpdbg_user_execute_data(EG(current_execute_data)); + const zend_op_array *op_array = &ex->func->op_array; + const zend_op *opline = op_array->opcodes; + + PHPDBG_G(seek_ex) = ex; + do { + switch (opline->opcode) { + case ZEND_RETURN: + case ZEND_FAST_RET: + case ZEND_GENERATOR_RETURN: + case ZEND_EXIT: + case ZEND_YIELD: + case ZEND_YIELD_FROM: + zend_hash_index_update_ptr(&PHPDBG_G(seek), (zend_ulong) opline, (void *) opline); + } + } while (++opline < op_array->opcodes + op_array->last); +} +/* }}} */ + PHPDBG_COMMAND(finish) /* {{{ */ { - if (!EG(in_execution)) { - phpdbg_error("Not executing"); + if (!PHPDBG_G(in_execution)) { + phpdbg_error("inactive", "type=\"noexec\"", "Not executing"); return SUCCESS; } - PHPDBG_G(flags) |= PHPDBG_IN_FINISH; - { - zend_uint next = 0, - self = (EG(current_execute_data)->opline - EG(active_op_array)->opcodes); - - for (next = self; next < EG(active_op_array)->last; next++) { - switch (EG(active_op_array)->opcodes[next].opcode) { - case ZEND_RETURN: - case ZEND_THROW: - case ZEND_EXIT: -#ifdef ZEND_YIELD - case ZEND_YIELD: -#endif - zend_hash_index_update( - &PHPDBG_G(seek), - (zend_ulong) &EG(active_op_array)->opcodes[next], - &EG(active_op_array)->opcodes[next], - sizeof(zend_op), NULL); - break; - } - } + phpdbg_seek_to_end(); + if (zend_hash_index_exists(&PHPDBG_G(seek), (zend_ulong) phpdbg_user_execute_data(EG(current_execute_data))->opline)) { + zend_hash_clean(&PHPDBG_G(seek)); + } else { + PHPDBG_G(flags) |= PHPDBG_IN_FINISH; } return PHPDBG_FINISH; @@ -484,142 +602,114 @@ PHPDBG_COMMAND(finish) /* {{{ */ PHPDBG_COMMAND(leave) /* {{{ */ { - if (!EG(in_execution)) { - phpdbg_error("Not executing"); + if (!PHPDBG_G(in_execution)) { + phpdbg_error("inactive", "type=\"noexec\"", "Not executing"); return SUCCESS; } - PHPDBG_G(flags) |= PHPDBG_IN_LEAVE; - { - zend_uint next = 0, - self = (EG(current_execute_data)->opline - EG(active_op_array)->opcodes); - - for (next = self; next < EG(active_op_array)->last; next++) { - switch (EG(active_op_array)->opcodes[next].opcode) { - case ZEND_RETURN: - case ZEND_THROW: - case ZEND_EXIT: -#ifdef ZEND_YIELD - case ZEND_YIELD: -#endif - zend_hash_index_update( - &PHPDBG_G(seek), - (zend_ulong) &EG(active_op_array)->opcodes[next], - &EG(active_op_array)->opcodes[next], - sizeof(zend_op), NULL); - break; - } - } + phpdbg_seek_to_end(); + if (zend_hash_index_exists(&PHPDBG_G(seek), (zend_ulong) phpdbg_user_execute_data(EG(current_execute_data))->opline)) { + zend_hash_clean(&PHPDBG_G(seek)); + phpdbg_notice("leave", "type=\"end\"", "Already at the end of the function"); + return SUCCESS; + } else { + PHPDBG_G(flags) |= PHPDBG_IN_LEAVE; + return PHPDBG_LEAVE; } - - return PHPDBG_LEAVE; } /* }}} */ PHPDBG_COMMAND(frame) /* {{{ */ { if (!param) { - phpdbg_notice("Currently in frame #%d", PHPDBG_G(frame).num); - } else phpdbg_switch_frame(param->num TSRMLS_CC); + phpdbg_notice("frame", "id=\"%d\"", "Currently in frame #%d", PHPDBG_G(frame).num); + } else { + phpdbg_switch_frame(param->num); + } return SUCCESS; } /* }}} */ -static inline void phpdbg_handle_exception(TSRMLS_D) /* }}} */ +static inline void phpdbg_handle_exception(void) /* {{{ */ { - zend_fcall_info fci; - - zval fname, - *trace, - exception; - - /* get filename and linenumber before unsetting exception */ - const char *filename = zend_get_executed_filename(TSRMLS_C); - zend_uint lineno = zend_get_executed_lineno(TSRMLS_C); + zend_object *ex = EG(exception); + zend_string *msg, *file; + zend_long line; + zval zv, rv, tmp; - /* copy exception */ - exception = *EG(exception); - zval_copy_ctor(&exception); EG(exception) = NULL; - phpdbg_error( - "Uncaught %s!", - Z_OBJCE(exception)->name); - - /* call __toString */ - ZVAL_STRINGL(&fname, "__tostring", sizeof("__tostring")-1, 1); - fci.size = sizeof(fci); - fci.function_table = &Z_OBJCE(exception)->function_table; - fci.function_name = &fname; - fci.symbol_table = NULL; - fci.object_ptr = &exception; - fci.retval_ptr_ptr = &trace; - fci.param_count = 0; - fci.params = NULL; - fci.no_separation = 1; - zend_call_function(&fci, NULL TSRMLS_CC); - - if (trace) { - phpdbg_writeln( - "Uncaught %s", Z_STRVAL_P(trace)); - /* remember to dtor trace */ - zval_ptr_dtor(&trace); + ZVAL_OBJ(&zv, ex); + zend_call_method_with_0_params(&zv, ex->ce, NULL, "__tostring", &tmp); + file = zval_get_string(zend_read_property(zend_get_exception_base(&zv), &zv, ZEND_STRL("file"), 1, &rv)); + line = zval_get_long(zend_read_property(zend_get_exception_base(&zv), &zv, ZEND_STRL("line"), 1, &rv)); + + if (EG(exception)) { + EG(exception) = NULL; + msg = ZSTR_EMPTY_ALLOC(); + } else { + zend_update_property_string(zend_get_exception_base(&zv), &zv, ZEND_STRL("string"), Z_STRVAL(tmp)); + zval_ptr_dtor(&tmp); + msg = zval_get_string(zend_read_property(zend_get_exception_base(&zv), &zv, ZEND_STRL("string"), 1, &rv)); } - /* output useful information about address */ - phpdbg_writeln( - "Stacked entered at %p in %s on line %u", - EG(active_op_array)->opcodes, filename, lineno); + phpdbg_error("exception", "name=\"%s\" file=\"%s\" line=\"" ZEND_LONG_FMT "\"", "Uncaught %s in %s on line " ZEND_LONG_FMT, ZSTR_VAL(ex->ce->name), ZSTR_VAL(file), line); + zend_string_release(file); + phpdbg_writeln("exceptionmsg", "msg=\"%s\"", ZSTR_VAL(msg)); + zend_string_release(msg); - zval_dtor(&fname); - zval_dtor(&exception); + if (EG(prev_exception)) { + OBJ_RELEASE(EG(prev_exception)); + EG(prev_exception) = 0; + } + OBJ_RELEASE(ex); + EG(opline_before_exception) = NULL; + + EG(exit_status) = 255; } /* }}} */ PHPDBG_COMMAND(run) /* {{{ */ { - if (EG(in_execution)) { - phpdbg_error("Cannot start another execution while one is in progress"); - return SUCCESS; - } - if (PHPDBG_G(ops) || PHPDBG_G(exec)) { - zend_op **orig_opline = EG(opline_ptr); - zend_op_array *orig_op_array = EG(active_op_array); - zval **orig_retval_ptr = EG(return_value_ptr_ptr); - zend_bool restore = 1; zend_execute_data *ex = EG(current_execute_data); - - if (!PHPDBG_G(ops)) { - if (phpdbg_compile(TSRMLS_C) == FAILURE) { - phpdbg_error("Failed to compile %s, cannot run", PHPDBG_G(exec)); - goto out; + zend_bool restore = 1; + + if (PHPDBG_G(in_execution)) { + if (phpdbg_ask_user_permission("Do you really want to restart execution?") == SUCCESS) { + phpdbg_startup_run++; + phpdbg_clean(1); } + return SUCCESS; } - EG(active_op_array) = PHPDBG_G(ops); - EG(return_value_ptr_ptr) = &PHPDBG_G(retval); - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); + if (!PHPDBG_G(ops)) { + if (phpdbg_compile() == FAILURE) { + phpdbg_error("compile", "type=\"compilefailure\" context=\"%s\"", "Failed to compile %s, cannot run", PHPDBG_G(exec)); + goto out; + } } /* clean up from last execution */ if (ex && ex->symbol_table) { zend_hash_clean(ex->symbol_table); + } else { + zend_rebuild_symbol_table(); } + PHPDBG_G(handled_exception) = NULL; /* clean seek state */ PHPDBG_G(flags) &= ~PHPDBG_SEEK_MASK; - zend_hash_clean( - &PHPDBG_G(seek)); + zend_hash_clean(&PHPDBG_G(seek)); /* reset hit counters */ - phpdbg_reset_breakpoints(TSRMLS_C); + phpdbg_reset_breakpoints(); if (param && param->type != EMPTY_PARAM && param->len != 0) { char **argv = emalloc(5 * sizeof(char *)); int argc = 0; int i; + /* TODO allow proper escaping with \, "" and '' here */ char *argv_str = strtok(param->str, " "); - + while (argv_str) { if (argc >= 4 && argc == (argc & -argc)) { argv = erealloc(argv, (argc * 2 + 1) * sizeof(char *)); @@ -635,38 +725,53 @@ PHPDBG_COMMAND(run) /* {{{ */ efree(SG(request_info).argv); SG(request_info).argv = erealloc(argv, ++argc * sizeof(char *)); SG(request_info).argc = argc; - - php_hash_environment(TSRMLS_C); + + php_build_argv(NULL, &PG(http_globals)[TRACK_VARS_SERVER]); } zend_try { - php_output_activate(TSRMLS_C); PHPDBG_G(flags) ^= PHPDBG_IS_INTERACTIVE; - zend_execute(EG(active_op_array) TSRMLS_CC); + PHPDBG_G(flags) |= PHPDBG_IS_RUNNING; + zend_execute(PHPDBG_G(ops), &PHPDBG_G(retval)); PHPDBG_G(flags) ^= PHPDBG_IS_INTERACTIVE; - php_output_deactivate(TSRMLS_C); } zend_catch { - EG(active_op_array) = orig_op_array; - EG(opline_ptr) = orig_opline; - EG(return_value_ptr_ptr) = orig_retval_ptr; + PHPDBG_G(in_execution) = 0; - if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) { - phpdbg_error("Caught exit/error from VM"); + if (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)) { restore = 0; + } else { + zend_bailout(); } } zend_end_try(); + if (PHPDBG_G(socket_fd) != -1) { + close(PHPDBG_G(socket_fd)); + PHPDBG_G(socket_fd) = -1; + } + if (restore) { + zend_exception_restore(); + zend_try { + zend_try_exception_handler(); + PHPDBG_G(in_execution) = 1; + } zend_catch { + PHPDBG_G(in_execution) = 0; + + if (PHPDBG_G(flags) & PHPDBG_IS_STOPPING) { + zend_bailout(); + } + } zend_end_try(); + if (EG(exception)) { - phpdbg_handle_exception(TSRMLS_C); + phpdbg_handle_exception(); } - - EG(active_op_array) = orig_op_array; - EG(opline_ptr) = orig_opline; - EG(return_value_ptr_ptr) = orig_retval_ptr; } + + PHPDBG_G(flags) &= ~PHPDBG_IS_RUNNING; + + phpdbg_clean(1); } else { - phpdbg_error("Nothing to execute!"); + phpdbg_error("inactive", "type=\"nocontext\"", "Nothing to execute!"); } out: @@ -674,50 +779,106 @@ out: return SUCCESS; } /* }}} */ +int phpdbg_output_ev_variable(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval *zv) /* {{{ */ { + phpdbg_notice("eval", "variable=\"%.*s\"", "Printing variable %.*s", (int) len, name); + phpdbg_xml("<eval %r>"); + zend_print_zval_r(zv, 0); + phpdbg_xml("</eval>"); + phpdbg_out("\n"); + + efree(name); + efree(keyname); + + return SUCCESS; +} +/* }}} */ + PHPDBG_COMMAND(ev) /* {{{ */ { - zend_bool stepping = ((PHPDBG_G(flags) & PHPDBG_IS_STEPPING)==PHPDBG_IS_STEPPING); + zend_bool stepping = ((PHPDBG_G(flags) & PHPDBG_IS_STEPPING) == PHPDBG_IS_STEPPING); zval retval; + zend_execute_data *original_execute_data = EG(current_execute_data); + zend_class_entry *original_scope = EG(scope); + zend_vm_stack original_stack = EG(vm_stack); + zend_object *ex = NULL; + + PHPDBG_OUTPUT_BACKUP(); + + original_stack->top = EG(vm_stack_top); + + if (PHPDBG_G(flags) & PHPDBG_IN_SIGNAL_HANDLER) { + phpdbg_try_access { + phpdbg_parse_variable(param->str, param->len, &EG(symbol_table), 0, phpdbg_output_ev_variable, 0); + } phpdbg_catch_access { + phpdbg_error("signalsegv", "", "Could not fetch data, invalid data source"); + } phpdbg_end_try_access(); + + PHPDBG_OUTPUT_BACKUP_RESTORE(); + return SUCCESS; + } + if (!(PHPDBG_G(flags) & PHPDBG_IS_STEPONEVAL)) { - PHPDBG_G(flags) &= ~ PHPDBG_IS_STEPPING; + PHPDBG_G(flags) &= ~PHPDBG_IS_STEPPING; } /* disable stepping while eval() in progress */ PHPDBG_G(flags) |= PHPDBG_IN_EVAL; zend_try { - if (zend_eval_stringl(param->str, param->len, - &retval, "eval()'d code" TSRMLS_CC) == SUCCESS) { - zend_print_zval_r( - &retval, 0 TSRMLS_CC); - phpdbg_writeln(EMPTY); - zval_dtor(&retval); + if (zend_eval_stringl(param->str, param->len, &retval, "eval()'d code") == SUCCESS) { + if (EG(exception)) { + ex = EG(exception); + zend_exception_error(EG(exception), E_ERROR); + } else { + phpdbg_xml("<eval %r>"); + if (PHPDBG_G(flags) & PHPDBG_WRITE_XML) { + zval *zvp = &retval; + phpdbg_xml_var_dump(zvp); + } + zend_print_zval_r(&retval, 0); + phpdbg_xml("</eval>"); + phpdbg_out("\n"); + zval_ptr_dtor(&retval); + } } + } zend_catch { + PHPDBG_G(unclean_eval) = 1; + if (ex) { + OBJ_RELEASE(ex); + } + EG(current_execute_data) = original_execute_data; + EG(scope) = original_scope; + EG(vm_stack_top) = original_stack->top; + EG(vm_stack_end) = original_stack->end; + EG(vm_stack) = original_stack; + EG(exit_status) = 0; } zend_end_try(); + PHPDBG_G(flags) &= ~PHPDBG_IN_EVAL; /* switch stepping back on */ - if (stepping && - !(PHPDBG_G(flags) & PHPDBG_IS_STEPONEVAL)) { + if (stepping && !(PHPDBG_G(flags) & PHPDBG_IS_STEPONEVAL)) { PHPDBG_G(flags) |= PHPDBG_IS_STEPPING; } CG(unclean_shutdown) = 0; + PHPDBG_OUTPUT_BACKUP_RESTORE(); + return SUCCESS; } /* }}} */ PHPDBG_COMMAND(back) /* {{{ */ { - if (!EG(in_execution)) { - phpdbg_error("Not executing!"); + if (!PHPDBG_G(in_execution)) { + phpdbg_error("inactive", "type=\"noexec\"", "Not executing!"); return SUCCESS; } if (!param) { - phpdbg_dump_backtrace(0 TSRMLS_CC); + phpdbg_dump_backtrace(0); } else { - phpdbg_dump_backtrace(param->num TSRMLS_CC); + phpdbg_dump_backtrace(param->num); } return SUCCESS; @@ -725,62 +886,62 @@ PHPDBG_COMMAND(back) /* {{{ */ PHPDBG_COMMAND(print) /* {{{ */ { - phpdbg_writeln(SEPARATE); - phpdbg_notice("Execution Context Information"); + if (!param || param->type == EMPTY_PARAM) { + return phpdbg_do_print_stack(param); + } else switch (param->type) { + case STR_PARAM: + return phpdbg_do_print_func(param); + case METHOD_PARAM: + return phpdbg_do_print_method(param); + default: + phpdbg_error("print", "type=\"invalidarg\"", "Invalid arguments to print, expected nothing, function name or method name"); + return SUCCESS; + } +} /* }}} */ + +PHPDBG_COMMAND(info) /* {{{ */ +{ + phpdbg_out("Execution Context Information\n\n"); + phpdbg_xml("<printinfo %r>"); #ifdef HAVE_LIBREADLINE - phpdbg_writeln("Readline\tyes"); + phpdbg_writeln("info", "readline=\"yes\"", "Readline yes"); #else - phpdbg_writeln("Readline\tno"); + phpdbg_writeln("info", "readline=\"no\"", "Readline no"); #endif #ifdef HAVE_LIBEDIT - phpdbg_writeln("Libedit\t\tyes"); + phpdbg_writeln("info", "libedit=\"yes\"", "Libedit yes"); #else - phpdbg_writeln("Libedit\t\tno"); + phpdbg_writeln("info", "libedit=\"no\"", "Libedit no"); #endif - phpdbg_writeln("Exec\t\t%s", PHPDBG_G(exec) ? PHPDBG_G(exec) : "none"); - phpdbg_writeln("Compiled\t%s", PHPDBG_G(ops) ? "yes" : "no"); - phpdbg_writeln("Stepping\t%s", (PHPDBG_G(flags) & PHPDBG_IS_STEPPING) ? "on" : "off"); - phpdbg_writeln("Quietness\t%s", (PHPDBG_G(flags) & PHPDBG_IS_QUIET) ? "on" : "off"); - phpdbg_writeln("Oplog\t\t%s", PHPDBG_G(oplog) ? "on" : "off"); + phpdbg_writeln("info", "context=\"%s\"", "Exec %s", PHPDBG_G(exec) ? PHPDBG_G(exec) : "none"); + phpdbg_writeln("info", "compiled=\"%s\"", "Compiled %s", PHPDBG_G(ops) ? "yes" : "no"); + phpdbg_writeln("info", "stepping=\"%s\"", "Stepping %s", (PHPDBG_G(flags) & PHPDBG_IS_STEPPING) ? "on" : "off"); + phpdbg_writeln("info", "quiet=\"%s\"", "Quietness %s", (PHPDBG_G(flags) & PHPDBG_IS_QUIET) ? "on" : "off"); + phpdbg_writeln("info", "oplog=\"%s\"", "Oplog %s", PHPDBG_G(oplog) ? "on" : "off"); if (PHPDBG_G(ops)) { - phpdbg_writeln("Opcodes\t\t%d", PHPDBG_G(ops)->last); - - if (PHPDBG_G(ops)->last_var) { - phpdbg_writeln("Variables\t%d", PHPDBG_G(ops)->last_var-1); - } else { - phpdbg_writeln("Variables\tNone"); - } + phpdbg_writeln("info", "ops=\"%d\"", "Opcodes %d", PHPDBG_G(ops)->last); + phpdbg_writeln("info", "vars=\"%d\"", "Variables %d", PHPDBG_G(ops)->last_var ? PHPDBG_G(ops)->last_var - 1 : 0); } - phpdbg_writeln("Executing\t%s", EG(in_execution) ? "yes" : "no"); - if (EG(in_execution)) { - phpdbg_writeln("VM Return\t%d", PHPDBG_G(vmret)); + phpdbg_writeln("info", "executing=\"%d\"", "Executing %s", PHPDBG_G(in_execution) ? "yes" : "no"); + if (PHPDBG_G(in_execution)) { + phpdbg_writeln("info", "vmret=\"%d\"", "VM Return %d", PHPDBG_G(vmret)); } - phpdbg_writeln("Classes\t\t%d", zend_hash_num_elements(EG(class_table))); - phpdbg_writeln("Functions\t%d", zend_hash_num_elements(EG(function_table))); - phpdbg_writeln("Constants\t%d", zend_hash_num_elements(EG(zend_constants))); - phpdbg_writeln("Included\t%d", zend_hash_num_elements(&EG(included_files))); - - phpdbg_writeln(SEPARATE); - - return SUCCESS; -} /* }}} */ - -PHPDBG_COMMAND(info) /* {{{ */ -{ - phpdbg_error( - "No information command selected!"); + phpdbg_writeln("info", "classes=\"%d\"", "Classes %d", zend_hash_num_elements(EG(class_table))); + phpdbg_writeln("info", "functions=\"%d\"", "Functions %d", zend_hash_num_elements(EG(function_table))); + phpdbg_writeln("info", "constants=\"%d\"", "Constants %d", zend_hash_num_elements(EG(zend_constants))); + phpdbg_writeln("info", "includes=\"%d\"", "Included %d", zend_hash_num_elements(&EG(included_files))); + phpdbg_xml("</printinfo>"); return SUCCESS; } /* }}} */ PHPDBG_COMMAND(set) /* {{{ */ { - phpdbg_error( - "No set command selected!"); + phpdbg_error("set", "type=\"toofewargs\" expected=\"1\"", "No set command selected!"); return SUCCESS; } /* }}} */ @@ -789,42 +950,42 @@ PHPDBG_COMMAND(break) /* {{{ */ { if (!param) { phpdbg_set_breakpoint_file( - zend_get_executed_filename(TSRMLS_C), - zend_get_executed_lineno(TSRMLS_C) TSRMLS_CC); + zend_get_executed_filename(), + zend_get_executed_lineno()); } else switch (param->type) { case ADDR_PARAM: - phpdbg_set_breakpoint_opline(param->addr TSRMLS_CC); + phpdbg_set_breakpoint_opline(param->addr); break; case NUMERIC_PARAM: if (PHPDBG_G(exec)) { - phpdbg_set_breakpoint_file(phpdbg_current_file(TSRMLS_C), param->num TSRMLS_CC); + phpdbg_set_breakpoint_file(phpdbg_current_file(), param->num); } else { - phpdbg_error("Execution context not set!"); + phpdbg_error("inactive", "type=\"noexec\"", "Execution context not set!"); } break; case METHOD_PARAM: - phpdbg_set_breakpoint_method(param->method.class, param->method.name TSRMLS_CC); + phpdbg_set_breakpoint_method(param->method.class, param->method.name); break; case NUMERIC_METHOD_PARAM: - phpdbg_set_breakpoint_method_opline(param->method.class, param->method.name, param->num TSRMLS_CC); + phpdbg_set_breakpoint_method_opline(param->method.class, param->method.name, param->num); break; case NUMERIC_FUNCTION_PARAM: - phpdbg_set_breakpoint_function_opline(param->str, param->num TSRMLS_CC); + phpdbg_set_breakpoint_function_opline(param->str, param->num); break; case FILE_PARAM: - phpdbg_set_breakpoint_file(param->file.name, param->file.line TSRMLS_CC); + phpdbg_set_breakpoint_file(param->file.name, param->file.line); break; case NUMERIC_FILE_PARAM: - phpdbg_set_breakpoint_file_opline(param->file.name, param->file.line TSRMLS_CC); + phpdbg_set_breakpoint_file_opline(param->file.name, param->file.line); break; case COND_PARAM: - phpdbg_set_breakpoint_expression(param->str, param->len TSRMLS_CC); + phpdbg_set_breakpoint_expression(param->str, param->len); break; case STR_PARAM: - phpdbg_set_breakpoint_symbol(param->str, param->len TSRMLS_CC); + phpdbg_set_breakpoint_symbol(param->str, param->len); break; case OP_PARAM: - phpdbg_set_breakpoint_opcode(param->str, param->len TSRMLS_CC); + phpdbg_set_breakpoint_opcode(param->str, param->len); break; phpdbg_default_switch_case(); @@ -837,42 +998,229 @@ PHPDBG_COMMAND(sh) /* {{{ */ { FILE *fd = NULL; if ((fd=VCWD_POPEN((char*)param->str, "w"))) { - /* do something perhaps ?? do we want input ?? */ - fclose(fd); + /* TODO: do something perhaps ?? do we want input ?? */ + pclose(fd); } else { - phpdbg_error( - "Failed to execute %s", param->str); + phpdbg_error("sh", "type=\"failure\" smd=\"%s\"", "Failed to execute %s", param->str); } - + + return SUCCESS; +} /* }}} */ + +static int add_module_info(zend_module_entry *module) /* {{{ */ { + phpdbg_write("module", "name=\"%s\"", "%s\n", module->name); + return 0; +} +/* }}} */ + +static int add_zendext_info(zend_extension *ext) /* {{{ */ { + phpdbg_write("extension", "name=\"%s\"", "%s\n", ext->name); + return 0; +} +/* }}} */ + +PHPDBG_API const char *phpdbg_load_module_or_extension(char **path, char **name) /* {{{ */ { + DL_HANDLE handle; + char *extension_dir; + + extension_dir = INI_STR("extension_dir"); + + if (strchr(*path, '/') != NULL || strchr(*path, DEFAULT_SLASH) != NULL) { + /* path is fine */ + } else if (extension_dir && extension_dir[0]) { + char *libpath; + int extension_dir_len = strlen(extension_dir); + if (IS_SLASH(extension_dir[extension_dir_len-1])) { + spprintf(&libpath, 0, "%s%s", extension_dir, *path); /* SAFE */ + } else { + spprintf(&libpath, 0, "%s%c%s", extension_dir, DEFAULT_SLASH, *path); /* SAFE */ + } + efree(*path); + *path = libpath; + } else { + phpdbg_error("dl", "type=\"relpath\"", "Not a full path given or extension_dir ini setting is not set"); + + return NULL; + } + + handle = DL_LOAD(*path); + + if (!handle) { +#if PHP_WIN32 + char *err = GET_DL_ERROR(); + if (err && *err != "") { + phpdbg_error("dl", "type=\"unknown\"", "%s", err); + LocalFree(err); + } else { + phpdbg_error("dl", "type=\"unknown\"", "Unknown reason"); + } +#else + phpdbg_error("dl", "type=\"unknown\"", "%s", GET_DL_ERROR()); +#endif + return NULL; + } + +#if ZEND_EXTENSIONS_SUPPORT + do { + zend_extension *new_extension; + zend_extension_version_info *extension_version_info; + + extension_version_info = (zend_extension_version_info *) DL_FETCH_SYMBOL(handle, "extension_version_info"); + if (!extension_version_info) { + extension_version_info = (zend_extension_version_info *) DL_FETCH_SYMBOL(handle, "_extension_version_info"); + } + new_extension = (zend_extension *) DL_FETCH_SYMBOL(handle, "zend_extension_entry"); + if (!new_extension) { + new_extension = (zend_extension *) DL_FETCH_SYMBOL(handle, "_zend_extension_entry"); + } + if (!extension_version_info || !new_extension) { + break; + } + if (extension_version_info->zend_extension_api_no != ZEND_EXTENSION_API_NO &&(!new_extension->api_no_check || new_extension->api_no_check(ZEND_EXTENSION_API_NO) != SUCCESS)) { + phpdbg_error("dl", "type=\"wrongapi\" extension=\"%s\" apineeded=\"%d\" apiinstalled=\"%d\"", "%s requires Zend Engine API version %d, which does not match the installed Zend Engine API version %d", new_extension->name, extension_version_info->zend_extension_api_no, ZEND_EXTENSION_API_NO); + + goto quit; + } else if (strcmp(ZEND_EXTENSION_BUILD_ID, extension_version_info->build_id) && (!new_extension->build_id_check || new_extension->build_id_check(ZEND_EXTENSION_BUILD_ID) != SUCCESS)) { + phpdbg_error("dl", "type=\"wrongbuild\" extension=\"%s\" buildneeded=\"%s\" buildinstalled=\"%s\"", "%s was built with configuration %s, whereas running engine is %s", new_extension->name, extension_version_info->build_id, ZEND_EXTENSION_BUILD_ID); + + goto quit; + } + + *name = new_extension->name; + + zend_register_extension(new_extension, handle); + + if (new_extension->startup) { + if (new_extension->startup(new_extension) != SUCCESS) { + phpdbg_error("dl", "type=\"startupfailure\" extension=\"%s\"", "Unable to startup Zend extension %s", new_extension->name); + + goto quit; + } + zend_append_version_info(new_extension); + } + + return "Zend extension"; + } while (0); +#endif + + do { + zend_module_entry *module_entry; + zend_module_entry *(*get_module)(void); + + get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "get_module"); + if (!get_module) { + get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "_get_module"); + } + + if (!get_module) { + break; + } + + module_entry = get_module(); + *name = (char *) module_entry->name; + + if (strcmp(ZEND_EXTENSION_BUILD_ID, module_entry->build_id)) { + phpdbg_error("dl", "type=\"wrongbuild\" module=\"%s\" buildneeded=\"%s\" buildinstalled=\"%s\"", "%s was built with configuration %s, whereas running engine is %s", module_entry->name, module_entry->build_id, ZEND_EXTENSION_BUILD_ID); + + goto quit; + } + + module_entry->type = MODULE_PERSISTENT; + module_entry->module_number = zend_next_free_module(); + module_entry->handle = handle; + + if ((module_entry = zend_register_module_ex(module_entry)) == NULL) { + phpdbg_error("dl", "type=\"registerfailure\" module=\"%s\"", "Unable to register module %s", module_entry->name); + + goto quit; + } + + if (zend_startup_module_ex(module_entry) == FAILURE) { + phpdbg_error("dl", "type=\"startupfailure\" module=\"%s\"", "Unable to startup module %s", module_entry->name); + + goto quit; + } + + if (module_entry->request_startup_func) { + if (module_entry->request_startup_func(MODULE_PERSISTENT, module_entry->module_number) == FAILURE) { + phpdbg_error("dl", "type=\"initfailure\" module=\"%s\"", "Unable to initialize module %s", module_entry->name); + + goto quit; + } + } + + return "module"; + } while (0); + + phpdbg_error("dl", "type=\"nophpso\"", "This shared object is nor a Zend extension nor a module"); + +quit: + DL_UNLOAD(handle); + return NULL; +} +/* }}} */ + +PHPDBG_COMMAND(dl) /* {{{ */ +{ + const char *type; + char *name, *path; + + if (!param || param->type == EMPTY_PARAM) { + phpdbg_notice("dl", "extensiontype=\"Zend extension\"", "Zend extensions"); + zend_llist_apply(&zend_extensions, (llist_apply_func_t) add_zendext_info); + phpdbg_out("\n"); + phpdbg_notice("dl", "extensiontype=\"module\"", "Modules"); + zend_hash_apply(&module_registry, (apply_func_t) add_module_info); + } else switch (param->type) { + case STR_PARAM: +#ifdef HAVE_LIBDL + path = estrndup(param->str, param->len); + + phpdbg_activate_err_buf(1); + if ((type = phpdbg_load_module_or_extension(&path, &name)) == NULL) { + phpdbg_error("dl", "path=\"%s\" %b", "Could not load %s, not found or invalid zend extension / module: %b", path); + efree(name); + } else { + phpdbg_notice("dl", "extensiontype=\"%s\" name=\"%s\" path=\"%s\"", "Successfully loaded the %s %s at path %s", type, name, path); + } + phpdbg_activate_err_buf(0); + phpdbg_free_err_buf(); + efree(path); +#else + phpdbg_error("dl", "type=\"unsupported\" path=\"%.*s\"", "Cannot dynamically load %.*s - dynamic modules are not supported", (int) param->len, param->str); +#endif + break; + + phpdbg_default_switch_case(); + } + return SUCCESS; } /* }}} */ PHPDBG_COMMAND(source) /* {{{ */ { - struct stat sb; - + zend_stat_t sb; + if (VCWD_STAT(param->str, &sb) != -1) { - phpdbg_try_file_init(param->str, param->len, 0 TSRMLS_CC); + phpdbg_try_file_init(param->str, param->len, 0); } else { - phpdbg_error( - "Failed to stat %s, file does not exist", param->str); + phpdbg_error("source", "type=\"notfound\" file=\"%s\"", "Failed to stat %s, file does not exist", param->str); } - + return SUCCESS; } /* }}} */ PHPDBG_COMMAND(export) /* {{{ */ { FILE *handle = VCWD_FOPEN(param->str, "w+"); - + if (handle) { - phpdbg_export_breakpoints(handle TSRMLS_CC); + phpdbg_export_breakpoints(handle); fclose(handle); } else { - phpdbg_error( - "Failed to open or create %s, check path and permissions", param->str); + phpdbg_error("export", "type=\"openfailure\" file=\"%s\"", "Failed to open or create %s, check path and permissions", param->str); } - + return SUCCESS; } /* }}} */ @@ -882,20 +1230,17 @@ PHPDBG_COMMAND(register) /* {{{ */ char *lcname = zend_str_tolower_dup(param->str, param->len); size_t lcname_len = strlen(lcname); - if (!zend_hash_exists(&PHPDBG_G(registered), lcname, lcname_len+1)) { - if (zend_hash_find(EG(function_table), lcname, lcname_len+1, (void**) &function) == SUCCESS) { - zend_hash_update( - &PHPDBG_G(registered), lcname, lcname_len+1, (void*)&function, sizeof(zend_function), NULL); + if (!zend_hash_str_exists(&PHPDBG_G(registered), lcname, lcname_len)) { + if ((function = zend_hash_str_find_ptr(EG(function_table), lcname, lcname_len))) { + zend_hash_str_update_ptr(&PHPDBG_G(registered), lcname, lcname_len, function); function_add_ref(function); - phpdbg_notice( - "Registered %s", lcname); + phpdbg_notice("register", "function=\"%s\"", "Registered %s", lcname); } else { - phpdbg_error("The requested function (%s) could not be found", param->str); + phpdbg_error("register", "type=\"notfound\" function=\"%s\"", "The requested function (%s) could not be found", param->str); } } else { - phpdbg_error( - "The requested name (%s) is already in use", lcname); + phpdbg_error("register", "type=\"inuse\" function=\"%s\"", "The requested name (%s) is already in use", lcname); } efree(lcname); @@ -904,48 +1249,52 @@ PHPDBG_COMMAND(register) /* {{{ */ PHPDBG_COMMAND(quit) /* {{{ */ { - /* don't allow this to loop, ever ... */ - if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) { - PHPDBG_G(flags) |= PHPDBG_IS_QUITTING; - zend_bailout(); - } + PHPDBG_G(flags) |= PHPDBG_IS_QUITTING; + PHPDBG_G(flags) &= ~PHPDBG_IS_CLEANING; - return PHPDBG_NEXT; + return SUCCESS; } /* }}} */ PHPDBG_COMMAND(clean) /* {{{ */ { - if (EG(in_execution)) { - phpdbg_error("Cannot clean environment while executing"); - return SUCCESS; + if (PHPDBG_G(in_execution)) { + if (phpdbg_ask_user_permission("Do you really want to clean your current environment?") == FAILURE) { + return SUCCESS; + } } - phpdbg_notice("Cleaning Execution Environment"); + phpdbg_out("Cleaning Execution Environment\n"); + phpdbg_xml("<cleaninfo %r>"); - phpdbg_writeln("Classes\t\t\t%d", zend_hash_num_elements(EG(class_table))); - phpdbg_writeln("Functions\t\t%d", zend_hash_num_elements(EG(function_table))); - phpdbg_writeln("Constants\t\t%d", zend_hash_num_elements(EG(zend_constants))); - phpdbg_writeln("Includes\t\t%d", zend_hash_num_elements(&EG(included_files))); + phpdbg_writeln("clean", "classes=\"%d\"", "Classes %d", zend_hash_num_elements(EG(class_table))); + phpdbg_writeln("clean", "functions=\"%d\"", "Functions %d", zend_hash_num_elements(EG(function_table))); + phpdbg_writeln("clean", "constants=\"%d\"", "Constants %d", zend_hash_num_elements(EG(zend_constants))); + phpdbg_writeln("clean", "includes=\"%d\"", "Includes %d", zend_hash_num_elements(&EG(included_files))); - phpdbg_clean(1 TSRMLS_CC); + phpdbg_clean(1); + + phpdbg_xml("</cleaninfo>"); return SUCCESS; } /* }}} */ PHPDBG_COMMAND(clear) /* {{{ */ { - phpdbg_notice("Clearing Breakpoints"); + phpdbg_out("Clearing Breakpoints\n"); + phpdbg_xml("<clearinfo %r>"); + + phpdbg_writeln("clear", "files=\"%d\"", "File %d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE])); + phpdbg_writeln("clear", "functions=\"%d\"", "Functions %d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM])); + phpdbg_writeln("clear", "methods=\"%d\"", "Methods %d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD])); + phpdbg_writeln("clear", "oplines=\"%d\"", "Oplines %d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE])); + phpdbg_writeln("clear", "fileoplines=\"%d\"", "File oplines %d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE])); + phpdbg_writeln("clear", "functionoplines=\"%d\"", "Function oplines %d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE])); + phpdbg_writeln("clear", "methodoplines=\"%d\"", "Method oplines %d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE])); + phpdbg_writeln("clear", "eval=\"%d\"", "Conditionals %d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_COND])); - phpdbg_writeln("File\t\t\t%d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE])); - phpdbg_writeln("Functions\t\t%d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM])); - phpdbg_writeln("Methods\t\t\t%d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD])); - phpdbg_writeln("Oplines\t\t\t%d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE])); - phpdbg_writeln("File oplines\t\t\t%d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE])); - phpdbg_writeln("Function oplines\t\t\t%d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE])); - phpdbg_writeln("Method oplines\t\t\t%d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE])); - phpdbg_writeln("Conditionals\t\t%d", zend_hash_num_elements(&PHPDBG_G(bp)[PHPDBG_BREAK_COND])); + phpdbg_clear_breakpoints(); - phpdbg_clear_breakpoints(TSRMLS_C); + phpdbg_xml("</clearinfo>"); return SUCCESS; } /* }}} */ @@ -962,7 +1311,7 @@ PHPDBG_COMMAND(list) /* {{{ */ return PHPDBG_LIST_HANDLER(lines)(PHPDBG_COMMAND_ARGS); case STR_PARAM: - phpdbg_list_function_byname(param->str, param->len TSRMLS_CC); + phpdbg_list_function_byname(param->str, param->len); break; case METHOD_PARAM: @@ -977,11 +1326,11 @@ PHPDBG_COMMAND(list) /* {{{ */ PHPDBG_COMMAND(watch) /* {{{ */ { if (!param || param->type == EMPTY_PARAM) { - phpdbg_list_watchpoints(TSRMLS_C); + phpdbg_list_watchpoints(); } else switch (param->type) { case STR_PARAM: - if (phpdbg_create_var_watchpoint(param->str, param->len TSRMLS_CC) != FAILURE) { - phpdbg_notice("Set watchpoint on %.*s", (int)param->len, param->str); + if (phpdbg_create_var_watchpoint(param->str, param->len) != FAILURE) { + phpdbg_notice("watch", "variable=\"%.*s\"", "Set watchpoint on %.*s", (int) param->len, param->str); } break; @@ -991,249 +1340,221 @@ PHPDBG_COMMAND(watch) /* {{{ */ return SUCCESS; } /* }}} */ -int phpdbg_interactive(TSRMLS_D) /* {{{ */ +int phpdbg_interactive(zend_bool allow_async_unsafe) /* {{{ */ { int ret = SUCCESS; - char *why = NULL; char *input = NULL; phpdbg_param_t stack; PHPDBG_G(flags) |= PHPDBG_IS_INTERACTIVE; - input = phpdbg_read_input(NULL TSRMLS_CC); + while (ret == SUCCESS || ret == FAILURE) { + if (PHPDBG_G(flags) & PHPDBG_IS_STOPPING) { + zend_bailout(); + } - if (input) { - do { - phpdbg_init_param(&stack, STACK_PARAM); + if (!(input = phpdbg_read_input(NULL))) { + break; + } - if (phpdbg_do_parse(&stack, input TSRMLS_CC) <= 0) { - switch (ret = phpdbg_stack_execute(&stack, &why TSRMLS_CC)) { - case FAILURE: - if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) { - if (phpdbg_call_register(&stack TSRMLS_CC) == FAILURE) { - if (why) { - phpdbg_error("%s", why); - } - } - } - if (why) { - free(why); - why = NULL; - } - break; + phpdbg_init_param(&stack, STACK_PARAM); - case PHPDBG_LEAVE: - case PHPDBG_FINISH: - case PHPDBG_UNTIL: - case PHPDBG_NEXT: { - if (!EG(in_execution) && !(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) { - phpdbg_error("Not running"); + if (phpdbg_do_parse(&stack, input) <= 0) { + phpdbg_activate_err_buf(1); + +#ifdef PHP_WIN32 +#define PARA ((phpdbg_param_t *)stack.next)->type + if (PHPDBG_G(flags) & PHPDBG_IS_REMOTE && (RUN_PARAM == PARA || EVAL_PARAM == PARA)) { + sigio_watcher_start(); + } +#endif + switch (ret = phpdbg_stack_execute(&stack, allow_async_unsafe)) { + case FAILURE: + if (!(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)) { + if (!allow_async_unsafe || phpdbg_call_register(&stack) == FAILURE) { + phpdbg_output_err_buf(NULL, "%b", "%b"); } - goto out; } + break; + + case PHPDBG_LEAVE: + case PHPDBG_FINISH: + case PHPDBG_UNTIL: + case PHPDBG_NEXT: { + phpdbg_activate_err_buf(0); + phpdbg_free_err_buf(); + if (!PHPDBG_G(in_execution) && !(PHPDBG_G(flags) & PHPDBG_IS_STOPPING)) { + phpdbg_error("command", "type=\"noexec\"", "Not running"); + } + break; } } - if (why) { - free(why); - why = NULL; + phpdbg_activate_err_buf(0); + phpdbg_free_err_buf(); +#ifdef PHP_WIN32 + if (PHPDBG_G(flags) & PHPDBG_IS_REMOTE && (RUN_PARAM == PARA || EVAL_PARAM == PARA)) { + sigio_watcher_stop(); } +#undef PARA +#endif + } - phpdbg_stack_free(&stack); - phpdbg_destroy_input(&input TSRMLS_CC); - - } while ((input = phpdbg_read_input(NULL TSRMLS_CC))); + phpdbg_stack_free(&stack); + phpdbg_destroy_input(&input); + PHPDBG_G(req_id) = 0; + input = NULL; } -out: if (input) { phpdbg_stack_free(&stack); - phpdbg_destroy_input(&input TSRMLS_CC); + phpdbg_destroy_input(&input); + PHPDBG_G(req_id) = 0; } - if (why) { - free(why); - } - - if (EG(in_execution)) { - phpdbg_restore_frame(TSRMLS_C); + if (PHPDBG_G(in_execution)) { + phpdbg_restore_frame(); } PHPDBG_G(flags) &= ~PHPDBG_IS_INTERACTIVE; - phpdbg_print_changed_zvals(TSRMLS_C); + phpdbg_print_changed_zvals(); return ret; } /* }}} */ -void phpdbg_clean(zend_bool full TSRMLS_DC) /* {{{ */ -{ - /* this is implicitly required */ - if (PHPDBG_G(ops)) { - destroy_op_array(PHPDBG_G(ops) TSRMLS_CC); - efree(PHPDBG_G(ops)); - PHPDBG_G(ops) = NULL; - } +/* code may behave weirdly if EG(exception) is set; thus backup it */ +#define DO_INTERACTIVE(allow_async_unsafe) do { \ + const zend_op *backup_opline; \ + const zend_op *before_ex; \ + if (exception) { \ + if (EG(current_execute_data) && EG(current_execute_data)->func && ZEND_USER_CODE(EG(current_execute_data)->func->common.type)) { \ + backup_opline = EG(current_execute_data)->opline; \ + } \ + before_ex = EG(opline_before_exception); \ + ++GC_REFCOUNT(exception); \ + zend_clear_exception(); \ + } \ + if (!(PHPDBG_G(flags) & PHPDBG_IN_EVAL)) { \ + const char *file_char = zend_get_executed_filename(); \ + zend_string *file = zend_string_init(file_char, strlen(file_char), 0); \ + phpdbg_list_file(file, 3, zend_get_executed_lineno()-1, zend_get_executed_lineno()); \ + efree(file); \ + } \ + \ + switch (phpdbg_interactive(allow_async_unsafe)) { \ + zval zv; \ + case PHPDBG_LEAVE: \ + case PHPDBG_FINISH: \ + case PHPDBG_UNTIL: \ + case PHPDBG_NEXT: \ + if (exception) { \ + if (EG(current_execute_data) && EG(current_execute_data)->func && ZEND_USER_CODE(EG(current_execute_data)->func->common.type) \ + && (backup_opline->opcode == ZEND_HANDLE_EXCEPTION || backup_opline->opcode == ZEND_CATCH)) { \ + EG(current_execute_data)->opline = backup_opline; \ + EG(exception) = exception; \ + } else { \ + Z_OBJ(zv) = exception; \ + zend_throw_exception_internal(&zv); \ + } \ + EG(opline_before_exception) = before_ex; \ + } \ + /* fallthrough */ \ + default: \ + goto next; \ + } \ +} while (0) - if (full) { - PHPDBG_G(flags) |= PHPDBG_IS_CLEANING; +void phpdbg_execute_ex(zend_execute_data *execute_data) /* {{{ */ +{ + zend_bool original_in_execution = PHPDBG_G(in_execution); + if ((PHPDBG_G(flags) & PHPDBG_IS_STOPPING) && !(PHPDBG_G(flags) & PHPDBG_IS_RUNNING)) { zend_bailout(); } -} /* }}} */ -static inline zend_execute_data *phpdbg_create_execute_data(zend_op_array *op_array, zend_bool nested TSRMLS_DC) /* {{{ */ -{ -#if PHP_VERSION_ID >= 50500 - return zend_create_execute_data_from_op_array(op_array, nested TSRMLS_CC); -#else + PHPDBG_G(in_execution) = 1; -#undef EX -#define EX(element) execute_data->element -#undef EX_CV -#define EX_CV(var) EX(CVs)[var] -#undef EX_CVs -#define EX_CVs() EX(CVs) -#undef EX_T -#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset)) -#undef EX_Ts -#define EX_Ts() EX(Ts) - - zend_execute_data *execute_data = (zend_execute_data *)zend_vm_stack_alloc( - ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)) + - ZEND_MM_ALIGNED_SIZE(sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2)) + - ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T TSRMLS_CC); - - EX(CVs) = (zval***)((char*)execute_data + ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data))); - memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var); - EX(Ts) = (temp_variable *)(((char*)EX(CVs)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2))); - EX(fbc) = NULL; - EX(called_scope) = NULL; - EX(object) = NULL; - EX(old_error_reporting) = NULL; - EX(op_array) = op_array; - EX(symbol_table) = EG(active_symbol_table); - EX(prev_execute_data) = EG(current_execute_data); - EG(current_execute_data) = execute_data; - EX(nested) = nested; - - if (!op_array->run_time_cache && op_array->last_cache_slot) { - op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*)); - } + while (1) { + zend_object *exception = EG(exception); - if (op_array->this_var != -1 && EG(This)) { - Z_ADDREF_P(EG(This)); /* For $this pointer */ - if (!EG(active_symbol_table)) { - EX_CV(op_array->this_var) = (zval**)EX_CVs() + (op_array->last_var + op_array->this_var); - *EX_CV(op_array->this_var) = EG(This); - } else { - if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void**)&EX_CV(op_array->this_var))==FAILURE) { - Z_DELREF_P(EG(This)); - } + if ((PHPDBG_G(flags) & PHPDBG_BP_RESOLVE_MASK)) { + /* resolve nth opline breakpoints */ + phpdbg_resolve_op_array_breaks(&execute_data->func->op_array); } - } - EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes; - EG(opline_ptr) = &EX(opline); +#ifdef ZEND_WIN32 + if (EG(timed_out)) { + zend_timeout(0); + } +#endif - EX(function_state).function = (zend_function *) op_array; - EX(function_state).arguments = NULL; + if (PHPDBG_G(flags) & PHPDBG_PREVENT_INTERACTIVE) { + phpdbg_print_opline_ex(execute_data, 0); + goto next; + } - return execute_data; -#endif -} /* }}} */ + /* check for uncaught exceptions */ + if (exception && PHPDBG_G(handled_exception) != exception && !(PHPDBG_G(flags) & PHPDBG_IN_EVAL)) { + zend_execute_data *prev_ex = execute_data; + zval zv, rv; + zend_string *file, *msg; + zend_long line; + + do { + prev_ex = zend_generator_check_placeholder_frame(prev_ex); + /* assuming that no internal functions will silently swallow exceptions ... */ + if (!prev_ex->func || !ZEND_USER_CODE(prev_ex->func->common.type)) { + continue; + } -#if PHP_VERSION_ID >= 50500 -void phpdbg_execute_ex(zend_execute_data *execute_data TSRMLS_DC) /* {{{ */ -{ -#else -void phpdbg_execute_ex(zend_op_array *op_array TSRMLS_DC) /* {{{ */ -{ - long long flags = 0; - zend_ulong address = 0L; - zend_execute_data *execute_data; - zend_bool nested = 0; -#endif - zend_bool original_in_execution = EG(in_execution); - HashTable vars; + if (phpdbg_check_caught_ex(prev_ex, exception)) { + goto ex_is_caught; + } + } while ((prev_ex = prev_ex->prev_execute_data)); -#if PHP_VERSION_ID < 50500 - if (EG(exception)) { - return; - } -#endif + PHPDBG_G(handled_exception) = exception; - EG(in_execution) = 1; + ZVAL_OBJ(&zv, exception); + file = zval_get_string(zend_read_property(zend_get_exception_base(&zv), &zv, ZEND_STRL("file"), 1, &rv)); + line = zval_get_long(zend_read_property(zend_get_exception_base(&zv), &zv, ZEND_STRL("line"), 1, &rv)); + msg = zval_get_string(zend_read_property(zend_get_exception_base(&zv), &zv, ZEND_STRL("message"), 1, &rv)); -#if PHP_VERSION_ID >= 50500 - if (0) { -zend_vm_enter: - execute_data = phpdbg_create_execute_data(EG(active_op_array), 1 TSRMLS_CC); - } - zend_hash_init(&vars, EG(active_op_array)->last, NULL, NULL, 0); -#else -zend_vm_enter: - execute_data = phpdbg_create_execute_data(op_array, nested TSRMLS_CC); - nested = 1; - zend_hash_init(&vars, EG(active_op_array)->last, NULL, NULL, 0); -#endif + phpdbg_error("exception", + "name=\"%s\" file=\"%s\" line=\"" ZEND_LONG_FMT "\"", + "Uncaught %s in %s on line " ZEND_LONG_FMT ": %.*s", + ZSTR_VAL(exception->ce->name), ZSTR_VAL(file), line, + ZSTR_LEN(msg) < 80 ? (int) ZSTR_LEN(msg) : 80, ZSTR_VAL(msg)); + zend_string_release(msg); + zend_string_release(file); - while (1) { - - if ((PHPDBG_G(flags) & PHPDBG_BP_RESOLVE_MASK)) { - /* resolve nth opline breakpoints */ - phpdbg_resolve_op_array_breaks(EG(active_op_array) TSRMLS_CC); + DO_INTERACTIVE(1); } - -#ifdef ZEND_WIN32 - if (EG(timed_out)) { - zend_timeout(0); - } -#endif - -#define DO_INTERACTIVE() do { \ - if (!(PHPDBG_G(flags) & PHPDBG_IN_EVAL)) { \ - phpdbg_list_file( \ - zend_get_executed_filename(TSRMLS_C), \ - 3, \ - zend_get_executed_lineno(TSRMLS_C)-1, \ - zend_get_executed_lineno(TSRMLS_C) \ - TSRMLS_CC \ - ); \ - } \ - \ -/* do { */\ - switch (phpdbg_interactive(TSRMLS_C)) { \ - case PHPDBG_LEAVE: \ - case PHPDBG_FINISH: \ - case PHPDBG_UNTIL: \ - case PHPDBG_NEXT:{ \ - goto next; \ - } \ - } \ -/* } while (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)); */\ -} while (0) +ex_is_caught: - /* allow conditional breakpoints and - initialization to access the vm uninterrupted */ - if ((PHPDBG_G(flags) & PHPDBG_IN_COND_BP) || - (PHPDBG_G(flags) & PHPDBG_IS_INITIALIZING)) { + /* allow conditional breakpoints and initialization to access the vm uninterrupted */ + if (PHPDBG_G(flags) & (PHPDBG_IN_COND_BP | PHPDBG_IS_INITIALIZING)) { /* skip possible breakpoints */ goto next; } /* perform seek operation */ - if (PHPDBG_G(flags) & PHPDBG_SEEK_MASK) { + if ((PHPDBG_G(flags) & PHPDBG_SEEK_MASK) && !(PHPDBG_G(flags) & PHPDBG_IN_EVAL)) { /* current address */ zend_ulong address = (zend_ulong) execute_data->opline; + if (PHPDBG_G(seek_ex) != execute_data) { + goto next; + } + +#define INDEX_EXISTS_CHECK (zend_hash_index_exists(&PHPDBG_G(seek), address) || (exception && phpdbg_check_caught_ex(execute_data, exception) == 0)) + /* run to next line */ if (PHPDBG_G(flags) & PHPDBG_IN_UNTIL) { - if (zend_hash_index_exists(&PHPDBG_G(seek), address)) { + if (INDEX_EXISTS_CHECK) { PHPDBG_G(flags) &= ~PHPDBG_IN_UNTIL; - zend_hash_clean( - &PHPDBG_G(seek)); + zend_hash_clean(&PHPDBG_G(seek)); } else { /* skip possible breakpoints */ goto next; @@ -1242,10 +1563,9 @@ zend_vm_enter: /* run to finish */ if (PHPDBG_G(flags) & PHPDBG_IN_FINISH) { - if (zend_hash_index_exists(&PHPDBG_G(seek), address)) { + if (INDEX_EXISTS_CHECK) { PHPDBG_G(flags) &= ~PHPDBG_IN_FINISH; - zend_hash_clean( - &PHPDBG_G(seek)); + zend_hash_clean(&PHPDBG_G(seek)); } /* skip possible breakpoints */ goto next; @@ -1253,16 +1573,14 @@ zend_vm_enter: /* break for leave */ if (PHPDBG_G(flags) & PHPDBG_IN_LEAVE) { - if (zend_hash_index_exists(&PHPDBG_G(seek), address)) { + if (INDEX_EXISTS_CHECK) { PHPDBG_G(flags) &= ~PHPDBG_IN_LEAVE; - zend_hash_clean( - &PHPDBG_G(seek)); - phpdbg_notice( - "Breaking for leave at %s:%u", - zend_get_executed_filename(TSRMLS_C), - zend_get_executed_lineno(TSRMLS_C) + zend_hash_clean(&PHPDBG_G(seek)); + phpdbg_notice("breakpoint", "id=\"leave\" file=\"%s\" line=\"%u\"", "Breaking for leave at %s:%u", + zend_get_executed_filename(), + zend_get_executed_lineno() ); - DO_INTERACTIVE(); + DO_INTERACTIVE(1); } else { /* skip possible breakpoints */ goto next; @@ -1271,18 +1589,17 @@ zend_vm_enter: } /* not while in conditionals */ - phpdbg_print_opline_ex( - execute_data, &vars, 0 TSRMLS_CC); + phpdbg_print_opline_ex(execute_data, 0); if (PHPDBG_G(flags) & PHPDBG_IS_STEPPING && (PHPDBG_G(flags) & PHPDBG_STEP_OPCODE || execute_data->opline->lineno != PHPDBG_G(last_line))) { PHPDBG_G(flags) &= ~PHPDBG_IS_STEPPING; - DO_INTERACTIVE(); + DO_INTERACTIVE(1); } /* check if some watchpoint was hit */ { - if (phpdbg_print_changed_zvals(TSRMLS_C) == SUCCESS) { - DO_INTERACTIVE(); + if (phpdbg_print_changed_zvals() == SUCCESS) { + DO_INTERACTIVE(1); } } @@ -1291,45 +1608,94 @@ zend_vm_enter: phpdbg_breakbase_t *brake; if ((PHPDBG_G(flags) & PHPDBG_BP_MASK) - && (brake = phpdbg_find_breakpoint(execute_data TSRMLS_CC)) + && (brake = phpdbg_find_breakpoint(execute_data)) && (brake->type != PHPDBG_BREAK_FILE || execute_data->opline->lineno != PHPDBG_G(last_line))) { - phpdbg_hit_breakpoint(brake, 1 TSRMLS_CC); - DO_INTERACTIVE(); + phpdbg_hit_breakpoint(brake, 1); + DO_INTERACTIVE(1); } } -next: if (PHPDBG_G(flags) & PHPDBG_IS_SIGNALED) { - phpdbg_writeln(EMPTY); - phpdbg_notice("Program received signal SIGINT"); PHPDBG_G(flags) &= ~PHPDBG_IS_SIGNALED; - DO_INTERACTIVE(); + + phpdbg_out("\n"); + phpdbg_notice("signal", "type=\"SIGINT\"", "Program received signal SIGINT"); + DO_INTERACTIVE(1); } +next: + PHPDBG_G(last_line) = execute_data->opline->lineno; - PHPDBG_G(vmret) = execute_data->opline->handler(execute_data TSRMLS_CC); + /* stupid hack to make zend_do_fcall_common_helper return ZEND_VM_ENTER() instead of recursively calling zend_execute() and eventually segfaulting */ + if ((execute_data->opline->opcode == ZEND_DO_FCALL || + execute_data->opline->opcode == ZEND_DO_UCALL || + execute_data->opline->opcode == ZEND_DO_FCALL_BY_NAME) && + execute_data->call->func->type == ZEND_USER_FUNCTION) { + zend_execute_ex = execute_ex; + } + PHPDBG_G(vmret) = zend_vm_call_opcode_handler(execute_data); + zend_execute_ex = phpdbg_execute_ex; - if (PHPDBG_G(vmret) > 0) { - switch (PHPDBG_G(vmret)) { - case 1: - EG(in_execution) = original_in_execution; - zend_hash_destroy(&vars); - return; - case 2: -#if PHP_VERSION_ID < 50500 - op_array = EG(active_op_array); -#endif - zend_hash_destroy(&vars); - goto zend_vm_enter; - break; - case 3: - execute_data = EG(current_execute_data); - break; - default: - break; + if (PHPDBG_G(vmret) != 0) { + if (PHPDBG_G(vmret) < 0) { + PHPDBG_G(in_execution) = original_in_execution; + return; + } else { + execute_data = EG(current_execute_data); } } } zend_error_noreturn(E_ERROR, "Arrived at end of main loop which shouldn't happen"); } /* }}} */ + +/* only if *not* interactive and while executing */ +void phpdbg_force_interruption(void) /* {{{ */ { + zend_object *exception = EG(exception); + zend_execute_data *data = EG(current_execute_data); /* should be always readable if not NULL */ + + PHPDBG_G(flags) |= PHPDBG_IN_SIGNAL_HANDLER; + + if (data) { + if (data->func) { + if (ZEND_USER_CODE(data->func->type)) { + phpdbg_notice("hardinterrupt", "opline=\"%p\" num=\"%lu\" file=\"%s\" line=\"%u\"", "Current opline: %p (op #%lu) in %s:%u", data->opline, (data->opline - data->func->op_array.opcodes) / sizeof(data->opline), data->func->op_array.filename->val, data->opline->lineno); + } else if (data->func->internal_function.function_name) { + phpdbg_notice("hardinterrupt", "func=\"%s\"", "Current opline: in internal function %s", data->func->internal_function.function_name->val); + } else { + phpdbg_notice("hardinterrupt", "", "Current opline: executing internal code"); + } + } else { + phpdbg_notice("hardinterrupt", "opline=\"%p\"", "Current opline: %p (op_array information unavailable)", data->opline); + } + } else { + phpdbg_notice("hardinterrupt", "", "No information available about executing context"); + } + + DO_INTERACTIVE(0); + +next: + PHPDBG_G(flags) &= ~PHPDBG_IN_SIGNAL_HANDLER; + + if (PHPDBG_G(flags) & PHPDBG_IS_STOPPING) { + zend_bailout(); + } +} +/* }}} */ + +PHPDBG_COMMAND(eol) /* {{{ */ +{ + if (!param || param->type == EMPTY_PARAM) { + phpdbg_notice("eol", "argument required", "argument required"); + } else switch (param->type) { + case STR_PARAM: + if (FAILURE == phpdbg_eol_global_update(param->str)) { + phpdbg_notice("eol", "unknown EOL name '%s', give crlf, lf, cr", "unknown EOL name '%s', give crlf, lf, cr", param->str); + } + break; + + phpdbg_default_switch_case(); + } + + return SUCCESS; +} /* }}} */ diff --git a/sapi/phpdbg/phpdbg_prompt.h b/sapi/phpdbg/phpdbg_prompt.h index 1a77428921..c17e7185ce 100644 --- a/sapi/phpdbg/phpdbg_prompt.h +++ b/sapi/phpdbg/phpdbg_prompt.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -22,11 +22,13 @@ #define PHPDBG_PROMPT_H /* {{{ */ -void phpdbg_init(char *init_file, size_t init_file_len, zend_bool use_default TSRMLS_DC); -void phpdbg_try_file_init(char *init_file, size_t init_file_len, zend_bool free_init TSRMLS_DC); -int phpdbg_interactive(TSRMLS_D); -int phpdbg_compile(TSRMLS_D); -void phpdbg_clean(zend_bool full TSRMLS_DC); /* }}} */ +void phpdbg_string_init(char *buffer); +void phpdbg_init(char *init_file, size_t init_file_len, zend_bool use_default); +void phpdbg_try_file_init(char *init_file, size_t init_file_len, zend_bool free_init); +int phpdbg_interactive(zend_bool allow_async_unsafe); +int phpdbg_compile(void); +void phpdbg_force_interruption(void); +/* }}} */ /* {{{ phpdbg command handlers */ PHPDBG_COMMAND(exec); @@ -47,21 +49,20 @@ PHPDBG_COMMAND(clean); PHPDBG_COMMAND(clear); PHPDBG_COMMAND(help); PHPDBG_COMMAND(sh); +PHPDBG_COMMAND(dl); PHPDBG_COMMAND(set); PHPDBG_COMMAND(source); PHPDBG_COMMAND(export); PHPDBG_COMMAND(register); PHPDBG_COMMAND(quit); -PHPDBG_COMMAND(watch); /* }}} */ +PHPDBG_COMMAND(watch); +PHPDBG_COMMAND(next); +PHPDBG_COMMAND(eol); +PHPDBG_COMMAND(wait); /* }}} */ /* {{{ prompt commands */ extern const phpdbg_command_t phpdbg_prompt_commands[]; /* }}} */ -/* {{{ */ -#if PHP_VERSION_ID >= 50500 -void phpdbg_execute_ex(zend_execute_data *execute_data TSRMLS_DC); -#else -void phpdbg_execute_ex(zend_op_array *op_array TSRMLS_DC); -#endif /* }}} */ +void phpdbg_execute_ex(zend_execute_data *execute_data); #endif /* PHPDBG_PROMPT_H */ diff --git a/sapi/phpdbg/phpdbg_rinit_hook.c b/sapi/phpdbg/phpdbg_rinit_hook.c new file mode 100644 index 0000000000..e0693acbbf --- /dev/null +++ b/sapi/phpdbg/phpdbg_rinit_hook.c @@ -0,0 +1,105 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2016 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: Bob Weinand <bwoebi@php.net> | + +----------------------------------------------------------------------+ +*/ + +#include "phpdbg_rinit_hook.h" +#include "php_ini.h" +#include <errno.h> + +ZEND_DECLARE_MODULE_GLOBALS(phpdbg_webhelper); + +PHP_INI_BEGIN() + STD_PHP_INI_ENTRY("phpdbg.auth", "", PHP_INI_SYSTEM | PHP_INI_PERDIR, OnUpdateString, auth, zend_phpdbg_webhelper_globals, phpdbg_webhelper_globals) + STD_PHP_INI_ENTRY("phpdbg.path", "", PHP_INI_SYSTEM | PHP_INI_PERDIR, OnUpdateString, path, zend_phpdbg_webhelper_globals, phpdbg_webhelper_globals) +PHP_INI_END() + +static inline void php_phpdbg_webhelper_globals_ctor(zend_phpdbg_webhelper_globals *pg) /* {{{ */ +{ +} /* }}} */ + +static PHP_MINIT_FUNCTION(phpdbg_webhelper) /* {{{ */ +{ + if (!strcmp(sapi_module.name, PHPDBG_NAME)) { + return SUCCESS; + } + + ZEND_INIT_MODULE_GLOBALS(phpdbg_webhelper, php_phpdbg_webhelper_globals_ctor, NULL); + REGISTER_INI_ENTRIES(); + + return SUCCESS; +} /* }}} */ + +static PHP_RINIT_FUNCTION(phpdbg_webhelper) /* {{{ */ +{ + zval cookies = PG(http_globals)[TRACK_VARS_COOKIE]; + zval *auth; + + if (Z_TYPE(cookies) == IS_ARRAY || (auth = zend_hash_str_find(Z_ARRVAL(cookies), PHPDBG_NAME "_AUTH_COOKIE", sizeof(PHPDBG_NAME "_AUTH_COOKIE"))) || Z_STRLEN_P(auth) != strlen(PHPDBG_WG(auth)) || strcmp(Z_STRVAL_P(auth), PHPDBG_WG(auth))) { + return SUCCESS; + } + +#ifndef _WIN32 + { + struct sockaddr_un sock; + int s = socket(AF_UNIX, SOCK_STREAM, 0); + int len = strlen(PHPDBG_WG(path)) + sizeof(sock.sun_family); + char buf[(1 << 8) + 1]; + int buflen; + sock.sun_family = AF_UNIX; + strcpy(sock.sun_path, PHPDBG_WG(path)); + + if (connect(s, (struct sockaddr *)&sock, len) == -1) { + zend_error(E_ERROR, "Unable to connect to UNIX domain socket at %s defined by phpdbg.path ini setting. Reason: %s", PHPDBG_WG(path), strerror(errno)); + } + + char *msg = NULL; + char msglen[5] = {0}; + phpdbg_webdata_compress(&msg, (int *)msglen); + + send(s, msglen, 4, 0); + send(s, msg, *(int *) msglen, 0); + + while ((buflen = recv(s, buf, sizeof(buf) - 1, 0)) > 0) { + php_write(buf, buflen); + } + + close(s); + + php_output_flush_all(); + zend_bailout(); + } +#endif + + return SUCCESS; +} /* }}} */ + +zend_module_entry phpdbg_webhelper_module_entry = { + STANDARD_MODULE_HEADER, + "phpdbg_webhelper", + NULL, + PHP_MINIT(phpdbg_webhelper), + NULL, + PHP_RINIT(phpdbg_webhelper), + NULL, + NULL, + PHPDBG_VERSION, + STANDARD_MODULE_PROPERTIES +}; + +#ifdef COMPILE_DL_PHPDBG_WEBHELPER +ZEND_GET_MODULE(phpdbg_webhelper) +#endif diff --git a/sapi/phpdbg/phpdbg_rinit_hook.h b/sapi/phpdbg/phpdbg_rinit_hook.h new file mode 100644 index 0000000000..2e56df17a9 --- /dev/null +++ b/sapi/phpdbg/phpdbg_rinit_hook.h @@ -0,0 +1,41 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2016 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: Felipe Pena <felipe@php.net> | + | Authors: Joe Watkins <joe.watkins@live.co.uk> | + | Authors: Bob Weinand <bwoebi@php.net> | + +----------------------------------------------------------------------+ +*/ + +#ifndef PHPDBG_WEBHELPER_H +#define PHPDBG_WEBHELPER_H + +#include "phpdbg_webdata_transfer.h" + +extern zend_module_entry phpdbg_webhelper_module_entry; +#define phpext_phpdbg_webhelper_ptr &phpdbg_webhelper_module_entry + +#ifdef ZTS +# define PHPDBG_WG(v) TSRMG(phpdbg_webhelper_globals_id, zend_phpdbg_webhelper_globals *, v) +#else +# define PHPDBG_WG(v) (phpdbg_webhelper_globals.v) +#endif + +/* {{{ structs */ +ZEND_BEGIN_MODULE_GLOBALS(phpdbg_webhelper) + char *auth; + char *path; +ZEND_END_MODULE_GLOBALS(phpdbg_webhelper) /* }}} */ + +#endif /* PHPDBG_WEBHELPER_H */ diff --git a/sapi/phpdbg/phpdbg_set.c b/sapi/phpdbg/phpdbg_set.c index 9252d7811a..47ecbd08b6 100644 --- a/sapi/phpdbg/phpdbg_set.c +++ b/sapi/phpdbg/phpdbg_set.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -25,31 +25,71 @@ #include "phpdbg_bp.h" #include "phpdbg_prompt.h" -ZEND_EXTERN_MODULE_GLOBALS(phpdbg); +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) -#define PHPDBG_SET_COMMAND_D(f, h, a, m, l, s) \ - PHPDBG_COMMAND_D_EXP(f, h, a, m, l, s, &phpdbg_prompt_commands[18]) +#define PHPDBG_SET_COMMAND_D(f, h, a, m, l, s, flags) \ + PHPDBG_COMMAND_D_EXP(f, h, a, m, l, s, &phpdbg_prompt_commands[17], flags) const phpdbg_command_t phpdbg_set_commands[] = { - PHPDBG_SET_COMMAND_D(prompt, "usage: set prompt [<string>]", 'p', set_prompt, NULL, "|s"), + PHPDBG_SET_COMMAND_D(prompt, "usage: set prompt [<string>]", 'p', set_prompt, NULL, "|s", 0), + PHPDBG_SET_COMMAND_D(pagination, "usage: set pagination [<on|off>]", 'P', set_pagination, NULL, "|b", PHPDBG_ASYNC_SAFE), #ifndef _WIN32 - PHPDBG_SET_COMMAND_D(color, "usage: set color <element> <color>", 'c', set_color, NULL, "ss"), - PHPDBG_SET_COMMAND_D(colors, "usage: set colors [<on|off>]", 'C', set_colors, NULL, "|b"), + PHPDBG_SET_COMMAND_D(color, "usage: set color <element> <color>", 'c', set_color, NULL, "ss", PHPDBG_ASYNC_SAFE), + PHPDBG_SET_COMMAND_D(colors, "usage: set colors [<on|off>]", 'C', set_colors, NULL, "|b", PHPDBG_ASYNC_SAFE), #endif - PHPDBG_SET_COMMAND_D(oplog, "usage: set oplog [<output>]", 'O', set_oplog, NULL, "|s"), - PHPDBG_SET_COMMAND_D(break, "usage: set break id [<on|off>]", 'b', set_break, NULL, "l|b"), - PHPDBG_SET_COMMAND_D(breaks, "usage: set breaks [<on|off>]", 'B', set_breaks, NULL, "|b"), - PHPDBG_SET_COMMAND_D(quiet, "usage: set quiet [<on|off>]", 'q', set_quiet, NULL, "|b"), - PHPDBG_SET_COMMAND_D(stepping, "usage: set stepping [<line|op>]", 's', set_stepping, NULL, "|s"), - PHPDBG_SET_COMMAND_D(refcount, "usage: set refcount [<on|off>]", 'r', set_refcount, NULL, "|b"), + PHPDBG_SET_COMMAND_D(oplog, "usage: set oplog [<output>]", 'O', set_oplog, NULL, "|s", 0), + PHPDBG_SET_COMMAND_D(break, "usage: set break id [<on|off>]", 'b', set_break, NULL, "l|b", PHPDBG_ASYNC_SAFE), + PHPDBG_SET_COMMAND_D(breaks, "usage: set breaks [<on|off>]", 'B', set_breaks, NULL, "|b", PHPDBG_ASYNC_SAFE), + PHPDBG_SET_COMMAND_D(quiet, "usage: set quiet [<on|off>]", 'q', set_quiet, NULL, "|b", PHPDBG_ASYNC_SAFE), + PHPDBG_SET_COMMAND_D(stepping, "usage: set stepping [<line|op>]", 's', set_stepping, NULL, "|s", PHPDBG_ASYNC_SAFE), + PHPDBG_SET_COMMAND_D(refcount, "usage: set refcount [<on|off>]", 'r', set_refcount, NULL, "|b", PHPDBG_ASYNC_SAFE), + PHPDBG_SET_COMMAND_D(lines, "usage: set lines [<number>]", 'l', set_lines, NULL, "|l", PHPDBG_ASYNC_SAFE), PHPDBG_END_COMMAND }; PHPDBG_SET(prompt) /* {{{ */ { if (!param || param->type == EMPTY_PARAM) { - phpdbg_writeln("%s", phpdbg_get_prompt(TSRMLS_C)); - } else phpdbg_set_prompt(param->str TSRMLS_CC); + phpdbg_writeln("setprompt", "str=\"%s\"", "Current prompt: %s", phpdbg_get_prompt()); + } else { + phpdbg_set_prompt(param->str); + } + + return SUCCESS; +} /* }}} */ + +PHPDBG_SET(pagination) /* {{{ */ +{ + if (!param || param->type == EMPTY_PARAM) { + phpdbg_writeln("setpagination", "active=\"%s\"", "Pagination %s", PHPDBG_G(flags) & PHPDBG_HAS_PAGINATION ? "on" : "off"); + } else switch (param->type) { + case NUMERIC_PARAM: { + if (param->num) { + PHPDBG_G(flags) |= PHPDBG_HAS_PAGINATION; + } else { + PHPDBG_G(flags) &= ~PHPDBG_HAS_PAGINATION; + } + } break; + + default: + phpdbg_error("setpagination", "type=\"wrongargs\"", "set pagination used incorrectly: set pagination <on|off>"); + } + + return SUCCESS; +} /* }}} */ + +PHPDBG_SET(lines) /* {{{ */ +{ + if (!param || param->type == EMPTY_PARAM) { + phpdbg_writeln("setlines", "active=\"%s\"", "Lines %ld", PHPDBG_G(lines)); + } else switch (param->type) { + case NUMERIC_PARAM: { + PHPDBG_G(lines) = param->num; + } break; + + default: + phpdbg_error("setlines", "type=\"wrongargs\"", "set lines used incorrectly: set lines <number>"); + } return SUCCESS; } /* }}} */ @@ -60,22 +100,22 @@ PHPDBG_SET(break) /* {{{ */ case NUMERIC_PARAM: { if (param->next) { if (param->next->num) { - phpdbg_enable_breakpoint(param->num TSRMLS_CC); - } else phpdbg_disable_breakpoint(param->num TSRMLS_CC); + phpdbg_enable_breakpoint(param->num); + } else { + phpdbg_disable_breakpoint(param->num); + } } else { - phpdbg_breakbase_t *brake = phpdbg_find_breakbase(param->num TSRMLS_CC); + phpdbg_breakbase_t *brake = phpdbg_find_breakbase(param->num); if (brake) { - phpdbg_writeln( - "%s", brake->disabled ? "off" : "on"); + phpdbg_writeln("setbreak", "id=\"%ld\" active=\"%s\"", "Breakpoint #%ld %s", param->num, brake->disabled ? "off" : "on"); } else { - phpdbg_error("Failed to find breakpoint #%ld", param->num); + phpdbg_error("setbreak", "type=\"nobreak\" id=\"%ld\"", "Failed to find breakpoint #%ld", param->num); } } } break; default: - phpdbg_error( - "set break used incorrectly: set break [id] <on|off>"); + phpdbg_error("setbreak", "type=\"wrongargs\"", "set break used incorrectly: set break [id] <on|off>"); } return SUCCESS; @@ -84,18 +124,18 @@ PHPDBG_SET(break) /* {{{ */ PHPDBG_SET(breaks) /* {{{ */ { if (!param || param->type == EMPTY_PARAM) { - phpdbg_writeln("%s", - PHPDBG_G(flags) & PHPDBG_IS_BP_ENABLED ? "on" : "off"); - } else switch (param->type) { + phpdbg_writeln("setbreaks", "active=\"%s\"", "Breakpoints %s",PHPDBG_G(flags) & PHPDBG_IS_BP_ENABLED ? "on" : "off"); + } else switch (param->type) { case NUMERIC_PARAM: { if (param->num) { - phpdbg_enable_breakpoints(TSRMLS_C); - } else phpdbg_disable_breakpoints(TSRMLS_C); + phpdbg_enable_breakpoints(); + } else { + phpdbg_disable_breakpoints(); + } } break; default: - phpdbg_error( - "set break used incorrectly: set break [id] <on|off>"); + phpdbg_error("setbreaks", "type=\"wrongargs\"", "set breaks used incorrectly: set breaks <on|off>"); } return SUCCESS; @@ -104,41 +144,35 @@ PHPDBG_SET(breaks) /* {{{ */ #ifndef _WIN32 PHPDBG_SET(color) /* {{{ */ { - const phpdbg_color_t *color = phpdbg_get_color( - param->next->str, param->next->len TSRMLS_CC); - + const phpdbg_color_t *color = phpdbg_get_color(param->next->str, param->next->len); + if (!color) { - phpdbg_error( - "Failed to find the requested color (%s)", param->next->str); + phpdbg_error("setcolor", "type=\"nocolor\"", "Failed to find the requested color (%s)", param->next->str); return SUCCESS; } - - switch (phpdbg_get_element(param->str, param->len TSRMLS_CC)) { + + switch (phpdbg_get_element(param->str, param->len)) { case PHPDBG_COLOR_PROMPT: - phpdbg_notice( - "setting prompt color to %s (%s)", color->name, color->code); + phpdbg_notice("setcolor", "type=\"prompt\" color=\"%s\" code=\"%s\"", "setting prompt color to %s (%s)", color->name, color->code); if (PHPDBG_G(prompt)[1]) { free(PHPDBG_G(prompt)[1]); PHPDBG_G(prompt)[1]=NULL; } - phpdbg_set_color(PHPDBG_COLOR_PROMPT, color TSRMLS_CC); + phpdbg_set_color(PHPDBG_COLOR_PROMPT, color); break; - + case PHPDBG_COLOR_ERROR: - phpdbg_notice( - "setting error color to %s (%s)", color->name, color->code); - phpdbg_set_color(PHPDBG_COLOR_ERROR, color TSRMLS_CC); + phpdbg_notice("setcolor", "type=\"error\" color=\"%s\" code=\"%s\"", "setting error color to %s (%s)", color->name, color->code); + phpdbg_set_color(PHPDBG_COLOR_ERROR, color); break; - + case PHPDBG_COLOR_NOTICE: - phpdbg_notice( - "setting notice color to %s (%s)", color->name, color->code); - phpdbg_set_color(PHPDBG_COLOR_NOTICE, color TSRMLS_CC); + phpdbg_notice("setcolor", "type=\"notice\" color=\"%s\" code=\"%s\"", "setting notice color to %s (%s)", color->name, color->code); + phpdbg_set_color(PHPDBG_COLOR_NOTICE, color); break; - + default: - phpdbg_error( - "Failed to find the requested element (%s)", param->str); + phpdbg_error("setcolor", "type=\"invalidtype\"", "Failed to find the requested element (%s)", param->str); } return SUCCESS; @@ -147,7 +181,7 @@ PHPDBG_SET(color) /* {{{ */ PHPDBG_SET(colors) /* {{{ */ { if (!param || param->type == EMPTY_PARAM) { - phpdbg_writeln("%s", PHPDBG_G(flags) & PHPDBG_IS_COLOURED ? "on" : "off"); + phpdbg_writeln("setcolors", "active=\"%s\"", "Colors %s", PHPDBG_G(flags) & PHPDBG_IS_COLOURED ? "on" : "off"); } else switch (param->type) { case NUMERIC_PARAM: { if (param->num) { @@ -156,10 +190,9 @@ PHPDBG_SET(colors) /* {{{ */ PHPDBG_G(flags) &= ~PHPDBG_IS_COLOURED; } } break; - + default: - phpdbg_error( - "set colors used incorrectly: set colors <on|off>"); + phpdbg_error("setcolors", "type=\"wrongargs\"", "set colors used incorrectly: set colors <on|off>"); } return SUCCESS; @@ -169,7 +202,7 @@ PHPDBG_SET(colors) /* {{{ */ PHPDBG_SET(oplog) /* {{{ */ { if (!param || param->type == EMPTY_PARAM) { - phpdbg_notice("Oplog %s", PHPDBG_G(oplog) ? "enabled" : "disabled"); + phpdbg_notice("setoplog", "active=\"%s\"", "Oplog %s", PHPDBG_G(oplog) ? "on" : "off"); } else switch (param->type) { case STR_PARAM: { /* open oplog */ @@ -177,14 +210,15 @@ PHPDBG_SET(oplog) /* {{{ */ PHPDBG_G(oplog) = fopen(param->str, "w+"); if (!PHPDBG_G(oplog)) { - phpdbg_error("Failed to open %s for oplog", param->str); + phpdbg_error("setoplog", "type=\"openfailure\" file=\"%s\"", "Failed to open %s for oplog", param->str); PHPDBG_G(oplog) = old; } else { if (old) { - phpdbg_notice("Closing previously open oplog"); + phpdbg_notice("setoplog", "type=\"closingold\"", "Closing previously open oplog"); fclose(old); } - phpdbg_notice("Successfully opened oplog %s", param->str); + + phpdbg_notice("setoplog", "file=\"%s\"", "Successfully opened oplog %s", param->str); } } break; @@ -197,8 +231,7 @@ PHPDBG_SET(oplog) /* {{{ */ PHPDBG_SET(quiet) /* {{{ */ { if (!param || param->type == EMPTY_PARAM) { - phpdbg_writeln("Quietness %s", - PHPDBG_G(flags) & PHPDBG_IS_QUIET ? "on" : "off"); + phpdbg_writeln("setquiet", "active=\"%s\"", "Quietness %s", PHPDBG_G(flags) & PHPDBG_IS_QUIET ? "on" : "off"); } else switch (param->type) { case NUMERIC_PARAM: { if (param->num) { @@ -217,18 +250,15 @@ PHPDBG_SET(quiet) /* {{{ */ PHPDBG_SET(stepping) /* {{{ */ { if (!param || param->type == EMPTY_PARAM) { - phpdbg_writeln("Stepping %s", - PHPDBG_G(flags) & PHPDBG_STEP_OPCODE ? "opcode" : "line"); + phpdbg_writeln("setstepping", "type=\"%s\"", "Stepping %s", PHPDBG_G(flags) & PHPDBG_STEP_OPCODE ? "opcode" : "line"); } else switch (param->type) { - case STR_PARAM: { - if ((param->len == sizeof("opcode")-1) && - (memcmp(param->str, "opcode", sizeof("opcode")) == SUCCESS)) { + case STR_PARAM: { + if (param->len == sizeof("opcode") - 1 && !memcmp(param->str, "opcode", sizeof("opcode"))) { PHPDBG_G(flags) |= PHPDBG_STEP_OPCODE; - } else if ((param->len == sizeof("line")-1) && - (memcmp(param->str, "line", sizeof("line")) == SUCCESS)) { + } else if (param->len == sizeof("line") - 1 && !memcmp(param->str, "line", sizeof("line"))) { PHPDBG_G(flags) &= ~PHPDBG_STEP_OPCODE; } else { - phpdbg_error("usage set stepping [<opcode|line>]"); + phpdbg_error("setstepping", "type=\"wrongargs\"", "usage set stepping [<opcode|line>]"); } } break; @@ -241,7 +271,7 @@ PHPDBG_SET(stepping) /* {{{ */ PHPDBG_SET(refcount) /* {{{ */ { if (!param || param->type == EMPTY_PARAM) { - phpdbg_writeln("Refcount %s", PHPDBG_G(flags) & PHPDBG_IS_QUIET ? "on" : "off"); + phpdbg_writeln("setrefcount", "active=\"%s\"", "Showing refcounts %s", PHPDBG_G(flags) & PHPDBG_IS_QUIET ? "on" : "off"); } else switch (param->type) { case NUMERIC_PARAM: { if (param->num) { diff --git a/sapi/phpdbg/phpdbg_set.h b/sapi/phpdbg/phpdbg_set.h index d337c5b2c4..e1c0105e40 100644 --- a/sapi/phpdbg/phpdbg_set.h +++ b/sapi/phpdbg/phpdbg_set.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -36,6 +36,8 @@ PHPDBG_SET(breaks); PHPDBG_SET(quiet); PHPDBG_SET(stepping); PHPDBG_SET(refcount); +PHPDBG_SET(pagination); +PHPDBG_SET(lines); extern const phpdbg_command_t phpdbg_set_commands[]; diff --git a/sapi/phpdbg/phpdbg_sigio_win32.c b/sapi/phpdbg/phpdbg_sigio_win32.c new file mode 100644 index 0000000000..db334a0dc5 --- /dev/null +++ b/sapi/phpdbg/phpdbg_sigio_win32.c @@ -0,0 +1,112 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 2014-2016 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: Anatol Belski <ab@php.net> | + +----------------------------------------------------------------------+ +*/ + + +#include <signal.h> + +#include "phpdbg.h" +#include "phpdbg_sigio_win32.h" + + +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) + + +VOID +SigIoWatcherThread(VOID *p) +{ + zend_uchar sig; + struct win32_sigio_watcher_data *swd = (struct win32_sigio_watcher_data *)p; + +top: + (void)phpdbg_consume_bytes(swd->fd, &sig, 1, -1); + + + if (3 == sig) { + /* XXX completely not sure it is done right here */ + if (*swd->flags & PHPDBG_IS_INTERACTIVE) { + if (raise(sig)) { + goto top; + } + } + if (*swd->flags & PHPDBG_IS_SIGNALED) { + phpdbg_set_sigsafe_mem(&sig); + zend_try { + phpdbg_force_interruption(); + } zend_end_try(); + phpdbg_clear_sigsafe_mem(); + goto end; + } + if (!(*swd->flags & PHPDBG_IS_INTERACTIVE)) { + *swd->flags |= PHPDBG_IS_SIGNALED; + } +end: + /* XXX set signaled flag to the caller thread, question is - whether it's needed */ + ExitThread(sig); + } else { + goto top; + } +} + + +/* Start this only for the time of the run or eval command, +for so long that the main thread is busy serving some debug +session. */ +void +sigio_watcher_start(void) +{ + + PHPDBG_G(swd).fd = PHPDBG_G(io)[PHPDBG_STDIN].fd; +#ifdef ZTS + PHPDBG_G(swd).flags = &PHPDBG_G(flags); +#endif + + PHPDBG_G(sigio_watcher_thread) = CreateThread( + NULL, + 0, + (LPTHREAD_START_ROUTINE)SigIoWatcherThread, + &PHPDBG_G(swd), + 0, + NULL); +} + +void +sigio_watcher_stop(void) +{ + DWORD waited; + + if (INVALID_HANDLE_VALUE == PHPDBG_G(sigio_watcher_thread)) { + /* it probably did bail out already */ + return; + } + + waited = WaitForSingleObject(PHPDBG_G(sigio_watcher_thread), 300); + + if (WAIT_OBJECT_0 != waited) { + if (!CancelSynchronousIo(PHPDBG_G(sigio_watcher_thread))) { + /* error out */ + } + + if (!TerminateThread(PHPDBG_G(sigio_watcher_thread), 0)) { + /* error out */ + } + } + + PHPDBG_G(swd).fd = -1; + PHPDBG_G(sigio_watcher_thread) = INVALID_HANDLE_VALUE; +} + diff --git a/sapi/phpdbg/phpdbg_sigio_win32.h b/sapi/phpdbg/phpdbg_sigio_win32.h new file mode 100644 index 0000000000..83b07d64b7 --- /dev/null +++ b/sapi/phpdbg/phpdbg_sigio_win32.h @@ -0,0 +1,38 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 2014-2016 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: Anatol Belski <ab@php.net> | + +----------------------------------------------------------------------+ +*/ + + +#ifndef PHPDBG_SIGIO_WIN32_H +#define PHPDBG_SIGIO_WIN32_H + +#include "phpdbg.h" +#include "phpdbg_prompt.h" +#include "phpdbg_io.h" + +struct win32_sigio_watcher_data { + uint64_t *flags; + int fd; +}; + +void +sigio_watcher_start(void); + +void +sigio_watcher_stop(void); + +#endif /* PHPDBG_SIGIO_WIN32_H */ diff --git a/sapi/phpdbg/phpdbg_sigsafe.c b/sapi/phpdbg/phpdbg_sigsafe.c new file mode 100644 index 0000000000..2f987b3a15 --- /dev/null +++ b/sapi/phpdbg/phpdbg_sigsafe.c @@ -0,0 +1,59 @@ +#include "phpdbg_sigsafe.h" +#include "phpdbg.h" + +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) + +#define STR(x) #x +#define EXP_STR(x) STR(x) + +static void* zend_mm_mem_alloc(zend_mm_storage *storage, size_t size, size_t alignment) { + + if (EXPECTED(size <= PHPDBG_SIGSAFE_MEM_SIZE && !PHPDBG_G(sigsafe_mem).allocated)) { + PHPDBG_G(sigsafe_mem).allocated = 1; + return (void *) (((size_t) PHPDBG_G(sigsafe_mem).mem & ~(alignment - 1)) + alignment); + } + + quiet_write(PHPDBG_G(io)[PHPDBG_STDERR].fd, ZEND_STRL("Tried to allocate more than " EXP_STR(PHPDBG_SIGSAFE_MEM_SIZE) " bytes from stack memory in signal handler ... bailing out of signal handler\n")); + + if (*EG(bailout)) { + LONGJMP(*EG(bailout), FAILURE); + } + + quiet_write(PHPDBG_G(io)[PHPDBG_STDERR].fd, ZEND_STRL("Bailed out without a bailout address in signal handler!\n")); + + return NULL; +} + +static void zend_mm_mem_free(zend_mm_storage *storage, void *ptr, size_t size) { +} + +void phpdbg_set_sigsafe_mem(char *buffer) { + phpdbg_signal_safe_mem *mem = &PHPDBG_G(sigsafe_mem); + const zend_mm_handlers phpdbg_handlers = { + zend_mm_mem_alloc, + zend_mm_mem_free, + NULL, + NULL, + }; + + mem->mem = buffer; + mem->allocated = 0; + + mem->heap = zend_mm_startup_ex(&phpdbg_handlers, NULL, 0); + + mem->old_heap = zend_mm_set_heap(mem->heap); +} + +zend_mm_heap *phpdbg_original_heap_sigsafe_mem(void) { + return PHPDBG_G(sigsafe_mem).old_heap; +} + +void phpdbg_clear_sigsafe_mem(void) { + zend_mm_set_heap(phpdbg_original_heap_sigsafe_mem()); + PHPDBG_G(sigsafe_mem).mem = NULL; +} + +zend_bool phpdbg_active_sigsafe_mem(void) { + return !!PHPDBG_G(sigsafe_mem).mem; +} + diff --git a/sapi/phpdbg/phpdbg_sigsafe.h b/sapi/phpdbg/phpdbg_sigsafe.h new file mode 100644 index 0000000000..ab689a38d8 --- /dev/null +++ b/sapi/phpdbg/phpdbg_sigsafe.h @@ -0,0 +1,24 @@ +#ifndef PHPDBG_SIGSAFE_H +#define PHPDBG_SIGSAFE_H + +#define PHPDBG_SIGSAFE_MEM_SIZE (ZEND_MM_CHUNK_SIZE * 2) + +#include "zend.h" + +typedef struct { + char *mem; + zend_bool allocated; + zend_mm_heap *heap; + zend_mm_heap *old_heap; +} phpdbg_signal_safe_mem; + +#include "phpdbg.h" + +zend_bool phpdbg_active_sigsafe_mem(void); + +void phpdbg_set_sigsafe_mem(char *mem); +void phpdbg_clear_sigsafe_mem(void); + +zend_mm_heap *phpdbg_original_heap_sigsafe_mem(void); + +#endif diff --git a/sapi/phpdbg/phpdbg_utils.c b/sapi/phpdbg/phpdbg_utils.c index 18d9b3c0d5..7158f3ba6c 100644 --- a/sapi/phpdbg/phpdbg_utils.c +++ b/sapi/phpdbg/phpdbg_utils.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -18,26 +18,27 @@ +----------------------------------------------------------------------+ */ -#include <stdio.h> -#include <ctype.h> -#include <string.h> #include "zend.h" + #include "php.h" -#include "spprintf.h" #include "phpdbg.h" #include "phpdbg_opcode.h" #include "phpdbg_utils.h" +#include "ext/standard/php_string.h" -#ifdef _WIN32 -# include "win32/time.h" -#elif defined(HAVE_SYS_IOCTL_H) -# include "sys/ioctl.h" -# ifndef GWINSZ_IN_SYS_IOCTL -# include <termios.h> -# endif +/* FASYNC under Solaris */ +#ifdef HAVE_SYS_FILE_H +# include <sys/file.h> +#endif + +#ifdef HAVE_SYS_IOCTL_H +# include "sys/ioctl.h" +# ifndef GWINSZ_IN_SYS_IOCTL +# include <termios.h> +# endif #endif -ZEND_EXTERN_MODULE_GLOBALS(phpdbg); +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) /* {{{ color structures */ const static phpdbg_color_t colors[] = { @@ -128,12 +129,12 @@ PHPDBG_API int phpdbg_is_class_method(const char *str, size_t len, char **class, } if (class != NULL) { - + if (str[0] == '\\') { str++; len--; } - + *class = estrndup(str, sep - str); (*class)[sep - str] = 0; } @@ -145,20 +146,20 @@ PHPDBG_API int phpdbg_is_class_method(const char *str, size_t len, char **class, return 1; } /* }}} */ -PHPDBG_API char *phpdbg_resolve_path(const char *path TSRMLS_DC) /* {{{ */ +PHPDBG_API char *phpdbg_resolve_path(const char *path) /* {{{ */ { char resolved_name[MAXPATHLEN]; - if (expand_filepath(path, resolved_name TSRMLS_CC) == NULL) { + if (expand_filepath(path, resolved_name) == NULL) { return NULL; } return estrdup(resolved_name); } /* }}} */ -PHPDBG_API const char *phpdbg_current_file(TSRMLS_D) /* {{{ */ +PHPDBG_API const char *phpdbg_current_file(void) /* {{{ */ { - const char *file = zend_get_executed_filename(TSRMLS_C); + const char *file = zend_get_executed_filename(); if (memcmp(file, "[no active file]", sizeof("[no active file]")) == 0) { return PHPDBG_G(exec); @@ -167,30 +168,32 @@ PHPDBG_API const char *phpdbg_current_file(TSRMLS_D) /* {{{ */ return file; } /* }}} */ -PHPDBG_API const zend_function *phpdbg_get_function(const char *fname, const char *cname TSRMLS_DC) /* {{{ */ +PHPDBG_API const zend_function *phpdbg_get_function(const char *fname, const char *cname) /* {{{ */ { zend_function *func = NULL; - size_t fname_len = strlen(fname); - char *lcname = zend_str_tolower_dup(fname, fname_len); + zend_string *lfname = zend_string_init(fname, strlen(fname), 0); + zend_string *tmp = zend_string_tolower(lfname); + zend_string_release(lfname); + lfname = tmp; if (cname) { - zend_class_entry **ce; - size_t cname_len = strlen(cname); - char *lc_cname = zend_str_tolower_dup(cname, cname_len); - int ret = zend_lookup_class(lc_cname, cname_len, &ce TSRMLS_CC); + zend_class_entry *ce; + zend_string *lcname = zend_string_init(cname, strlen(cname), 0); + tmp = zend_string_tolower(lcname); + zend_string_release(lcname); + lcname = tmp; + ce = zend_lookup_class(lcname); - efree(lc_cname); + zend_string_release(lcname); - if (ret == SUCCESS) { - zend_hash_find(&(*ce)->function_table, lcname, fname_len+1, - (void**)&func); + if (ce) { + func = zend_hash_find_ptr(&ce->function_table, lfname); } } else { - zend_hash_find(EG(function_table), lcname, fname_len+1, - (void**)&func); + func = zend_hash_find_ptr(EG(function_table), lfname); } - efree(lcname); + zend_string_release(lfname); return func; } /* }}} */ @@ -224,145 +227,46 @@ PHPDBG_API char *phpdbg_trim(const char *str, size_t len, size_t *new_len) /* {{ } /* }}} */ -PHPDBG_API int phpdbg_print(int type TSRMLS_DC, FILE *fp, const char *format, ...) /* {{{ */ -{ - int rc = 0; - char *buffer = NULL; - va_list args; - - if (format != NULL && strlen(format) > 0L) { - va_start(args, format); - vspprintf(&buffer, 0, format, args); - va_end(args); - } - - /* TODO(anyone) colours */ - - switch (type) { - case P_ERROR: - if (PHPDBG_G(flags) & PHPDBG_IS_COLOURED) { - rc = fprintf(fp, - "\033[%sm[%s]\033[0m\n", - PHPDBG_G(colors)[PHPDBG_COLOR_ERROR]->code, buffer); - } else { - rc = fprintf(fp, "[%s]\n", buffer); - } - break; - - case P_NOTICE: - if (PHPDBG_G(flags) & PHPDBG_IS_COLOURED) { - rc = fprintf(fp, - "\033[%sm[%s]\033[0m\n", - PHPDBG_G(colors)[PHPDBG_COLOR_NOTICE]->code, buffer); - } else { - rc = fprintf(fp, "[%s]\n", buffer); - } - break; - - case P_WRITELN: { - if (buffer) { - rc = fprintf(fp, "%s\n", buffer); - } else { - rc = fprintf(fp, "\n"); - } - } break; - - case P_WRITE: - if (buffer) { - rc = fprintf(fp, "%s", buffer); - } - break; - - /* no formatting on logging output */ - case P_LOG: - if (buffer) { - struct timeval tp; - if (gettimeofday(&tp, NULL) == SUCCESS) { - rc = fprintf(fp, "[%ld %.8F]: %s\n", tp.tv_sec, tp.tv_usec / 1000000.00, buffer); - } else { - rc = FAILURE; - } - } - break; - } - - if (buffer) { - efree(buffer); - } - - return rc; -} /* }}} */ - -PHPDBG_API int phpdbg_rlog(FILE *fp, const char *fmt, ...) { /* {{{ */ - int rc = 0; - - va_list args; - struct timeval tp; - - va_start(args, fmt); - if (gettimeofday(&tp, NULL) == SUCCESS) { - char friendly[100]; - char *format = NULL, *buffer = NULL; - const time_t tt = tp.tv_sec; - - strftime(friendly, 100, "%a %b %d %T.%%04d %Y", localtime(&tt)); - asprintf( - &buffer, friendly, tp.tv_usec/1000); - asprintf( - &format, "[%s]: %s\n", buffer, fmt); - rc = vfprintf( - fp, format, args); - - free(format); - free(buffer); - } - va_end(args); - - return rc; -} /* }}} */ - -PHPDBG_API const phpdbg_color_t *phpdbg_get_color(const char *name, size_t name_length TSRMLS_DC) /* {{{ */ +PHPDBG_API const phpdbg_color_t *phpdbg_get_color(const char *name, size_t name_length) /* {{{ */ { const phpdbg_color_t *color = colors; while (color && color->name) { if (name_length == color->name_length && memcmp(name, color->name, name_length) == SUCCESS) { - phpdbg_debug( - "phpdbg_get_color(%s, %lu): %s", name, name_length, color->code); + phpdbg_debug("phpdbg_get_color(%s, %lu): %s", name, name_length, color->code); return color; } ++color; } - phpdbg_debug( - "phpdbg_get_color(%s, %lu): failed", name, name_length); + phpdbg_debug("phpdbg_get_color(%s, %lu): failed", name, name_length); return NULL; } /* }}} */ -PHPDBG_API void phpdbg_set_color(int element, const phpdbg_color_t *color TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_set_color(int element, const phpdbg_color_t *color) /* {{{ */ { PHPDBG_G(colors)[element] = color; } /* }}} */ -PHPDBG_API void phpdbg_set_color_ex(int element, const char *name, size_t name_length TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_set_color_ex(int element, const char *name, size_t name_length) /* {{{ */ { - const phpdbg_color_t *color = phpdbg_get_color(name, name_length TSRMLS_CC); + const phpdbg_color_t *color = phpdbg_get_color(name, name_length); if (color) { - phpdbg_set_color(element, color TSRMLS_CC); + phpdbg_set_color(element, color); } else PHPDBG_G(colors)[element] = colors; } /* }}} */ -PHPDBG_API const phpdbg_color_t* phpdbg_get_colors(TSRMLS_D) /* {{{ */ +PHPDBG_API const phpdbg_color_t* phpdbg_get_colors(void) /* {{{ */ { return colors; } /* }}} */ -PHPDBG_API int phpdbg_get_element(const char *name, size_t len TSRMLS_DC) { +PHPDBG_API int phpdbg_get_element(const char *name, size_t len) { const phpdbg_element_t *element = elements; - + while (element && element->name) { if (len == element->name_length) { if (strncasecmp(name, element->name, len) == SUCCESS) { @@ -371,11 +275,11 @@ PHPDBG_API int phpdbg_get_element(const char *name, size_t len TSRMLS_DC) { } element++; } - + return PHPDBG_COLOR_INVALID; } -PHPDBG_API void phpdbg_set_prompt(const char *prompt TSRMLS_DC) /* {{{ */ +PHPDBG_API void phpdbg_set_prompt(const char *prompt) /* {{{ */ { /* free formatted prompt */ if (PHPDBG_G(prompt)[1]) { @@ -392,7 +296,7 @@ PHPDBG_API void phpdbg_set_prompt(const char *prompt TSRMLS_DC) /* {{{ */ PHPDBG_G(prompt)[0] = strdup(prompt); } /* }}} */ -PHPDBG_API const char *phpdbg_get_prompt(TSRMLS_D) /* {{{ */ +PHPDBG_API const char *phpdbg_get_prompt(void) /* {{{ */ { /* find cached prompt */ if (PHPDBG_G(prompt)[1]) { @@ -403,48 +307,41 @@ PHPDBG_API const char *phpdbg_get_prompt(TSRMLS_D) /* {{{ */ #ifndef HAVE_LIBEDIT /* TODO: libedit doesn't seems to support coloured prompt */ if ((PHPDBG_G(flags) & PHPDBG_IS_COLOURED)) { - asprintf( - &PHPDBG_G(prompt)[1], "\033[%sm%s\033[0m ", + ZEND_IGNORE_VALUE(asprintf(&PHPDBG_G(prompt)[1], "\033[%sm%s\033[0m ", PHPDBG_G(colors)[PHPDBG_COLOR_PROMPT]->code, - PHPDBG_G(prompt)[0]); + PHPDBG_G(prompt)[0])); } else #endif { - asprintf( - &PHPDBG_G(prompt)[1], "%s ", - PHPDBG_G(prompt)[0]); + ZEND_IGNORE_VALUE(asprintf(&PHPDBG_G(prompt)[1], "%s ", PHPDBG_G(prompt)[0])); } return PHPDBG_G(prompt)[1]; } /* }}} */ -int phpdbg_rebuild_symtable(TSRMLS_D) { - if (!EG(active_op_array)) { - phpdbg_error("No active op array!"); +int phpdbg_rebuild_symtable(void) { + if (!EG(current_execute_data) || !EG(current_execute_data)->func) { + phpdbg_error("inactive", "type=\"op_array\"", "No active op array!"); return FAILURE; } - if (!EG(active_symbol_table)) { - zend_rebuild_symbol_table(TSRMLS_C); - - if (!EG(active_symbol_table)) { - phpdbg_error("No active symbol table!"); - return FAILURE; - } + if (!zend_rebuild_symbol_table()) { + phpdbg_error("inactive", "type=\"symbol_table\"", "No active symbol table!"); + return FAILURE; } return SUCCESS; } -PHPDBG_API int phpdbg_get_terminal_width(TSRMLS_D) /* {{{ */ +PHPDBG_API int phpdbg_get_terminal_width(void) /* {{{ */ { - int columns; + int columns; #ifdef _WIN32 CONSOLE_SCREEN_BUFFER_INFO csbi; GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); columns = csbi.srWindow.Right - csbi.srWindow.Left + 1; -#elif defined(HAVE_SYS_IOCTL_H) && defined (TIOCGWINSZ) +#elif defined(HAVE_SYS_IOCTL_H) && defined(TIOCGWINSZ) struct winsize w; columns = ioctl(fileno(stdout), TIOCGWINSZ, &w) == 0 ? w.ws_col : 80; @@ -453,3 +350,497 @@ PHPDBG_API int phpdbg_get_terminal_width(TSRMLS_D) /* {{{ */ #endif return columns; } /* }}} */ + +PHPDBG_API int phpdbg_get_terminal_height(void) /* {{{ */ +{ + int lines; +#ifdef _WIN32 + CONSOLE_SCREEN_BUFFER_INFO csbi; + + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); + lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; +#elif defined(HAVE_SYS_IOCTL_H) && defined(TIOCGWINSZ) + struct winsize w; + + lines = ioctl(fileno(stdout), TIOCGWINSZ, &w) == 0 ? w.ws_row : 40; +#else + lines = 40; +#endif + return lines; +} /* }}} */ + +PHPDBG_API void phpdbg_set_async_io(int fd) { +#if !defined(_WIN32) && defined(FASYNC) + int flags; + fcntl(STDIN_FILENO, F_SETOWN, getpid()); + flags = fcntl(STDIN_FILENO, F_GETFL); + fcntl(STDIN_FILENO, F_SETFL, flags | FASYNC); +#endif +} + +int phpdbg_safe_class_lookup(const char *name, int name_length, zend_class_entry **ce) { + if (PHPDBG_G(flags) & PHPDBG_IN_SIGNAL_HANDLER) { + char *lc_name, *lc_free; + int lc_length; + + if (name == NULL || !name_length) { + return FAILURE; + } + + lc_free = lc_name = emalloc(name_length + 1); + zend_str_tolower_copy(lc_name, name, name_length); + lc_length = name_length + 1; + + if (lc_name[0] == '\\') { + lc_name += 1; + lc_length -= 1; + } + + phpdbg_try_access { + *ce = zend_hash_str_find_ptr(EG(class_table), lc_name, lc_length); + } phpdbg_catch_access { + phpdbg_error("signalsegv", "class=\"%.*s\"", "Could not fetch class %.*s, invalid data source", name_length, name); + } phpdbg_end_try_access(); + + efree(lc_free); + } else { + zend_string *str_name = zend_string_init(name, name_length, 0); + *ce = zend_lookup_class(str_name); + efree(str_name); + } + + return *ce ? SUCCESS : FAILURE; +} + +char *phpdbg_get_property_key(char *key) { + if (*key != 0) { + return key; + } + return strchr(key + 1, 0) + 1; +} + +static int phpdbg_parse_variable_arg_wrapper(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval *zv, phpdbg_parse_var_func callback) { + return callback(name, len, keyname, keylen, parent, zv); +} + +PHPDBG_API int phpdbg_parse_variable(char *input, size_t len, HashTable *parent, size_t i, phpdbg_parse_var_func callback, zend_bool silent) { + return phpdbg_parse_variable_with_arg(input, len, parent, i, (phpdbg_parse_var_with_arg_func) phpdbg_parse_variable_arg_wrapper, NULL, silent, callback); +} + +PHPDBG_API int phpdbg_parse_variable_with_arg(char *input, size_t len, HashTable *parent, size_t i, phpdbg_parse_var_with_arg_func callback, phpdbg_parse_var_with_arg_func step_cb, zend_bool silent, void *arg) { + int ret = FAILURE; + zend_bool new_index = 1; + char *last_index; + size_t index_len = 0; + zval *zv; + + if (len < 2 || *input != '$') { + goto error; + } + + while (i++ < len) { + if (i == len) { + new_index = 1; + } else { + switch (input[i]) { + case '[': + new_index = 1; + break; + case ']': + break; + case '>': + if (last_index[index_len - 1] == '-') { + new_index = 1; + index_len--; + } + break; + + default: + if (new_index) { + last_index = input + i; + new_index = 0; + } + if (input[i - 1] == ']') { + goto error; + } + index_len++; + } + } + + if (new_index && index_len == 0) { + zend_ulong numkey; + zend_string *strkey; + ZEND_HASH_FOREACH_KEY_PTR(parent, numkey, strkey, zv) { + while (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + } + + if (i == len || (i == len - 1 && input[len - 1] == ']')) { + char *key, *propkey; + size_t namelen, keylen; + char *name; + char *keyname = estrndup(last_index, index_len); + if (strkey) { + key = ZSTR_VAL(strkey); + keylen = ZSTR_LEN(strkey); + } else { + keylen = spprintf(&key, 0, ZEND_ULONG_FMT, numkey); + } + propkey = phpdbg_get_property_key(key); + name = emalloc(i + keylen + 2); + namelen = sprintf(name, "%.*s%.*s%s", (int) i, input, (int) (keylen - (propkey - key)), propkey, input[len - 1] == ']'?"]":""); + if (!strkey) { + efree(key); + } + + ret = callback(name, namelen, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE; + } else retry_ref: if (Z_TYPE_P(zv) == IS_OBJECT) { + if (step_cb) { + char *name = estrndup(input, i); + char *keyname = estrndup(last_index, index_len); + + ret = step_cb(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE; + } + + phpdbg_parse_variable_with_arg(input, len, Z_OBJPROP_P(zv), i, callback, step_cb, silent, arg); + } else if (Z_TYPE_P(zv) == IS_ARRAY) { + if (step_cb) { + char *name = estrndup(input, i); + char *keyname = estrndup(last_index, index_len); + + ret = step_cb(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE; + } + + phpdbg_parse_variable_with_arg(input, len, Z_ARRVAL_P(zv), i, callback, step_cb, silent, arg); + } else if (Z_ISREF_P(zv)) { + if (step_cb) { + char *name = estrndup(input, i); + char *keyname = estrndup(last_index, index_len); + + ret = step_cb(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE; + } + + ZVAL_DEREF(zv); + goto retry_ref; + } else { + /* Ignore silently */ + } + } ZEND_HASH_FOREACH_END(); + return ret; + } else if (new_index) { + char last_chr = last_index[index_len]; + last_index[index_len] = 0; + if (!(zv = zend_symtable_str_find(parent, last_index, index_len))) { + if (!silent) { + phpdbg_error("variable", "type=\"undefined\" variable=\"%.*s\"", "%.*s is undefined", (int) i, input); + } + return FAILURE; + } + while (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + } + + last_index[index_len] = last_chr; + if (i == len) { + char *name = estrndup(input, i); + char *keyname = estrndup(last_index, index_len); + + ret = callback(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE; + } else retry_ref_end: if (Z_TYPE_P(zv) == IS_OBJECT) { + if (step_cb) { + char *name = estrndup(input, i); + char *keyname = estrndup(last_index, index_len); + + ret = step_cb(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE; + } + + parent = Z_OBJPROP_P(zv); + } else if (Z_TYPE_P(zv) == IS_ARRAY) { + if (step_cb) { + char *name = estrndup(input, i); + char *keyname = estrndup(last_index, index_len); + + ret = step_cb(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE; + } + + parent = Z_ARRVAL_P(zv); + } else if (Z_ISREF_P(zv)) { + if (step_cb) { + char *name = estrndup(input, i); + char *keyname = estrndup(last_index, index_len); + + ret = step_cb(name, i, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE; + } + + ZVAL_DEREF(zv); + goto retry_ref_end; + } else { + phpdbg_error("variable", "type=\"notiterable\" variable=\"%.*s\"", "%.*s is nor an array nor an object", (int) (input[i] == '>' ? i - 1 : i), input); + return FAILURE; + } + index_len = 0; + } + } + + return ret; + error: + phpdbg_error("variable", "type=\"invalidinput\"", "Malformed input"); + return FAILURE; +} + +int phpdbg_is_auto_global(char *name, int len) { + return zend_is_auto_global_str(name, len); +} + +static int phpdbg_xml_array_element_dump(zval *zv, zend_string *key, zend_ulong num) { + phpdbg_xml("<element"); + + phpdbg_try_access { + if (key) { /* string key */ + phpdbg_xml(" name=\"%.*s\"", (int) ZSTR_LEN(key), ZSTR_VAL(key)); + } else { /* numeric key */ + phpdbg_xml(" name=\"%ld\"", num); + } + } phpdbg_catch_access { + phpdbg_xml(" severity=\"error\" ></element>"); + return 0; + } phpdbg_end_try_access(); + + phpdbg_xml(">"); + + phpdbg_xml_var_dump(zv); + + phpdbg_xml("</element>"); + + return 0; +} + +static int phpdbg_xml_object_property_dump(zval *zv, zend_string *key, zend_ulong num) { + phpdbg_xml("<property"); + + phpdbg_try_access { + if (key) { /* string key */ + const char *prop_name, *class_name; + int unmangle = zend_unmangle_property_name(key, &class_name, &prop_name); + + if (class_name && unmangle == SUCCESS) { + phpdbg_xml(" name=\"%s\"", prop_name); + if (class_name[0] == '*') { + phpdbg_xml(" protection=\"protected\""); + } else { + phpdbg_xml(" class=\"%s\" protection=\"private\"", class_name); + } + } else { + phpdbg_xml(" name=\"%.*s\" protection=\"public\"", (int) ZSTR_LEN(key), ZSTR_VAL(key)); + } + } else { /* numeric key */ + phpdbg_xml(" name=\"%ld\" protection=\"public\"", num); + } + } phpdbg_catch_access { + phpdbg_xml(" severity=\"error\" ></property>"); + return 0; + } phpdbg_end_try_access(); + + phpdbg_xml(">"); + + phpdbg_xml_var_dump(zv); + + phpdbg_xml("</property>"); + + return 0; +} + +#define COMMON (is_ref ? "&" : "") + +PHPDBG_API void phpdbg_xml_var_dump(zval *zv) { + HashTable *myht; + zend_string *class_name, *key; + zend_ulong num; + zval *val; + int (*element_dump_func)(zval *zv, zend_string *key, zend_ulong num); + zend_bool is_ref = 0; + + int is_temp; + + phpdbg_try_access { + is_ref = Z_ISREF_P(zv) && GC_REFCOUNT(Z_COUNTED_P(zv)) > 1; + ZVAL_DEREF(zv); + + switch (Z_TYPE_P(zv)) { + case IS_TRUE: + phpdbg_xml("<bool refstatus=\"%s\" value=\"true\" />", COMMON); + break; + case IS_FALSE: + phpdbg_xml("<bool refstatus=\"%s\" value=\"false\" />", COMMON); + break; + case IS_NULL: + phpdbg_xml("<null refstatus=\"%s\" />", COMMON); + break; + case IS_LONG: + phpdbg_xml("<int refstatus=\"%s\" value=\"" ZEND_LONG_FMT "\" />", COMMON, Z_LVAL_P(zv)); + break; + case IS_DOUBLE: + phpdbg_xml("<float refstatus=\"%s\" value=\"%.*G\" />", COMMON, (int) EG(precision), Z_DVAL_P(zv)); + break; + case IS_STRING: + phpdbg_xml("<string refstatus=\"%s\" length=\"%zd\" value=\"%.*s\" />", COMMON, Z_STRLEN_P(zv), (int) Z_STRLEN_P(zv), Z_STRVAL_P(zv)); + break; + case IS_ARRAY: + myht = Z_ARRVAL_P(zv); + if (ZEND_HASH_APPLY_PROTECTION(myht) && ++myht->u.v.nApplyCount > 1) { + phpdbg_xml("<recursion />"); + --myht->u.v.nApplyCount; + break; + } + phpdbg_xml("<array refstatus=\"%s\" num=\"%d\">", COMMON, zend_hash_num_elements(myht)); + element_dump_func = phpdbg_xml_array_element_dump; + is_temp = 0; + goto head_done; + case IS_OBJECT: + myht = Z_OBJDEBUG_P(zv, is_temp); + if (myht && ++myht->u.v.nApplyCount > 1) { + phpdbg_xml("<recursion />"); + --myht->u.v.nApplyCount; + break; + } + + class_name = Z_OBJ_HANDLER_P(zv, get_class_name)(Z_OBJ_P(zv)); + phpdbg_xml("<object refstatus=\"%s\" class=\"%.*s\" id=\"%d\" num=\"%d\">", COMMON, (int) ZSTR_LEN(class_name), ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(zv), myht ? zend_hash_num_elements(myht) : 0); + zend_string_release(class_name); + + element_dump_func = phpdbg_xml_object_property_dump; +head_done: + if (myht) { + ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) { + element_dump_func(val, key, num); + } ZEND_HASH_FOREACH_END(); + zend_hash_apply_with_arguments(myht, (apply_func_args_t) element_dump_func, 0); + --myht->u.v.nApplyCount; + if (is_temp) { + zend_hash_destroy(myht); + efree(myht); + } + } + if (Z_TYPE_P(zv) == IS_ARRAY) { + phpdbg_xml("</array>"); + } else { + phpdbg_xml("</object>"); + } + break; + case IS_RESOURCE: { + const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(zv)); + phpdbg_xml("<resource refstatus=\"%s\" id=\"%pd\" type=\"%s\" />", COMMON, Z_RES_P(zv)->handle, type_name ? type_name : "unknown"); + break; + } + default: + break; + } + } phpdbg_end_try_access(); +} + +PHPDBG_API zend_bool phpdbg_check_caught_ex(zend_execute_data *execute_data, zend_object *exception) { + const zend_op *op; + zend_op *cur; + uint32_t op_num, i; + zend_op_array *op_array = &execute_data->func->op_array; + + if (execute_data->opline >= EG(exception_op) && execute_data->opline < EG(exception_op) + 3) { + op = EG(opline_before_exception); + } else { + op = execute_data->opline; + } + + op_num = op - op_array->opcodes; + + for (i = 0; i < op_array->last_try_catch && op_array->try_catch_array[i].try_op <= op_num; i++) { + uint32_t catch = op_array->try_catch_array[i].catch_op, finally = op_array->try_catch_array[i].finally_op; + if (op_num <= catch || op_num <= finally) { + if (finally) { + return 1; + } + + do { + zend_class_entry *ce; + cur = &op_array->opcodes[catch]; + + if (!(ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(cur->op1))))) { + ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(cur->op1)), EX_CONSTANT(cur->op1) + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD); + CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(cur->op1)), ce); + } + + if (ce == exception->ce || (ce && instanceof_function(exception->ce, ce))) { + return 1; + } + + catch = cur->extended_value; + } while (!cur->result.num); + + return 0; + } + } + + return op->opcode == ZEND_CATCH; +} + +char *phpdbg_short_zval_print(zval *zv, int maxlen) /* {{{ */ +{ + char *decode = NULL; + + switch (Z_TYPE_P(zv)) { + case IS_UNDEF: + decode = estrdup(""); + break; + case IS_NULL: + decode = estrdup("null"); + break; + case IS_FALSE: + decode = estrdup("false"); + break; + case IS_TRUE: + decode = estrdup("true"); + break; + case IS_LONG: + spprintf(&decode, 0, ZEND_LONG_FMT, Z_LVAL_P(zv)); + break; + case IS_DOUBLE: + spprintf(&decode, 0, "%.*G", 14, Z_DVAL_P(zv)); + break; + case IS_STRING: { + int i; + zend_string *str = php_addcslashes(Z_STR_P(zv), 0, "\\\"", 2); + for (i = 0; i < ZSTR_LEN(str); i++) { + if (ZSTR_VAL(str)[i] < 32) { + ZSTR_VAL(str)[i] = ' '; + } + } + spprintf(&decode, 0, "\"%.*s\"%c", + ZSTR_LEN(str) <= maxlen - 2 ? (int) ZSTR_LEN(str) : (maxlen - 3), + ZSTR_VAL(str), ZSTR_LEN(str) <= maxlen - 2 ? 0 : '+'); + zend_string_release(str); + } break; + case IS_RESOURCE: + spprintf(&decode, 0, "Rsrc #%d", Z_RES_HANDLE_P(zv)); + break; + case IS_ARRAY: + spprintf(&decode, 0, "array(%d)", zend_hash_num_elements(Z_ARR_P(zv))); + break; + case IS_OBJECT: { + zend_string *str = Z_OBJCE_P(zv)->name; + spprintf(&decode, 0, "%.*s%c", + ZSTR_LEN(str) <= maxlen ? (int) ZSTR_LEN(str) : maxlen - 1, + ZSTR_VAL(str), ZSTR_LEN(str) <= maxlen ? 0 : '+'); + break; + } + case IS_CONSTANT: + decode = estrdup("<constant>"); + break; + case IS_CONSTANT_AST: + decode = estrdup("<ast>"); + break; + default: + spprintf(&decode, 0, "unknown type: %d", Z_TYPE_P(zv)); + break; + } + + return decode; +} /* }}} */ diff --git a/sapi/phpdbg/phpdbg_utils.h b/sapi/phpdbg/phpdbg_utils.h index 14116f9a5b..4ba756139b 100644 --- a/sapi/phpdbg/phpdbg_utils.h +++ b/sapi/phpdbg/phpdbg_utils.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -28,56 +28,10 @@ PHPDBG_API int phpdbg_is_numeric(const char*); PHPDBG_API int phpdbg_is_empty(const char*); PHPDBG_API int phpdbg_is_addr(const char*); PHPDBG_API int phpdbg_is_class_method(const char*, size_t, char**, char**); -PHPDBG_API const char *phpdbg_current_file(TSRMLS_D); -PHPDBG_API char *phpdbg_resolve_path(const char* TSRMLS_DC); +PHPDBG_API const char *phpdbg_current_file(void); +PHPDBG_API char *phpdbg_resolve_path(const char*); PHPDBG_API char *phpdbg_trim(const char*, size_t, size_t*); -PHPDBG_API const zend_function *phpdbg_get_function(const char*, const char* TSRMLS_DC); - -/** - * Error/notice/formatting helpers - */ -enum { - P_ERROR = 1, - P_NOTICE, - P_WRITELN, - P_WRITE, - P_LOG -}; - -#ifdef ZTS -PHPDBG_API int phpdbg_print(int TSRMLS_DC, FILE*, const char*, ...) PHP_ATTRIBUTE_FORMAT(printf, 4, 5); -#else -PHPDBG_API int phpdbg_print(int TSRMLS_DC, FILE*, const char*, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4); -#endif - -PHPDBG_API int phpdbg_rlog(FILE *stream, const char *fmt, ...); - -#define phpdbg_error(fmt, ...) phpdbg_print(P_ERROR TSRMLS_CC, PHPDBG_G(io)[PHPDBG_STDOUT], fmt, ##__VA_ARGS__) -#define phpdbg_notice(fmt, ...) phpdbg_print(P_NOTICE TSRMLS_CC, PHPDBG_G(io)[PHPDBG_STDOUT], fmt, ##__VA_ARGS__) -#define phpdbg_writeln(fmt, ...) phpdbg_print(P_WRITELN TSRMLS_CC, PHPDBG_G(io)[PHPDBG_STDOUT], fmt, ##__VA_ARGS__) -#define phpdbg_write(fmt, ...) phpdbg_print(P_WRITE TSRMLS_CC, PHPDBG_G(io)[PHPDBG_STDOUT], fmt, ##__VA_ARGS__) -#define phpdbg_log(fmt, ...) phpdbg_print(P_LOG TSRMLS_CC, PHPDBG_G(io)[PHPDBG_STDOUT], fmt, ##__VA_ARGS__) - -#define phpdbg_error_ex(out, fmt, ...) phpdbg_print(P_ERROR TSRMLS_CC, out, fmt, ##__VA_ARGS__) -#define phpdbg_notice_ex(out, fmt, ...) phpdbg_print(P_NOTICE TSRMLS_CC, out, fmt, ##__VA_ARGS__) -#define phpdbg_writeln_ex(out, fmt, ...) phpdbg_print(P_WRITELN TSRMLS_CC, out, fmt, ##__VA_ARGS__) -#define phpdbg_write_ex(out, fmt, ...) phpdbg_print(P_WRITE TSRMLS_CC, out, fmt, ##__VA_ARGS__) -#define phpdbg_log_ex(out, fmt, ...) phpdbg_print(P_LOG TSRMLS_CC, out, fmt, ##__VA_ARGS__) - -#if PHPDBG_DEBUG -# define phpdbg_debug(fmt, ...) phpdbg_print(P_LOG TSRMLS_CC, PHPDBG_G(io)[PHPDBG_STDERR], fmt, ##__VA_ARGS__) -#else -# define phpdbg_debug(fmt, ...) -#endif - -/* {{{ For writing blank lines */ -#define EMPTY NULL /* }}} */ - -/* {{{ For prompt lines */ -#define PROMPT "phpdbg>" /* }}} */ - -/* {{{ For separation */ -#define SEPARATE "------------------------------------------------" /* }}} */ +PHPDBG_API const zend_function *phpdbg_get_function(const char*, const char*); /* {{{ Color Management */ #define PHPDBG_COLOR_LEN 12 @@ -109,39 +63,73 @@ typedef struct _phpdbg_element_t { int id; } phpdbg_element_t; -PHPDBG_API const phpdbg_color_t *phpdbg_get_color(const char *name, size_t name_length TSRMLS_DC); -PHPDBG_API void phpdbg_set_color(int element, const phpdbg_color_t *color TSRMLS_DC); -PHPDBG_API void phpdbg_set_color_ex(int element, const char *name, size_t name_length TSRMLS_DC); -PHPDBG_API const phpdbg_color_t* phpdbg_get_colors(TSRMLS_D); -PHPDBG_API int phpdbg_get_element(const char *name, size_t len TSRMLS_DC); /* }}} */ +PHPDBG_API const phpdbg_color_t *phpdbg_get_color(const char *name, size_t name_length); +PHPDBG_API void phpdbg_set_color(int element, const phpdbg_color_t *color); +PHPDBG_API void phpdbg_set_color_ex(int element, const char *name, size_t name_length); +PHPDBG_API const phpdbg_color_t *phpdbg_get_colors(void); +PHPDBG_API int phpdbg_get_element(const char *name, size_t len); /* }}} */ /* {{{ Prompt Management */ -PHPDBG_API void phpdbg_set_prompt(const char* TSRMLS_DC); -PHPDBG_API const char *phpdbg_get_prompt(TSRMLS_D); /* }}} */ - -/* {{{ Console Width */ -PHPDBG_API int phpdbg_get_terminal_width(TSRMLS_D); /* }}} */ - -int phpdbg_rebuild_symtable(TSRMLS_D); - -#if PHP_VERSION_ID < 50500 -/* copy from zend_hash.c PHP 5.5 for 5.4 compatibility */ -static void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos) { - Bucket *p; - - p = pos ? (*pos) : ht->pInternalPointer; - - if (!p) { - Z_TYPE_P(key) = IS_NULL; - } else if (p->nKeyLength) { - Z_TYPE_P(key) = IS_STRING; - Z_STRVAL_P(key) = IS_INTERNED(p->arKey) ? (char*)p->arKey : estrndup(p->arKey, p->nKeyLength - 1); - Z_STRLEN_P(key) = p->nKeyLength - 1; - } else { - Z_TYPE_P(key) = IS_LONG; - Z_LVAL_P(key) = p->h; +PHPDBG_API void phpdbg_set_prompt(const char*); +PHPDBG_API const char *phpdbg_get_prompt(void); /* }}} */ + +/* {{{ Console size */ +PHPDBG_API int phpdbg_get_terminal_width(void); +PHPDBG_API int phpdbg_get_terminal_height(void); /* }}} */ + +PHPDBG_API void phpdbg_set_async_io(int fd); + +int phpdbg_rebuild_symtable(void); + +int phpdbg_safe_class_lookup(const char *name, int name_length, zend_class_entry **ce); + +char *phpdbg_get_property_key(char *key); + +typedef int (*phpdbg_parse_var_func)(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval *zv); +typedef int (*phpdbg_parse_var_with_arg_func)(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval *zv, void *arg); + +PHPDBG_API int phpdbg_parse_variable(char *input, size_t len, HashTable *parent, size_t i, phpdbg_parse_var_func callback, zend_bool silent); +PHPDBG_API int phpdbg_parse_variable_with_arg(char *input, size_t len, HashTable *parent, size_t i, phpdbg_parse_var_with_arg_func callback, phpdbg_parse_var_with_arg_func step_cb, zend_bool silent, void *arg); + +int phpdbg_is_auto_global(char *name, int len); + +PHPDBG_API void phpdbg_xml_var_dump(zval *zv); + +char *phpdbg_short_zval_print(zval *zv, int maxlen); + +PHPDBG_API zend_bool phpdbg_check_caught_ex(zend_execute_data *ex, zend_object *exception); + +static zend_always_inline zend_execute_data *phpdbg_user_execute_data(zend_execute_data *ex) { + while (!ex->func || !ZEND_USER_CODE(ex->func->common.type)) { + ex = ex->prev_execute_data; + ZEND_ASSERT(ex); } + return ex; } + +#ifdef ZTS +#define PHPDBG_OUTPUT_BACKUP_DEFINES() \ + zend_output_globals *output_globals_ptr; \ + zend_output_globals original_output_globals; \ + output_globals_ptr = (zend_output_globals *) (*((void ***) tsrm_get_ls_cache()))[TSRM_UNSHUFFLE_RSRC_ID(output_globals_id)]; +#else +#define PHPDBG_OUTPUT_BACKUP_DEFINES() \ + zend_output_globals *output_globals_ptr; \ + zend_output_globals original_output_globals; \ + output_globals_ptr = &output_globals; #endif +#define PHPDBG_OUTPUT_BACKUP_SWAP() \ + original_output_globals = *output_globals_ptr; \ + memset(output_globals_ptr, 0, sizeof(zend_output_globals)); \ + php_output_activate(); + +#define PHPDBG_OUTPUT_BACKUP() \ + PHPDBG_OUTPUT_BACKUP_DEFINES() \ + PHPDBG_OUTPUT_BACKUP_SWAP() + +#define PHPDBG_OUTPUT_BACKUP_RESTORE() \ + php_output_deactivate(); \ + *output_globals_ptr = original_output_globals; + #endif /* PHPDBG_UTILS_H */ diff --git a/sapi/phpdbg/phpdbg_wait.c b/sapi/phpdbg/phpdbg_wait.c new file mode 100644 index 0000000000..c7dcd4fbd4 --- /dev/null +++ b/sapi/phpdbg/phpdbg_wait.c @@ -0,0 +1,393 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2016 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: Bob Weinand <bwoebi@php.net> | + +----------------------------------------------------------------------+ +*/ + +#include "phpdbg_wait.h" +#include "phpdbg_prompt.h" +#include "ext/standard/php_var.h" +#include "ext/standard/basic_functions.h" + +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) + +static void phpdbg_rebuild_http_globals_array(int type, const char *name) { + zval *zvp; + if (Z_TYPE(PG(http_globals)[type]) != IS_UNDEF) { + zval_dtor(&PG(http_globals)[type]); + } + if ((zvp = zend_hash_str_find(&EG(symbol_table), name, strlen(name)))) { + Z_ADDREF_P(zvp); + PG(http_globals)[type] = *zvp; + } +} + + +static int phpdbg_dearm_autoglobals(zend_auto_global *auto_global) { + if (ZSTR_LEN(auto_global->name) != sizeof("GLOBALS") - 1 || memcmp(ZSTR_VAL(auto_global->name), "GLOBALS", sizeof("GLOBALS") - 1)) { + auto_global->armed = 0; + } + + return ZEND_HASH_APPLY_KEEP; +} + +typedef struct { + HashTable *ht[2]; + HashPosition pos[2]; +} phpdbg_intersect_ptr; + +static int phpdbg_array_data_compare(const void *a, const void *b) { + Bucket *f, *s; + int result; + zval *first, *second; + + f = *((Bucket **) a); + s = *((Bucket **) b); + + first = &f->val; + second = &s->val; + + result = string_compare_function(first, second); + + if (result < 0) { + return -1; + } else if (result > 0) { + return 1; + } + + return 0; +} + +static void phpdbg_array_intersect_init(phpdbg_intersect_ptr *info, HashTable *ht1, HashTable *ht2) { + info->ht[0] = ht1; + info->ht[1] = ht2; + + zend_hash_sort(info->ht[0], (compare_func_t) phpdbg_array_data_compare, 0); + zend_hash_sort(info->ht[1], (compare_func_t) phpdbg_array_data_compare, 0); + + zend_hash_internal_pointer_reset_ex(info->ht[0], &info->pos[0]); + zend_hash_internal_pointer_reset_ex(info->ht[1], &info->pos[1]); +} + +/* -1 => first array, 0 => both arrays equal, 1 => second array */ +static int phpdbg_array_intersect(phpdbg_intersect_ptr *info, zval **ptr) { + int ret; + zval *zvp[2]; + int invalid = !info->ht[0] + !info->ht[1]; + + if (invalid > 0) { + invalid = !info->ht[0]; + + if (!(*ptr = zend_hash_get_current_data_ex(info->ht[invalid], &info->pos[invalid]))) { + return 0; + } + + zend_hash_move_forward_ex(info->ht[invalid], &info->pos[invalid]); + + return invalid ? 1 : -1; + } + + if (!(zvp[0] = zend_hash_get_current_data_ex(info->ht[0], &info->pos[0]))) { + info->ht[0] = NULL; + return phpdbg_array_intersect(info, ptr); + } + if (!(zvp[1] = zend_hash_get_current_data_ex(info->ht[1], &info->pos[1]))) { + info->ht[1] = NULL; + return phpdbg_array_intersect(info, ptr); + } + + ret = zend_binary_zval_strcmp(zvp[0], zvp[1]); + + if (ret <= 0) { + *ptr = zvp[0]; + zend_hash_move_forward_ex(info->ht[0], &info->pos[0]); + } + if (ret >= 0) { + *ptr = zvp[1]; + zend_hash_move_forward_ex(info->ht[1], &info->pos[1]); + } + + return ret; +} + +void phpdbg_webdata_decompress(char *msg, int len) { + zval *free_zv = NULL; + zval zv, *zvp; + HashTable *ht; + php_unserialize_data_t var_hash; + + PHP_VAR_UNSERIALIZE_INIT(var_hash); + if (!php_var_unserialize(&zv, (const unsigned char **) &msg, (unsigned char *) msg + len, &var_hash)) { + PHP_VAR_UNSERIALIZE_DESTROY(var_hash); + phpdbg_error("wait", "type=\"invaliddata\" import=\"fail\"", "Malformed serialized was sent to this socket, arborting"); + return; + } + PHP_VAR_UNSERIALIZE_DESTROY(var_hash); + + ht = Z_ARRVAL(zv); + + /* Reapply symbol table */ + if ((zvp = zend_hash_str_find(ht, ZEND_STRL("GLOBALS"))) && Z_TYPE_P(zvp) == IS_ARRAY) { + { + zval *srv; + if ((srv = zend_hash_str_find(Z_ARRVAL_P(zvp), ZEND_STRL("_SERVER"))) && Z_TYPE_P(srv) == IS_ARRAY) { + zval *script; + if ((script = zend_hash_str_find(Z_ARRVAL_P(srv), ZEND_STRL("SCRIPT_FILENAME"))) && Z_TYPE_P(script) == IS_STRING) { + phpdbg_param_t param; + param.str = Z_STRVAL_P(script); + PHPDBG_COMMAND_HANDLER(exec)(¶m); + } + } + } + + PG(auto_globals_jit) = 0; + zend_hash_apply(CG(auto_globals), (apply_func_t) phpdbg_dearm_autoglobals); + + zend_hash_clean(&EG(symbol_table)); + EG(symbol_table) = *Z_ARR_P(zvp); + + /* Rebuild cookies, env vars etc. from GLOBALS (PG(http_globals)) */ + phpdbg_rebuild_http_globals_array(TRACK_VARS_POST, "_POST"); + phpdbg_rebuild_http_globals_array(TRACK_VARS_GET, "_GET"); + phpdbg_rebuild_http_globals_array(TRACK_VARS_COOKIE, "_COOKIE"); + phpdbg_rebuild_http_globals_array(TRACK_VARS_SERVER, "_SERVER"); + phpdbg_rebuild_http_globals_array(TRACK_VARS_ENV, "_ENV"); + phpdbg_rebuild_http_globals_array(TRACK_VARS_FILES, "_FILES"); + + Z_ADDREF_P(zvp); + free_zv = zvp; + } + + if ((zvp = zend_hash_str_find(ht, ZEND_STRL("input"))) && Z_TYPE_P(zvp) == IS_STRING) { + if (SG(request_info).request_body) { + php_stream_close(SG(request_info).request_body); + } + SG(request_info).request_body = php_stream_temp_create_ex(TEMP_STREAM_DEFAULT, SAPI_POST_BLOCK_SIZE, PG(upload_tmp_dir)); + php_stream_truncate_set_size(SG(request_info).request_body, 0); + php_stream_write(SG(request_info).request_body, Z_STRVAL_P(zvp), Z_STRLEN_P(zvp)); + } + + if ((zvp = zend_hash_str_find(ht, ZEND_STRL("cwd"))) && Z_TYPE_P(zvp) == IS_STRING) { + if (VCWD_CHDIR(Z_STRVAL_P(zvp)) == SUCCESS) { + if (BG(CurrentStatFile) && !IS_ABSOLUTE_PATH(BG(CurrentStatFile), strlen(BG(CurrentStatFile)))) { + efree(BG(CurrentStatFile)); + BG(CurrentStatFile) = NULL; + } + if (BG(CurrentLStatFile) && !IS_ABSOLUTE_PATH(BG(CurrentLStatFile), strlen(BG(CurrentLStatFile)))) { + efree(BG(CurrentLStatFile)); + BG(CurrentLStatFile) = NULL; + } + } + } + + if ((zvp = zend_hash_str_find(ht, ZEND_STRL("sapi_name"))) && (Z_TYPE_P(zvp) == IS_STRING || Z_TYPE_P(zvp) == IS_NULL)) { + if (PHPDBG_G(sapi_name_ptr)) { + free(PHPDBG_G(sapi_name_ptr)); + } + if (Z_TYPE_P(zvp) == IS_STRING) { + PHPDBG_G(sapi_name_ptr) = sapi_module.name = strdup(Z_STRVAL_P(zvp)); + } else { + PHPDBG_G(sapi_name_ptr) = sapi_module.name = NULL; + } + } + + if ((zvp = zend_hash_str_find(ht, ZEND_STRL("modules"))) && Z_TYPE_P(zvp) == IS_ARRAY) { + phpdbg_intersect_ptr pos; + zval *module; + zend_module_entry *mod; + HashTable zv_registry; + + /* intersect modules, unregister modules loaded "too much", announce not yet registered modules (phpdbg_notice) */ + + zend_hash_init(&zv_registry, zend_hash_num_elements(&module_registry), 0, ZVAL_PTR_DTOR, 0); + ZEND_HASH_FOREACH_PTR(&module_registry, mod) { + if (mod->name) { + zval value; + ZVAL_NEW_STR(&value, zend_string_init(mod->name, strlen(mod->name), 0)); + zend_hash_next_index_insert(&zv_registry, &value); + } + } ZEND_HASH_FOREACH_END(); + + phpdbg_array_intersect_init(&pos, &zv_registry, Z_ARRVAL_P(zvp)); + do { + int mode = phpdbg_array_intersect(&pos, &module); + if (mode < 0) { + // loaded module, but not needed + if (strcmp(PHPDBG_NAME, Z_STRVAL_P(module))) { + zend_hash_del(&module_registry, Z_STR_P(module)); + } + } else if (mode > 0) { + // not loaded module + if (!sapi_module.name || strcmp(sapi_module.name, Z_STRVAL_P(module))) { + phpdbg_notice("wait", "missingmodule=\"%.*s\"", "The module %.*s isn't present in " PHPDBG_NAME ", you still can load via dl /path/to/module/%.*s.so", (int) Z_STRLEN_P(module), Z_STRVAL_P(module), (int) Z_STRLEN_P(module), Z_STRVAL_P(module)); + } + } + } while (module); + + zend_hash_clean(&zv_registry); + } + + if ((zvp = zend_hash_str_find(ht, ZEND_STRL("extensions"))) && Z_TYPE_P(zvp) == IS_ARRAY) { + zend_extension *extension; + zend_llist_position pos; + zval *name = NULL; + zend_string *strkey; + + extension = (zend_extension *) zend_llist_get_first_ex(&zend_extensions, &pos); + while (extension) { + extension = (zend_extension *) zend_llist_get_next_ex(&zend_extensions, &pos); + + /* php_serach_array() body should be in some ZEND_API function... */ + ZEND_HASH_FOREACH_STR_KEY_PTR(Z_ARRVAL_P(zvp), strkey, name) { + if (Z_TYPE_P(name) == IS_STRING && !zend_binary_strcmp(extension->name, strlen(extension->name), Z_STRVAL_P(name), Z_STRLEN_P(name))) { + break; + } + name = NULL; + } ZEND_HASH_FOREACH_END(); + + if (name) { + /* sigh, breaking the encapsulation, there aren't any functions manipulating the llist at the place of the zend_llist_position */ + zend_llist_element *elm = pos; + if (elm->prev) { + elm->prev->next = elm->next; + } else { + zend_extensions.head = elm->next; + } + if (elm->next) { + elm->next->prev = elm->prev; + } else { + zend_extensions.tail = elm->prev; + } +#if ZEND_EXTENSIONS_SUPPORT + if (extension->shutdown) { + extension->shutdown(extension); + } +#endif + if (zend_extensions.dtor) { + zend_extensions.dtor(elm->data); + } + pefree(elm, zend_extensions.persistent); + zend_extensions.count--; + } else { + zend_hash_del(Z_ARRVAL_P(zvp), strkey); + } + } + + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(zvp), name) { + if (Z_TYPE_P(name) == IS_STRING) { + phpdbg_notice("wait", "missingextension=\"%.*s\"", "The Zend extension %.*s isn't present in " PHPDBG_NAME ", you still can load via dl /path/to/extension.so", (int) Z_STRLEN_P(name), Z_STRVAL_P(name)); + } + } ZEND_HASH_FOREACH_END(); + } + + zend_ini_deactivate(); + + if ((zvp = zend_hash_str_find(ht, ZEND_STRL("systemini"))) && Z_TYPE_P(zvp) == IS_ARRAY) { + zval *ini_entry; + zend_ini_entry *original_ini; + zend_string *key; + + ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zvp), key, ini_entry) { + if (key && Z_TYPE_P(ini_entry) == IS_STRING) { + if ((original_ini = zend_hash_find_ptr(EG(ini_directives), key))) { + if (!original_ini->on_modify || original_ini->on_modify(original_ini, Z_STR_P(ini_entry), original_ini->mh_arg1, original_ini->mh_arg2, original_ini->mh_arg3, ZEND_INI_STAGE_ACTIVATE) == SUCCESS) { + if (original_ini->modified && original_ini->orig_value != original_ini->value) { + efree(original_ini->value); + } + original_ini->value = Z_STR_P(ini_entry); + Z_ADDREF_P(ini_entry); /* don't free the string */ + } + } + } + } ZEND_HASH_FOREACH_END(); + } + + if ((zvp = zend_hash_str_find(ht, ZEND_STRL("userini"))) && Z_TYPE_P(zvp) == IS_ARRAY) { + zval *ini_entry; + zend_string *key; + + ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zvp), key, ini_entry) { + if (key && Z_TYPE_P(ini_entry) == IS_STRING) { + zend_alter_ini_entry_ex(key, Z_STR_P(ini_entry), ZEND_INI_PERDIR, ZEND_INI_STAGE_HTACCESS, 1); + } + } ZEND_HASH_FOREACH_END(); + } + + zval_dtor(&zv); + if (free_zv) { + /* separate freeing to not dtor the symtable too, just the container zval... */ + efree(free_zv); + } + + /* Reapply raw input */ + /* ??? */ +} + +PHPDBG_COMMAND(wait) /* {{{ */ +{ +#ifndef PHP_WIN32 + struct sockaddr_un local, remote; + int rlen, sr, sl; + unlink(PHPDBG_G(socket_path)); + if (PHPDBG_G(socket_server_fd) == -1) { + int len; + PHPDBG_G(socket_server_fd) = sl = socket(AF_UNIX, SOCK_STREAM, 0); + + local.sun_family = AF_UNIX; + strcpy(local.sun_path, PHPDBG_G(socket_path)); + len = strlen(local.sun_path) + sizeof(local.sun_family); + if (bind(sl, (struct sockaddr *)&local, len) == -1) { + phpdbg_error("wait", "type=\"nosocket\" import=\"fail\"", "Unable to connect to UNIX domain socket at %s defined by phpdbg.path ini setting", PHPDBG_G(socket_path)); + return FAILURE; + } + + chmod(PHPDBG_G(socket_path), 0666); + + listen(sl, 2); + } else { + sl = PHPDBG_G(socket_server_fd); + } + + rlen = sizeof(remote); + sr = accept(sl, (struct sockaddr *) &remote, (socklen_t *) &rlen); + + char msglen[5]; + int recvd = 4; + + do { + recvd -= recv(sr, &(msglen[4 - recvd]), recvd, 0); + } while (recvd > 0); + + recvd = *(size_t *) msglen; + char *data = emalloc(recvd); + + do { + recvd -= recv(sr, &(data[(*(int *) msglen) - recvd]), recvd, 0); + } while (recvd > 0); + + phpdbg_webdata_decompress(data, *(int *) msglen); + + if (PHPDBG_G(socket_fd) != -1) { + close(PHPDBG_G(socket_fd)); + } + PHPDBG_G(socket_fd) = sr; + + efree(data); + + phpdbg_notice("wait", "import=\"success\"", "Successfully imported request data, stopped before executing"); +#endif + + return SUCCESS; +} /* }}} */ diff --git a/sapi/webjames/php_webjames.h b/sapi/phpdbg/phpdbg_wait.h index 9dec1c0ab0..090b10ba61 100644 --- a/sapi/webjames/php_webjames.h +++ b/sapi/phpdbg/phpdbg_wait.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -12,17 +12,18 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: Alex Waugh <alex@alexwaugh.com> | + | Authors: Bob Weinand <bwoebi@php.net> | +----------------------------------------------------------------------+ */ -#ifndef PHP_WEBJAMES_H -#define PHP_WEBJAMES_H +#ifndef PHPDBG_WAIT_H +#define PHPDBG_WAIT_H -#include "webjames.h" +#include "zend.h" +#include "phpdbg.h" -void webjames_php_shutdown(void); -int webjames_php_init(void); -void webjames_php_request(struct connection *conn); +PHPDBG_COMMAND(wait); -#endif +void phpdbg_webdata_decompress(char *msg, int len); + +#endif /* PHPDBG_WAIT_H */ diff --git a/sapi/phpdbg/phpdbg_watch.c b/sapi/phpdbg/phpdbg_watch.c index eb1866058a..2c324aa5dc 100644 --- a/sapi/phpdbg/phpdbg_watch.c +++ b/sapi/phpdbg/phpdbg_watch.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -18,18 +18,83 @@ +----------------------------------------------------------------------+ */ +/* Some information for the reader... + * + * Watchpoints are either simple, recursive or implicit (PHPDBG_WATCH_* flags) + * Simple means that a particular watchpoint was explicitely defined + * Recursive watchpoints are created recursively and substitute simple watchpoints + * Implicit watchpoints are implicitely created on all ancestors of simple or recursive watchpoints + * Recursive and (simple or implicit) watchpoints are mutually exclusive + * + * PHPDBG_G(watchpoint_tree) contains all watchpoints identified by the watch target address + * PHPDBG_G(watch_HashTables) contains the dtors of the HashTables to call in our custom dtor (we substitute the dtor of HashTables containing watched zvals by our own dtor) + * PHPDBG_G(watchpoints) contains all watchpoints (except the ones managed by watch collision) + * PHPDBG_G(watch_collisions) is indexed by a zend_reference * pointer. It stores information about collisions (everything which contains a zend_reference * may be referenced by multiple watches) + * + * Creating a watchpoint: + * * Create watchpoints with PHPDBG_WATCH_IMPLICIT set on each zval and HashTable in hierarchy except the last zval or HashTable fetch. (if already existing PHPDBG_WATCH_IMPLICIT flag is added) + * * Create a PHPDBG_WATCH_SIMPLE watch for simple watches or a PHPDBG_WATCH_RECURSIVE watch for recursive watches + * * When the target zval is an IS_REFERENCE, create a watchpoint on it too + * * Each time a watchpoints parent is a zval and it is Z_REFCOUNTED(), put a watchpoint (WATCH_ON_REFCOUNTED) on it and add a watchpoint collision + * * When in recursive mode and encountering a not-refcounted PHPDBG_WATCH_SIMPLE, remove it and recreate it with a PHPDBG_WATCH_RECURSIVE (handled via watch collision) + * * Make attention to not add something twice or iterate over it twice + * + * Deleting a watchpoint: + * * Only allow deletion of recursive watches at their root and simple watches + * * Go to referenced variable. And remove watch collision on *parent* (if there is a parent) + * * If it is Z_REFCOUNTED(), remove that watch collision + * + * Watch collisions: + * * hold a counter for recursive, if it is incremented from 0 to 1, create recursive watchpoint + * * holds a HashTable for normal (not implicit) watchpoints ... it is used to get the fetch type of the HashTable (depending on whether it is empty or not) + * * holds a HashTable for implicit watchpoints ... (some sort of a refcounter, but ensure that there are no duplicates) + * * if normal and implicit watchpoints are empty, drop that watch collision and remove WATCH_ON_REFCOUNT alongside with watchpoint on an eventual reference + * + * Watching on addresses: + * * Address and size are transformed into memory page aligned address and size + * * mprotect() enables or disables them (depending on flags) - Windows has a transparent compatibility layer in phpdbg_win.c + * * segfault handler dumps watched memory segment and deactivates watchpoint + * * later watches inside these memory segments are compared against their current value and eventually reactivated (or deleted) + * + * A watched zval was removed: + * * trigger a memory copy (in segv handler) and an automatic deactivation + * * change a type flag _zval_struct.u1.v.type_flags (add PHPDBG_DESTRUCTED_ZVAL flag) in memory dump + * + * A watched zval was changed: + * * check if parent container has a different reference for referenced zval - recursively update all watches and drop them if necessary + * * if _zval_struct.u1.v.type_flags & PHPDBG_DESTRUCTED_ZVAL, add it to a list of zvals to be handled at the end (if location was not changed, remove it finally) + * * display changes if watch->flags & PHPDBG_WATCH_NORMAL (means: not implicit) + * * handle case where Z_RECOUNTED() or Z_PTR() changed (remove/add collison(s)) + * * if necessary ... on zvals: handle references, if recursive also objects and arrays ... on arrays: if recursive, add new elements + * * drop destructed zval watchpoints which were not updated + */ + #include "zend.h" #include "phpdbg.h" #include "phpdbg_btree.h" #include "phpdbg_watch.h" #include "phpdbg_utils.h" +#include "phpdbg_prompt.h" #ifndef _WIN32 # include <unistd.h> # include <sys/mman.h> #endif -ZEND_EXTERN_MODULE_GLOBALS(phpdbg); +ZEND_EXTERN_MODULE_GLOBALS(phpdbg) + +const phpdbg_command_t phpdbg_watch_commands[] = { + PHPDBG_COMMAND_D_EX(array, "create watchpoint on an array", 'a', watch_array, &phpdbg_prompt_commands[24], "s", 0), + PHPDBG_COMMAND_D_EX(delete, "delete watchpoint", 'd', watch_delete, &phpdbg_prompt_commands[24], "s", 0), + PHPDBG_COMMAND_D_EX(recursive, "create recursive watchpoints", 'r', watch_recursive, &phpdbg_prompt_commands[24], "s", 0), + PHPDBG_END_COMMAND +}; + +//#define HT_FROM_WATCH(watch) (watch->type == WATCH_ON_OBJECT ? watch->addr.obj->handlers->get_properties(watch->parent_container.zv) : watch->type == WATCH_ON_ARRAY ? &watch->addr.arr->ht : NULL) +#define HT_FROM_ZVP(zvp) (Z_TYPE_P(zvp) == IS_OBJECT ? Z_OBJPROP_P(zvp) : Z_TYPE_P(zvp) == IS_ARRAY ? Z_ARRVAL_P(zvp) : NULL) +#define HT_WATCH_OFFSET (sizeof(zend_refcounted *) + sizeof(uint32_t)) /* we are not interested in gc and flags */ +#define HT_PTR_HT(ptr) ((HashTable *) (((char *) (ptr)) - HT_WATCH_OFFSET)) +#define HT_WATCH_HT(watch) HT_PTR_HT((watch)->addr.ptr) typedef struct { void *page; @@ -42,7 +107,7 @@ typedef struct { #define MEMDUMP_SIZE(size) (sizeof(phpdbg_watch_memdump) - sizeof(void *) + (size)) -static phpdbg_watchpoint_t *phpdbg_check_for_watchpoint(void *addr TSRMLS_DC) { +static phpdbg_watchpoint_t *phpdbg_check_for_watchpoint(void *addr) { phpdbg_watchpoint_t *watch; phpdbg_btree_result *result = phpdbg_btree_find_closest(&PHPDBG_G(watchpoint_tree), (zend_ulong)phpdbg_get_page_boundary(addr) + phpdbg_pagesize - 1); @@ -53,7 +118,7 @@ static phpdbg_watchpoint_t *phpdbg_check_for_watchpoint(void *addr TSRMLS_DC) { watch = result->ptr; /* check if that addr is in a mprotect()'ed memory area */ - if ((char *)phpdbg_get_page_boundary(watch->addr.ptr) > (char *)addr || (char *)phpdbg_get_page_boundary(watch->addr.ptr) + phpdbg_get_total_page_size(watch->addr.ptr, watch->size) < (char *)addr) { + if ((char *) phpdbg_get_page_boundary(watch->addr.ptr) > (char *) addr || (char *) phpdbg_get_page_boundary(watch->addr.ptr) + phpdbg_get_total_page_size(watch->addr.ptr, watch->size) < (char *) addr) { /* failure */ return NULL; } @@ -61,27 +126,25 @@ static phpdbg_watchpoint_t *phpdbg_check_for_watchpoint(void *addr TSRMLS_DC) { return watch; } -static void phpdbg_change_watchpoint_access(phpdbg_watchpoint_t *watch, int access TSRMLS_DC) { - int m; - +static void phpdbg_change_watchpoint_access(phpdbg_watchpoint_t *watch, int access) { /* pagesize is assumed to be in the range of 2^x */ - m = mprotect(phpdbg_get_page_boundary(watch->addr.ptr), phpdbg_get_total_page_size(watch->addr.ptr, watch->size), access); + mprotect(phpdbg_get_page_boundary(watch->addr.ptr), phpdbg_get_total_page_size(watch->addr.ptr, watch->size), access); } -static inline void phpdbg_activate_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) { - phpdbg_change_watchpoint_access(watch, PROT_READ TSRMLS_CC); +static inline void phpdbg_activate_watchpoint(phpdbg_watchpoint_t *watch) { + phpdbg_change_watchpoint_access(watch, PROT_READ); } -static inline void phpdbg_deactivate_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) { - phpdbg_change_watchpoint_access(watch, PROT_READ | PROT_WRITE TSRMLS_CC); +static inline void phpdbg_deactivate_watchpoint(phpdbg_watchpoint_t *watch) { + phpdbg_change_watchpoint_access(watch, PROT_READ | PROT_WRITE); } -static inline void phpdbg_store_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) { - phpdbg_btree_insert(&PHPDBG_G(watchpoint_tree), (zend_ulong)watch->addr.ptr, watch); +static inline void phpdbg_store_watchpoint(phpdbg_watchpoint_t *watch) { + phpdbg_btree_insert(&PHPDBG_G(watchpoint_tree), (zend_ulong) watch->addr.ptr, watch); } -static inline void phpdbg_remove_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) { - phpdbg_btree_delete(&PHPDBG_G(watchpoint_tree), (zend_ulong)watch->addr.ptr); +static inline void phpdbg_remove_watchpoint(phpdbg_watchpoint_t *watch) { + phpdbg_btree_delete(&PHPDBG_G(watchpoint_tree), (zend_ulong) watch->addr.ptr); } void phpdbg_create_addr_watchpoint(void *addr, size_t size, phpdbg_watchpoint_t *watch) { @@ -95,326 +158,547 @@ void phpdbg_create_zval_watchpoint(zval *zv, phpdbg_watchpoint_t *watch) { } void phpdbg_create_ht_watchpoint(HashTable *ht, phpdbg_watchpoint_t *watch) { - phpdbg_create_addr_watchpoint(ht, sizeof(HashTable), watch); + phpdbg_create_addr_watchpoint(((char *) ht) + HT_WATCH_OFFSET, sizeof(HashTable) - HT_WATCH_OFFSET, watch); watch->type = WATCH_ON_HASHTABLE; + watch->implicit_ht_count = 0; } -void phpdbg_watch_HashTable_dtor(zval **ptr); +static int phpdbg_create_recursive_ht_watch(phpdbg_watchpoint_t *watch); +static int phpdbg_create_recursive_zval_watch(phpdbg_watchpoint_t *watch); -static int phpdbg_create_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) { - watch->flags |= PHPDBG_WATCH_SIMPLE; +void phpdbg_watch_HashTable_dtor(zval *ptr); - phpdbg_store_watchpoint(watch TSRMLS_CC); - zend_hash_add(&PHPDBG_G(watchpoints), watch->str, watch->str_len, &watch, sizeof(phpdbg_watchpoint_t *), NULL); +static void phpdbg_free_watch(phpdbg_watchpoint_t *watch) { + zend_string_release(watch->str); + zend_string_release(watch->name_in_parent); +} - if (watch->type == WATCH_ON_ZVAL) { - phpdbg_btree_insert(&PHPDBG_G(watch_HashTables), (zend_ulong)watch->parent_container, watch->parent_container->pDestructor); - watch->parent_container->pDestructor = (dtor_func_t)phpdbg_watch_HashTable_dtor; +static int phpdbg_delete_watchpoint(phpdbg_watchpoint_t *tmp_watch); +static void phpdbg_delete_ht_watchpoints_recursive(phpdbg_watchpoint_t *watch); +static void phpdbg_delete_zval_watchpoints_recursive(phpdbg_watchpoint_t *watch); +static void phpdbg_delete_watchpoints_recursive(phpdbg_watchpoint_t *watch); + +/* Store all the possible watches the refcounted may refer to (for displaying & deleting by identifier) [collision] */ +static phpdbg_watchpoint_t *phpdbg_create_refcounted_watchpoint(phpdbg_watchpoint_t *parent, zend_refcounted *ref) { + phpdbg_watchpoint_t *watch = emalloc(sizeof(phpdbg_watchpoint_t)); + watch->flags = parent->flags; + watch->parent = parent; + watch->str = parent->str; + ++GC_REFCOUNT(parent->str); + phpdbg_create_addr_watchpoint(&GC_REFCOUNT(ref), sizeof(uint32_t), watch); + watch->type = WATCH_ON_REFCOUNTED; + + return watch; +} + +/* Must prevent duplicates ... if there are duplicates, replace new by old! */ +static void phpdbg_add_watch_collision(phpdbg_watchpoint_t *watch) { + phpdbg_watch_collision *cur; + + /* Check for either recursive or (simple and/or implicit) */ + ZEND_ASSERT(((watch->flags & PHPDBG_WATCH_RECURSIVE) == 0) ^ ((watch->flags & (PHPDBG_WATCH_IMPLICIT | PHPDBG_WATCH_SIMPLE)) == 0)); + + if ((cur = zend_hash_index_find_ptr(&PHPDBG_G(watch_collisions), (zend_ulong) watch->addr.ref))) { + phpdbg_watchpoint_t *old; + int flags = 0; + if ((old = zend_hash_find_ptr(&cur->watches, watch->str)) || (old = zend_hash_find_ptr(&cur->implicit_watches, watch->str))) { + if (((old->flags ^ watch->flags) & (PHPDBG_WATCH_NORMAL|PHPDBG_WATCH_IMPLICIT)) == 0) { + return; /* there was no change ... */ + } + + flags = old->flags; + + if (flags & PHPDBG_WATCH_RECURSIVE) { + if (!(watch->flags & PHPDBG_WATCH_RECURSIVE) && !--cur->refs) { + phpdbg_delete_watchpoints_recursive(watch); + } + } + if (flags & PHPDBG_WATCH_NORMAL) { + zend_hash_del(&cur->watches, watch->str); + if (zend_hash_num_elements(&cur->watches) > 0) { + cur->watch = Z_PTR_P(zend_hash_get_current_data_ex(&cur->watches, NULL)); + } else { + cur->watch = Z_PTR_P(zend_hash_get_current_data_ex(&cur->implicit_watches, NULL)); + } + } + if (flags & PHPDBG_WATCH_IMPLICIT) { + zend_hash_del(&cur->implicit_watches, watch->str); + } + + old->flags = watch->flags; + phpdbg_free_watch(watch); + efree(watch); + watch = old; + } + if (watch->flags & PHPDBG_WATCH_RECURSIVE) { + if (!(flags & PHPDBG_WATCH_RECURSIVE) && !cur->refs++) { + phpdbg_create_recursive_zval_watch(watch->parent); + } + } + } else { + phpdbg_watch_collision coll; + coll.refs = (watch->flags & PHPDBG_WATCH_RECURSIVE) != 0; + coll.watch = watch; + zend_hash_init(&coll.watches, 8, arghs, NULL, 0); + zend_hash_init(&coll.implicit_watches, 8, ..., NULL, 0); + cur = zend_hash_index_add_mem(&PHPDBG_G(watch_collisions), (zend_ulong) watch->addr.ref, &coll, sizeof(phpdbg_watch_collision)); + phpdbg_store_watchpoint(cur->watch); + phpdbg_activate_watchpoint(cur->watch); + if (coll.refs) { + phpdbg_create_recursive_zval_watch(watch->parent); + } } - phpdbg_activate_watchpoint(watch TSRMLS_CC); + if (watch->flags & PHPDBG_WATCH_NORMAL) { + cur->watch = watch; + zend_hash_add_ptr(&cur->watches, watch->str, watch->parent); + } + if (watch->flags & PHPDBG_WATCH_IMPLICIT) { + zend_hash_add_ptr(&cur->implicit_watches, watch->str, watch->parent); + } +} - return SUCCESS; +static void phpdbg_remove_watch_collision(phpdbg_watchpoint_t *watch) { + phpdbg_watch_collision *cur; + if ((cur = zend_hash_index_find_ptr(&PHPDBG_G(watch_collisions), (zend_ulong) Z_COUNTED_P(watch->addr.zv)))) { + if (cur->refs && !--cur->refs) { + phpdbg_delete_watchpoints_recursive(watch); + } + + zend_hash_del(&cur->watches, watch->str); + zend_hash_del(&cur->implicit_watches, watch->str); + + if (zend_hash_num_elements(&cur->watches) > 0) { + cur->watch = Z_PTR_P(zend_hash_get_current_data_ex(&cur->watches, NULL)); + } else if (zend_hash_num_elements(&cur->implicit_watches) > 0) { + cur->watch = Z_PTR_P(zend_hash_get_current_data_ex(&cur->implicit_watches, NULL)); + } else { + phpdbg_deactivate_watchpoint(cur->watch); + phpdbg_remove_watchpoint(cur->watch); + + zend_hash_index_del(&PHPDBG_G(watch_collisions), (zend_ulong) Z_COUNTED_P(watch->addr.zv)); + } + } } -static int phpdbg_create_array_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) { - HashTable *ht; +static phpdbg_watchpoint_t *phpdbg_create_watchpoint(phpdbg_watchpoint_t *watch); - switch (Z_TYPE_P(watch->addr.zv)) { - case IS_ARRAY: - ht = Z_ARRVAL_P(watch->addr.zv); - break; - case IS_OBJECT: - ht = Z_OBJPROP_P(watch->addr.zv); - break; - default: - return FAILURE; +static phpdbg_watchpoint_t *phpdbg_create_reference_watch(phpdbg_watchpoint_t *watch) { + phpdbg_watchpoint_t *ref = emalloc(sizeof(phpdbg_watchpoint_t)); + watch->reference = ref; + ref->flags = watch->flags; + ref->str = watch->str; + ++GC_REFCOUNT(ref->str); + ref->parent = watch; + ref->parent_container = NULL; + phpdbg_create_zval_watchpoint(Z_REFVAL_P(watch->addr.zv), ref); + + phpdbg_create_watchpoint(ref); + + return ref; +} + +static phpdbg_watchpoint_t *phpdbg_get_refcount_watch(phpdbg_watchpoint_t *parent) { + zend_refcounted *ref; + phpdbg_btree_result *res; + + if (parent->type == WATCH_ON_HASHTABLE) { + parent = parent->parent; + if (!parent) { + return NULL; + } } - phpdbg_create_ht_watchpoint(ht, watch); + ZEND_ASSERT(parent->type == WATCH_ON_ZVAL); + ref = Z_COUNTED_P(parent->addr.zv); - phpdbg_create_watchpoint(watch TSRMLS_CC); + res = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong) ref); + if (res) { + return res->ptr; + } + return NULL; +} - return SUCCESS; +static phpdbg_watchpoint_t *phpdbg_create_watchpoint(phpdbg_watchpoint_t *watch) { + phpdbg_watchpoint_t *ret = watch; + + if (watch->type == WATCH_ON_ZVAL) { + switch (Z_TYPE_P(watch->addr.zv)) { + case IS_NULL: + case IS_UNDEF: + case IS_TRUE: + case IS_FALSE: + memset(watch->addr.zv, 0, sizeof(zend_value)); + } + } + + /* exclude references & refcounted */ + if (!watch->parent || watch->parent->type != WATCH_ON_ZVAL || watch->type == WATCH_ON_HASHTABLE) { + phpdbg_watchpoint_t *old_watch = zend_hash_find_ptr(&PHPDBG_G(watchpoints), watch->str); + + if (old_watch) { +#define return_and_free_watch(x) { \ + phpdbg_watchpoint_t *ref = phpdbg_get_refcount_watch(old_watch); \ + if (ref) { \ + phpdbg_add_watch_collision(ref); \ + } \ + if (watch != old_watch) { \ + phpdbg_free_watch(watch); \ + efree(watch); \ + } \ + return (x); \ } + if (watch->flags & PHPDBG_WATCH_RECURSIVE) { + if (old_watch->flags & PHPDBG_WATCH_RECURSIVE) { + return_and_free_watch(NULL); + } else { + old_watch->flags &= ~(PHPDBG_WATCH_SIMPLE | PHPDBG_WATCH_IMPLICIT); + old_watch->flags |= PHPDBG_WATCH_RECURSIVE; + return_and_free_watch(old_watch); + } + } else { + if (!(old_watch->flags & PHPDBG_WATCH_RECURSIVE)) { + old_watch->flags |= watch->flags & (PHPDBG_WATCH_IMPLICIT | PHPDBG_WATCH_SIMPLE); + } + return_and_free_watch(NULL); + } + } else { + if (watch->parent && watch->parent->type == WATCH_ON_HASHTABLE) { + watch->parent->implicit_ht_count++; + } + zend_hash_add_ptr(&PHPDBG_G(watchpoints), watch->str, watch); + } + } + + phpdbg_store_watchpoint(watch); + + if (watch->parent && watch->parent->type == WATCH_ON_ZVAL && Z_REFCOUNTED_P(watch->parent->addr.zv)) { + phpdbg_add_watch_collision(phpdbg_create_refcounted_watchpoint(watch, Z_COUNTED_P(watch->parent->addr.zv))); + } + + if (watch->type == WATCH_ON_ZVAL) { + if (watch->parent_container) { + HashTable *ht_watches; + phpdbg_btree_result *find; + if (!(find = phpdbg_btree_find(&PHPDBG_G(watch_HashTables), (zend_ulong) watch->parent_container))) { + phpdbg_watch_ht_info *hti = emalloc(sizeof(*hti)); + hti->dtor = watch->parent_container->pDestructor; + ht_watches = &hti->watches; + zend_hash_init(ht_watches, 0, grrrrr, ZVAL_PTR_DTOR, 0); + phpdbg_btree_insert(&PHPDBG_G(watch_HashTables), (zend_ulong) watch->parent_container, hti); + watch->parent_container->pDestructor = (dtor_func_t) phpdbg_watch_HashTable_dtor; + } else { + ht_watches = &((phpdbg_watch_ht_info *) find->ptr)->watches; + } + zend_hash_add_ptr(ht_watches, watch->name_in_parent, watch); + } -static char *phpdbg_get_property_key(char *key) { - if (*key != 0) { - return key; + if (Z_ISREF_P(watch->addr.zv)) { + ret = phpdbg_create_reference_watch(watch); + } } - return strchr(key + 1, 0) + 1; + + phpdbg_activate_watchpoint(watch); + + return ret; } -static int phpdbg_create_recursive_watchpoint(phpdbg_watchpoint_t *watch TSRMLS_DC) { - HashTable *ht; +static int phpdbg_create_simple_watchpoint(phpdbg_watchpoint_t *watch) { + watch->flags |= PHPDBG_WATCH_SIMPLE; + + phpdbg_create_watchpoint(watch); + + return SUCCESS; +} + +static int phpdbg_create_array_watchpoint(phpdbg_watchpoint_t *zv_watch) { + zval *zv = zv_watch->addr.zv; + phpdbg_watchpoint_t *watch = emalloc(sizeof(phpdbg_watchpoint_t)); + HashTable *ht = HT_FROM_ZVP(zv); + + watch->parent = zv_watch; + + if (!ht) { + return FAILURE; + } + + phpdbg_create_ht_watchpoint(ht, watch); + + if (phpdbg_create_watchpoint(watch) == NULL) { + return SUCCESS; + } + + if (Z_TYPE_P(zv) == IS_ARRAY) { + watch->flags |= PHPDBG_WATCH_ARRAY; + } else { + watch->flags |= PHPDBG_WATCH_OBJECT; + } + phpdbg_add_watch_collision(phpdbg_create_refcounted_watchpoint(watch, Z_COUNTED_P(zv))); + + return SUCCESS; +} + +static int phpdbg_create_recursive_watchpoint(phpdbg_watchpoint_t *watch) { if (watch->type != WATCH_ON_ZVAL) { return FAILURE; } watch->flags |= PHPDBG_WATCH_RECURSIVE; - phpdbg_create_watchpoint(watch TSRMLS_CC); + watch = phpdbg_create_watchpoint(watch); - switch (Z_TYPE_P(watch->addr.zv)) { - case IS_ARRAY: - ht = Z_ARRVAL_P(watch->addr.zv); - break; - case IS_OBJECT: - ht = Z_OBJPROP_P(watch->addr.zv); - break; - default: - return SUCCESS; - } + return SUCCESS; +} - { - HashPosition position; - zval **zv; - zval key; +static int phpdbg_create_recursive_ht_watch(phpdbg_watchpoint_t *watch) { + zval *zv; + zend_string *key; + zend_long h; - for (zend_hash_internal_pointer_reset_ex(ht, &position); - zend_hash_get_current_data_ex(ht, (void **)&zv, &position) == SUCCESS; - zend_hash_move_forward_ex(ht, &position)) { - phpdbg_watchpoint_t *new_watch = emalloc(sizeof(phpdbg_watchpoint_t)); + ZEND_ASSERT(watch->type == WATCH_ON_HASHTABLE); - new_watch->flags = PHPDBG_WATCH_RECURSIVE; - new_watch->parent = watch; - new_watch->parent_container = ht; + ZEND_HASH_FOREACH_KEY_VAL(HT_WATCH_HT(watch), h, key, zv) { + phpdbg_watchpoint_t *new_watch = emalloc(sizeof(phpdbg_watchpoint_t)); - zend_hash_get_current_key_zval_ex(ht, &key, &position); - if (Z_TYPE(key) == IS_STRING) { - new_watch->name_in_parent = zend_strndup(Z_STRVAL(key), Z_STRLEN(key)); - new_watch->name_in_parent_len = Z_STRLEN(key); - } else { - new_watch->name_in_parent = NULL; - new_watch->name_in_parent_len = asprintf(&new_watch->name_in_parent, "%ld", Z_LVAL(key)); - } + new_watch->flags = PHPDBG_WATCH_RECURSIVE; + new_watch->parent = watch; + new_watch->parent_container = HT_WATCH_HT(watch); - new_watch->str = NULL; - new_watch->str_len = asprintf(&new_watch->str, "%.*s%s%s%s", (int)watch->str_len, watch->str, Z_TYPE_P(watch->addr.zv) == IS_ARRAY?"[":"->", phpdbg_get_property_key(new_watch->name_in_parent), Z_TYPE_P(watch->addr.zv) == IS_ARRAY?"]":""); + if (key) { + new_watch->name_in_parent = key; + ++GC_REFCOUNT(key); + } else { + new_watch->name_in_parent = strpprintf(0, ZEND_LONG_FMT, h); + } - phpdbg_create_zval_watchpoint(*zv, new_watch); - phpdbg_create_recursive_watchpoint(new_watch TSRMLS_CC); + new_watch->str = strpprintf(0, "%.*s%s%s%s", (int) ZSTR_LEN(watch->str) - 2, ZSTR_VAL(watch->str), (watch->flags & PHPDBG_WATCH_ARRAY) ? "[" : "->", phpdbg_get_property_key(ZSTR_VAL(new_watch->name_in_parent)), (watch->flags & PHPDBG_WATCH_ARRAY) ? "]" : ""); + + while (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); } - } - { + phpdbg_create_zval_watchpoint(zv, new_watch); + new_watch = phpdbg_create_watchpoint(new_watch); + phpdbg_create_recursive_zval_watch(new_watch); + } ZEND_HASH_FOREACH_END(); + + return SUCCESS; +} + +static int phpdbg_create_recursive_zval_watch(phpdbg_watchpoint_t *watch) { + HashTable *ht; + zval *zvp; + + ZEND_ASSERT(watch->type == WATCH_ON_ZVAL); + + zvp = watch->addr.zv; + ZVAL_DEREF(zvp); + + if ((ht = HT_FROM_ZVP(zvp))) { phpdbg_watchpoint_t *new_watch = emalloc(sizeof(phpdbg_watchpoint_t)); + new_watch->flags = PHPDBG_WATCH_RECURSIVE; new_watch->parent = watch; new_watch->parent_container = watch->parent_container; - new_watch->name_in_parent = zend_strndup(watch->name_in_parent, watch->name_in_parent_len); - new_watch->name_in_parent_len = watch->name_in_parent_len; - new_watch->str = NULL; - new_watch->str_len = asprintf(&new_watch->str, "%.*s[]", (int)watch->str_len, watch->str); - new_watch->flags = PHPDBG_WATCH_RECURSIVE; + new_watch->name_in_parent = watch->name_in_parent; + ++GC_REFCOUNT(new_watch->name_in_parent); + new_watch->str = strpprintf(0, "%.*s[]", (int) ZSTR_LEN(watch->str), ZSTR_VAL(watch->str)); + + if (Z_TYPE_P(zvp) == IS_ARRAY) { + new_watch->flags |= PHPDBG_WATCH_ARRAY; + } else { + new_watch->flags |= PHPDBG_WATCH_OBJECT; + } phpdbg_create_ht_watchpoint(ht, new_watch); - phpdbg_create_watchpoint(new_watch TSRMLS_CC); + + phpdbg_create_recursive_ht_watch(new_watch); + + phpdbg_create_watchpoint(new_watch); } return SUCCESS; } -static int phpdbg_delete_watchpoint_recursive(phpdbg_watchpoint_t *watch, zend_bool user_request TSRMLS_DC) { - if (watch->type == WATCH_ON_HASHTABLE || (watch->type == WATCH_ON_ZVAL && (Z_TYPE_P(watch->addr.zv) == IS_ARRAY || Z_TYPE_P(watch->addr.zv) == IS_OBJECT))) { - HashTable *ht; - phpdbg_btree_result *result; - - if (watch->type == WATCH_ON_HASHTABLE && user_request) { - HashPosition position; - zval **zv; - zval key; - char *str; - int str_len; - phpdbg_watchpoint_t **watchpoint; - - ht = watch->addr.ht; - - for (zend_hash_internal_pointer_reset_ex(ht, &position); - zend_hash_get_current_data_ex(ht, (void **)&zv, &position) == SUCCESS; - zend_hash_move_forward_ex(ht, &position)) { - zend_hash_get_current_key_zval_ex(ht, &key, &position); - str = NULL; - if (Z_TYPE(key) == IS_STRING) { - str_len = asprintf(&str, "%.*s%s%s%s", (int)watch->parent->str_len, watch->parent->str, Z_TYPE_P(watch->parent->addr.zv) == IS_ARRAY?"[":"->", phpdbg_get_property_key(Z_STRVAL(key)), Z_TYPE_P(watch->parent->addr.zv) == IS_ARRAY?"]":""); - } else { - str_len = asprintf(&str, "%.*s%s%li%s", (int)watch->parent->str_len, watch->parent->str, Z_TYPE_P(watch->parent->addr.zv) == IS_ARRAY?"[":"->", Z_LVAL(key), Z_TYPE_P(watch->parent->addr.zv) == IS_ARRAY?"]":""); - } +static void phpdbg_delete_implicit_parents(phpdbg_watchpoint_t *watch) { + phpdbg_watchpoint_t *parent = watch->parent; + if (!parent) { + return; + } - if (zend_hash_find(&PHPDBG_G(watchpoints), str, str_len, (void **) &watchpoint) == SUCCESS) { - phpdbg_delete_watchpoint_recursive(*watchpoint, 1 TSRMLS_CC); - } - } + ZEND_ASSERT(!(parent->flags & PHPDBG_WATCH_RECURSIVE)); + ZEND_ASSERT(parent->flags & PHPDBG_WATCH_IMPLICIT); + + if (parent->type == WATCH_ON_HASHTABLE && --parent->implicit_ht_count) { + return; + } + + parent->flags &= ~PHPDBG_WATCH_IMPLICIT; + if (!(parent->flags & PHPDBG_WATCH_SIMPLE)) { + if (parent->type == WATCH_ON_ZVAL && Z_REFCOUNTED_P(watch->addr.zv)) { + phpdbg_remove_watch_collision(parent); + } + zend_hash_del(&PHPDBG_G(watchpoints), parent->str); + } +} + +/* delete watchpoint, recursively (and inclusively) */ +static int phpdbg_delete_watchpoint_recursive(phpdbg_watchpoint_t *watch, zend_bool user_request) { + if (watch->type == WATCH_ON_HASHTABLE) { + if (user_request) { + phpdbg_delete_ht_watchpoints_recursive(watch); } else { - switch (Z_TYPE_P(watch->addr.zv)) { - case IS_ARRAY: - ht = Z_ARRVAL_P(watch->addr.zv); - break; - case IS_OBJECT: - ht = Z_OBJPROP_P(watch->addr.zv); - break; - } + HashTable *ht; + phpdbg_btree_result *result; + + ht = HT_FROM_ZVP(watch->addr.zv); if ((result = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong) ht))) { - phpdbg_delete_watchpoint_recursive((phpdbg_watchpoint_t *) result->ptr, user_request TSRMLS_CC); + phpdbg_delete_watchpoint_recursive((phpdbg_watchpoint_t *) result->ptr, user_request); } } + } else if (watch->type == WATCH_ON_ZVAL) { + phpdbg_delete_zval_watchpoints_recursive(watch); + } + + return zend_hash_del(&PHPDBG_G(watchpoints), watch->str); +} + +static void phpdbg_delete_ht_watchpoints_recursive(phpdbg_watchpoint_t *watch) { + zend_string *str, *strkey; + zend_long numkey; + phpdbg_watchpoint_t *watchpoint; + + ZEND_HASH_FOREACH_KEY(HT_WATCH_HT(watch), numkey, strkey) { + if (strkey) { + str = strpprintf(0, "%.*s%s%s%s", (int) ZSTR_LEN(watch->str), ZSTR_VAL(watch->str), (watch->flags & PHPDBG_WATCH_ARRAY) ? "[" : "->", phpdbg_get_property_key(ZSTR_VAL(strkey)), (watch->flags & PHPDBG_WATCH_ARRAY) ? "]" : ""); + } else { + str = strpprintf(0, "%.*s%s" ZEND_LONG_FMT "%s", (int) ZSTR_LEN(watch->str), ZSTR_VAL(watch->str), (watch->flags & PHPDBG_WATCH_ARRAY) ? "[" : "->", numkey, (watch->flags & PHPDBG_WATCH_ARRAY) ? "]" : ""); + } + + if ((watchpoint = zend_hash_find_ptr(&PHPDBG_G(watchpoints), str))) { + phpdbg_delete_watchpoint_recursive(watchpoint, 1); + } + + zend_string_release(str); + } ZEND_HASH_FOREACH_END(); +} + +static void phpdbg_delete_zval_watchpoints_recursive(phpdbg_watchpoint_t *watch) { + if (Z_REFCOUNTED_P(watch->addr.zv)) { + phpdbg_remove_watch_collision(watch); } +} - return zend_hash_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); +/* delete watchpoints recusively (exclusively!) */ +static void phpdbg_delete_watchpoints_recursive(phpdbg_watchpoint_t *watch) { + if (watch->type == WATCH_ON_ZVAL) { + phpdbg_delete_zval_watchpoints_recursive(watch); + } else if (watch->type == WATCH_ON_HASHTABLE) { + phpdbg_delete_ht_watchpoints_recursive(watch); + } } -static int phpdbg_delete_watchpoint(phpdbg_watchpoint_t *tmp_watch TSRMLS_DC) { +static int phpdbg_delete_watchpoint(phpdbg_watchpoint_t *tmp_watch) { int ret; phpdbg_watchpoint_t *watch; phpdbg_btree_result *result; - if ((result = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong)tmp_watch->addr.ptr)) == NULL) { + if ((result = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong) tmp_watch->addr.ptr)) == NULL) { return FAILURE; } watch = result->ptr; + if (!(watch->flags & PHPDBG_WATCH_NORMAL) || (watch->parent && (watch->parent->flags & PHPDBG_WATCH_RECURSIVE))) { + return FAILURE; /* TODO: better error message for recursive (??) */ + } + if (watch->flags & PHPDBG_WATCH_RECURSIVE) { - ret = phpdbg_delete_watchpoint_recursive(watch, 1 TSRMLS_CC); + ret = phpdbg_delete_watchpoint_recursive(watch, 1); } else { - ret = zend_hash_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); + ret = zend_hash_del(&PHPDBG_G(watchpoints), watch->str); } - free(tmp_watch->str); + phpdbg_free_watch(tmp_watch); efree(tmp_watch); return ret; } -static int phpdbg_watchpoint_parse_input(char *input, size_t len, HashTable *parent, size_t i, int (*callback)(phpdbg_watchpoint_t * TSRMLS_DC), zend_bool silent TSRMLS_DC) { - int ret = FAILURE; - zend_bool new_index = 1; - char *last_index; - int index_len = 0; - zval **zv; +static int phpdbg_watchpoint_parse_wrapper(char *name, size_t namelen, char *key, size_t keylen, HashTable *parent, zval *zv, int (*callback)(phpdbg_watchpoint_t *)) { + int ret; + phpdbg_watchpoint_t *watch = ecalloc(1, sizeof(phpdbg_watchpoint_t)); + watch->str = zend_string_init(name, namelen, 0); + watch->name_in_parent = zend_string_init(key, keylen, 0); + watch->parent_container = parent; + phpdbg_create_zval_watchpoint(zv, watch); - if (len < 2 || *input != '$') { - goto error; + ret = callback(watch); + + efree(name); + efree(key); + + if (ret != SUCCESS) { + phpdbg_free_watch(watch); + efree(watch); } - while (i++ < len) { - if (i == len) { - new_index = 1; - } else { - switch (input[i]) { - case '[': - new_index = 1; - break; - case ']': - break; - case '>': - if (last_index[index_len - 1] == '-') { - new_index = 1; - index_len--; - } - break; + PHPDBG_G(watch_tmp) = NULL; - default: - if (new_index) { - last_index = input + i; - new_index = 0; - } - if (input[i - 1] == ']') { - goto error; - } - index_len++; - } - } + return ret; +} - if (new_index && index_len == 0) { - HashPosition position; - for (zend_hash_internal_pointer_reset_ex(parent, &position); - zend_hash_get_current_data_ex(parent, (void **)&zv, &position) == SUCCESS; - zend_hash_move_forward_ex(parent, &position)) { - if (i == len || (i == len - 1 && input[len - 1] == ']')) { - zval *key = emalloc(sizeof(zval)); - phpdbg_watchpoint_t *watch = emalloc(sizeof(phpdbg_watchpoint_t)); - watch->flags = 0; - zend_hash_get_current_key_zval_ex(parent, key, &position); - convert_to_string(key); - watch->str = malloc(i + Z_STRLEN_P(key) + 2); - watch->str_len = sprintf(watch->str, "%.*s%s%s", (int)i, input, phpdbg_get_property_key(Z_STRVAL_P(key)), input[len - 1] == ']'?"]":""); - efree(key); - watch->name_in_parent = zend_strndup(last_index, index_len); - watch->name_in_parent_len = index_len; - watch->parent_container = parent; - phpdbg_create_zval_watchpoint(*zv, watch); - - ret = callback(watch TSRMLS_CC) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE; - } else if (Z_TYPE_PP(zv) == IS_OBJECT) { - phpdbg_watchpoint_parse_input(input, len, Z_OBJPROP_PP(zv), i, callback, silent TSRMLS_CC); - } else if (Z_TYPE_PP(zv) == IS_ARRAY) { - phpdbg_watchpoint_parse_input(input, len, Z_ARRVAL_PP(zv), i, callback, silent TSRMLS_CC); - } else { - /* Ignore silently */ - } - } - return ret; - } else if (new_index) { - char last_chr = last_index[index_len]; - last_index[index_len] = 0; - if (zend_symtable_find(parent, last_index, index_len + 1, (void **)&zv) == FAILURE) { - if (!silent) { - phpdbg_error("%.*s is undefined", (int)i, input); - } - return FAILURE; - } - last_index[index_len] = last_chr; - if (i == len) { - phpdbg_watchpoint_t *watch = emalloc(sizeof(phpdbg_watchpoint_t)); - watch->flags = 0; - watch->str = zend_strndup(input, len); - watch->str_len = len; - watch->name_in_parent = zend_strndup(last_index, index_len); - watch->name_in_parent_len = index_len; - watch->parent_container = parent; - phpdbg_create_zval_watchpoint(*zv, watch); - - ret = callback(watch TSRMLS_CC) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE; - } else if (Z_TYPE_PP(zv) == IS_OBJECT) { - parent = Z_OBJPROP_PP(zv); - } else if (Z_TYPE_PP(zv) == IS_ARRAY) { - parent = Z_ARRVAL_PP(zv); - } else { - phpdbg_error("%.*s is nor an array nor an object", (int)i, input); - return FAILURE; - } - index_len = 0; - } +PHPDBG_API int phpdbg_watchpoint_parse_input(char *input, size_t len, HashTable *parent, size_t i, int (*callback)(phpdbg_watchpoint_t *), zend_bool silent) { + return phpdbg_parse_variable_with_arg(input, len, parent, i, (phpdbg_parse_var_with_arg_func) phpdbg_watchpoint_parse_wrapper, NULL, 0, callback); +} + +static int phpdbg_watchpoint_parse_step(char *name, size_t namelen, char *key, size_t keylen, HashTable *parent, zval *zv, int (*callback)(phpdbg_watchpoint_t *)) { + phpdbg_watchpoint_t *watch; + + if ((watch = zend_hash_str_find_ptr(&PHPDBG_G(watchpoints), name, namelen))) { + watch->flags |= PHPDBG_WATCH_IMPLICIT; + PHPDBG_G(watch_tmp) = watch; + return SUCCESS; } - return ret; - error: - phpdbg_error("Malformed input"); - return FAILURE; + watch = ecalloc(1, sizeof(phpdbg_watchpoint_t)); + watch->flags = PHPDBG_WATCH_IMPLICIT; + watch->str = zend_string_init(name, namelen, 0); + watch->name_in_parent = zend_string_init(key, keylen, 0); + watch->parent_container = parent; + watch->parent = PHPDBG_G(watch_tmp); + phpdbg_create_zval_watchpoint(zv, watch); + + phpdbg_create_watchpoint(watch); + + efree(name); + efree(key); + + PHPDBG_G(watch_tmp) = watch; + return SUCCESS; } -static int phpdbg_watchpoint_parse_symtables(char *input, size_t len, int (*callback)(phpdbg_watchpoint_t * TSRMLS_DC) TSRMLS_DC) { - if (EG(This) && len >= 5 && !memcmp("$this", input, 5)) { - zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), NULL); +static int phpdbg_watchpoint_parse_symtables(char *input, size_t len, int (*callback)(phpdbg_watchpoint_t *)) { + if (EG(scope) && len >= 5 && !memcmp("$this", input, 5)) { + zend_hash_str_add(EG(current_execute_data)->symbol_table, ZEND_STRL("this"), &EG(current_execute_data)->This); } - if (zend_is_auto_global(input, len TSRMLS_CC) && phpdbg_watchpoint_parse_input(input, len, &EG(symbol_table), 0, callback, 1 TSRMLS_CC) != FAILURE) { + if (phpdbg_is_auto_global(input, len) && phpdbg_watchpoint_parse_input(input, len, &EG(symbol_table), 0, callback, 1) != FAILURE) { return SUCCESS; } - return phpdbg_watchpoint_parse_input(input, len, EG(active_symbol_table), 0, callback, 0 TSRMLS_CC); + return phpdbg_parse_variable_with_arg(input, len, EG(current_execute_data)->symbol_table, 0, (phpdbg_parse_var_with_arg_func) phpdbg_watchpoint_parse_wrapper, (phpdbg_parse_var_with_arg_func) phpdbg_watchpoint_parse_step, 0, callback); } PHPDBG_WATCH(delete) /* {{{ */ { switch (param->type) { case STR_PARAM: - if (phpdbg_delete_var_watchpoint(param->str, param->len TSRMLS_CC) == FAILURE) { - phpdbg_error("Nothing was deleted, no corresponding watchpoint found"); + if (phpdbg_delete_var_watchpoint(param->str, param->len) == FAILURE) { + phpdbg_error("watchdelete", "type=\"nowatch\"", "Nothing was deleted, no corresponding watchpoint found"); } else { - phpdbg_notice("Removed watchpoint %.*s", (int)param->len, param->str); + phpdbg_notice("watchdelete", "variable=\"%.*s\"", "Removed watchpoint %.*s", (int) param->len, param->str); } break; @@ -426,14 +710,14 @@ PHPDBG_WATCH(delete) /* {{{ */ PHPDBG_WATCH(recursive) /* {{{ */ { - if (phpdbg_rebuild_symtable(TSRMLS_C) == FAILURE) { + if (phpdbg_rebuild_symtable() == FAILURE) { return SUCCESS; } switch (param->type) { case STR_PARAM: - if (phpdbg_watchpoint_parse_symtables(param->str, param->len, phpdbg_create_recursive_watchpoint TSRMLS_CC) != FAILURE) { - phpdbg_notice("Set recursive watchpoint on %.*s", (int)param->len, param->str); + if (phpdbg_watchpoint_parse_symtables(param->str, param->len, phpdbg_create_recursive_watchpoint) != FAILURE) { + phpdbg_notice("watchrecursive", "variable=\"%.*s\"", "Set recursive watchpoint on %.*s", (int)param->len, param->str); } break; @@ -445,14 +729,14 @@ PHPDBG_WATCH(recursive) /* {{{ */ PHPDBG_WATCH(array) /* {{{ */ { - if (phpdbg_rebuild_symtable(TSRMLS_C) == FAILURE) { + if (phpdbg_rebuild_symtable() == FAILURE) { return SUCCESS; } switch (param->type) { case STR_PARAM: - if (phpdbg_watchpoint_parse_symtables(param->str, param->len, phpdbg_create_array_watchpoint TSRMLS_CC) != FAILURE) { - phpdbg_notice("Set array watchpoint on %.*s", (int)param->len, param->str); + if (phpdbg_watchpoint_parse_symtables(param->str, param->len, phpdbg_create_array_watchpoint) != FAILURE) { + phpdbg_notice("watcharray", "variable=\"%.*s\"", "Set array watchpoint on %.*s", (int)param->len, param->str); } break; @@ -462,48 +746,65 @@ PHPDBG_WATCH(array) /* {{{ */ return SUCCESS; } /* }}} */ -void phpdbg_watch_HashTable_dtor(zval **zv) { +void phpdbg_watch_HashTable_dtor(zval *zv) { phpdbg_btree_result *result; - TSRMLS_FETCH(); + zval *orig_zv = zv; - zval_ptr_dtor_wrapper(zv); + while (Z_TYPE_P(zv) == IS_INDIRECT) { + zv = Z_INDIRECT_P(zv); + } - if ((result = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong)*zv))) { + if ((result = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong) zv))) { phpdbg_watchpoint_t *watch = result->ptr; - PHPDBG_G(watchpoint_hit) = 1; + if (watch->flags & PHPDBG_WATCH_NORMAL) { + PHPDBG_G(watchpoint_hit) = 1; - phpdbg_notice("%.*s was removed, removing watchpoint%s", (int)watch->str_len, watch->str, (watch->flags & PHPDBG_WATCH_RECURSIVE)?" recursively":""); + phpdbg_notice("watchdelete", "variable=\"%.*s\" recursive=\"%s\"", "%.*s was removed, removing watchpoint%s", (int) ZSTR_LEN(watch->str), ZSTR_VAL(watch->str), (watch->flags & PHPDBG_WATCH_RECURSIVE) ? " recursively" : ""); + } + + if ((result = phpdbg_btree_find(&PHPDBG_G(watch_HashTables), (zend_ulong) watch->parent_container))) { + phpdbg_watch_ht_info *hti = result->ptr; + hti->dtor(orig_zv); + zend_hash_del(&hti->watches, watch->name_in_parent); + if (zend_hash_num_elements(&hti->watches) == 0) { + watch->parent_container->pDestructor = hti->dtor; + zend_hash_destroy(&hti->watches); + phpdbg_btree_delete(&PHPDBG_G(watch_HashTables), (zend_ulong) watch->parent_container); + efree(hti); + } + } else { + zval_ptr_dtor_wrapper(orig_zv); + } if (watch->flags & PHPDBG_WATCH_RECURSIVE) { - phpdbg_delete_watchpoint_recursive(watch, 0 TSRMLS_CC); + phpdbg_delete_watchpoint_recursive(watch, 0); } else { - zend_hash_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); + zend_hash_del(&PHPDBG_G(watchpoints), watch->str); } } } - -int phpdbg_create_var_watchpoint(char *input, size_t len TSRMLS_DC) { - if (phpdbg_rebuild_symtable(TSRMLS_C) == FAILURE) { +int phpdbg_create_var_watchpoint(char *input, size_t len) { + if (phpdbg_rebuild_symtable() == FAILURE) { return FAILURE; } - return phpdbg_watchpoint_parse_symtables(input, len, phpdbg_create_watchpoint TSRMLS_CC); + return phpdbg_watchpoint_parse_symtables(input, len, phpdbg_create_simple_watchpoint); } -int phpdbg_delete_var_watchpoint(char *input, size_t len TSRMLS_DC) { - if (phpdbg_rebuild_symtable(TSRMLS_C) == FAILURE) { +int phpdbg_delete_var_watchpoint(char *input, size_t len) { + if (phpdbg_rebuild_symtable() == FAILURE) { return FAILURE; } - return phpdbg_watchpoint_parse_symtables(input, len, phpdbg_delete_watchpoint TSRMLS_CC); + return phpdbg_watchpoint_parse_input(input, len, EG(current_execute_data)->symbol_table, 0, phpdbg_delete_watchpoint, 0); } #ifdef _WIN32 -int phpdbg_watchpoint_segfault_handler(void *addr TSRMLS_DC) { +int phpdbg_watchpoint_segfault_handler(void *addr) { #else -int phpdbg_watchpoint_segfault_handler(siginfo_t *info, void *context TSRMLS_DC) { +int phpdbg_watchpoint_segfault_handler(siginfo_t *info, void *context) { #endif void *page; phpdbg_watch_memdump *dump; @@ -516,7 +817,7 @@ int phpdbg_watchpoint_segfault_handler(siginfo_t *info, void *context TSRMLS_DC) #else info->si_addr #endif - TSRMLS_CC); + ); if (watch == NULL) { return FAILURE; @@ -531,6 +832,7 @@ int phpdbg_watchpoint_segfault_handler(siginfo_t *info, void *context TSRMLS_DC) dump = malloc(MEMDUMP_SIZE(size)); dump->page = page; dump->size = size; + dump->reenable_writing = 0; memcpy(&dump->data, page, size); @@ -539,34 +841,55 @@ int phpdbg_watchpoint_segfault_handler(siginfo_t *info, void *context TSRMLS_DC) return SUCCESS; } -void phpdbg_watchpoints_clean(TSRMLS_D) { +void phpdbg_watchpoints_clean(void) { zend_hash_clean(&PHPDBG_G(watchpoints)); } -static void phpdbg_watch_dtor(void *pDest) { - phpdbg_watchpoint_t *watch = *(phpdbg_watchpoint_t **)pDest; - TSRMLS_FETCH(); +/* due to implicit delete... MUST BE DESTROYED MANUALLY */ +static void phpdbg_watch_dtor(zval *pDest) { + phpdbg_watchpoint_t *watch = (phpdbg_watchpoint_t *) Z_PTR_P(pDest); - phpdbg_deactivate_watchpoint(watch TSRMLS_CC); - phpdbg_remove_watchpoint(watch TSRMLS_CC); + if (watch->flags & PHPDBG_WATCH_IMPLICIT) { + watch->flags = PHPDBG_WATCH_SIMPLE; // tiny hack for delete_implicit_parents - free(watch->str); - free(watch->name_in_parent); + if (watch->type == WATCH_ON_ZVAL) { + phpdbg_delete_zval_watchpoints_recursive(watch); + } else if (watch->type == WATCH_ON_HASHTABLE) { + phpdbg_watchpoint_t *watchpoint; + + watch->implicit_ht_count++; + + ZEND_HASH_FOREACH_PTR(&((phpdbg_watch_ht_info *) phpdbg_btree_find(&PHPDBG_G(watch_HashTables), (zend_ulong) HT_WATCH_HT(watch))->ptr)->watches, watchpoint) { + phpdbg_delete_watchpoint_recursive(watchpoint, 1); + } ZEND_HASH_FOREACH_END(); + } + } + + phpdbg_delete_implicit_parents(watch); + + phpdbg_deactivate_watchpoint(watch); + phpdbg_remove_watchpoint(watch); + + phpdbg_free_watch(watch); efree(watch); } static void phpdbg_watch_mem_dtor(void *llist_data) { - phpdbg_watch_memdump *dump = *(phpdbg_watch_memdump **)llist_data; + phpdbg_watch_memdump *dump = *(phpdbg_watch_memdump **) llist_data; /* Disble writing again */ if (dump->reenable_writing) { mprotect(dump->page, dump->size, PROT_READ); } - free(*(void **)llist_data); + free(dump); } -void phpdbg_setup_watchpoints(TSRMLS_D) { +static void phpdbg_watch_free_ptr_dtor(zval *ptr) { + efree(Z_PTR_P(ptr)); +} + +void phpdbg_setup_watchpoints(void) { #if _SC_PAGE_SIZE phpdbg_pagesize = sysconf(_SC_PAGE_SIZE); #elif _SC_PAGESIZE @@ -580,164 +903,199 @@ void phpdbg_setup_watchpoints(TSRMLS_D) { zend_llist_init(&PHPDBG_G(watchlist_mem), sizeof(void *), phpdbg_watch_mem_dtor, 1); phpdbg_btree_init(&PHPDBG_G(watchpoint_tree), sizeof(void *) * 8); phpdbg_btree_init(&PHPDBG_G(watch_HashTables), sizeof(void *) * 8); - zend_hash_init(&PHPDBG_G(watchpoints), 8, NULL, phpdbg_watch_dtor, 0 ZEND_FILE_LINE_CC); + zend_hash_init(&PHPDBG_G(watchpoints), 8, NULL, phpdbg_watch_dtor, 0); + zend_hash_init(&PHPDBG_G(watch_collisions), 8, NULL, phpdbg_watch_free_ptr_dtor, 0); } -static void phpdbg_print_changed_zval(phpdbg_watch_memdump *dump TSRMLS_DC) { +static void phpdbg_print_changed_zval(phpdbg_watch_memdump *dump) { /* fetch all changes between dump->page and dump->page + dump->size */ - phpdbg_btree_position pos = phpdbg_btree_find_between(&PHPDBG_G(watchpoint_tree), (zend_ulong)dump->page, (zend_ulong)dump->page + dump->size); - phpdbg_btree_result *result, *htresult; + phpdbg_btree_position pos = phpdbg_btree_find_between(&PHPDBG_G(watchpoint_tree), (zend_ulong) dump->page, (zend_ulong) dump->page + dump->size); + phpdbg_btree_result *result; int elementDiff; void *curTest; dump->reenable_writing = 0; while ((result = phpdbg_btree_next(&pos))) { - phpdbg_watchpoint_t *watch = result->ptr, *htwatch; - void *oldPtr = (char *)&dump->data + ((size_t)watch->addr.ptr - (size_t)dump->page); + phpdbg_watchpoint_t *watch = result->ptr; + void *oldPtr = (char *) &dump->data + ((size_t) watch->addr.ptr - (size_t) dump->page); char reenable = 1; + int removed = 0; - if ((size_t)watch->addr.ptr < (size_t)dump->page || (size_t)watch->addr.ptr + watch->size > (size_t)dump->page + dump->size) { + if ((size_t) watch->addr.ptr < (size_t) dump->page || (size_t) watch->addr.ptr + watch->size > (size_t) dump->page + dump->size) { continue; } - /* Test if the zval was separated and if necessary move the watchpoint */ - if (zend_hash_find(watch->parent_container, watch->name_in_parent, watch->name_in_parent_len + 1, &curTest) == SUCCESS) { - if (watch->type == WATCH_ON_HASHTABLE) { - switch (Z_TYPE_PP((zval **)curTest)) { - case IS_ARRAY: - curTest = (void *)Z_ARRVAL_PP((zval **)curTest); - break; - case IS_OBJECT: - curTest = (void *)Z_OBJPROP_PP((zval **)curTest); - break; + /* Test if the zval was separated or replaced and if necessary move the watchpoint */ + if ((watch->type == WATCH_ON_HASHTABLE || watch->type == WATCH_ON_ZVAL) && watch->parent_container) { + if ((curTest = zend_symtable_find(watch->parent_container, watch->name_in_parent))) { + while (Z_TYPE_P((zval *) curTest) == IS_INDIRECT) { + curTest = Z_INDIRECT_P((zval *) curTest); + } + + if (watch->type == WATCH_ON_HASHTABLE) { + switch (Z_TYPE_P((zval *) curTest)) { + case IS_ARRAY: + curTest = (void *) Z_ARRVAL_P((zval *) curTest); + break; + case IS_OBJECT: + curTest = (void *) Z_OBJPROP_P((zval *) curTest); + break; + } } - } else { - curTest = *(void **)curTest; - } - if (curTest != watch->addr.ptr) { - phpdbg_deactivate_watchpoint(watch TSRMLS_CC); - phpdbg_remove_watchpoint(watch TSRMLS_CC); - watch->addr.ptr = curTest; - phpdbg_store_watchpoint(watch TSRMLS_CC); - phpdbg_activate_watchpoint(watch TSRMLS_CC); + if (curTest != watch->addr.ptr) { + phpdbg_deactivate_watchpoint(watch); + phpdbg_remove_watchpoint(watch); + watch->addr.ptr = curTest; + phpdbg_store_watchpoint(watch); + phpdbg_activate_watchpoint(watch); - reenable = 0; + reenable = 0; + } + } else { + removed = 1; } } /* Show to the user what changed and delete watchpoint upon removal */ - if (memcmp(oldPtr, watch->addr.ptr, watch->size) != SUCCESS) { - if (PHPDBG_G(flags) & PHPDBG_SHOW_REFCOUNTS || (watch->type == WATCH_ON_ZVAL && memcmp(oldPtr, watch->addr.zv, sizeof(zvalue_value))) || (watch->type == WATCH_ON_HASHTABLE -#if ZEND_DEBUG - && !watch->addr.ht->inconsistent -#endif - && zend_hash_num_elements((HashTable *)oldPtr) != zend_hash_num_elements(watch->addr.ht))) { + { + zend_bool do_break = 0; + + switch (watch->type) { + case WATCH_ON_ZVAL: + do_break = memcmp(oldPtr, watch->addr.zv, sizeof(zend_value) + sizeof(uint32_t) /* value + typeinfo */) != 0; + if (!do_break) { + goto end; + } + break; + case WATCH_ON_HASHTABLE: + do_break = zend_hash_num_elements(HT_PTR_HT(oldPtr)) != zend_hash_num_elements(HT_WATCH_HT(watch)); + if (!do_break) { + goto end; + } + break; + case WATCH_ON_REFCOUNTED: + do_break = memcmp(oldPtr, watch->addr.ref, sizeof(uint32_t) /* no zend_refcounted metadata info */) != 0; + if (!do_break) { + goto end; + } + if (!(PHPDBG_G(flags) & PHPDBG_SHOW_REFCOUNTS)) { + do_break = 0; + } + break; + } + + if (!(watch->flags & PHPDBG_WATCH_NORMAL)) { + do_break = 0; + } + + if (do_break) { PHPDBG_G(watchpoint_hit) = 1; - phpdbg_notice("Breaking on watchpoint %s", watch->str); + phpdbg_notice("watchhit", "variable=\"%s\"", "Breaking on watchpoint %.*s", (int) ZSTR_LEN(watch->str), ZSTR_VAL(watch->str)); + phpdbg_xml("<watchdata %r>"); } switch (watch->type) { case WATCH_ON_ZVAL: { - int removed = ((zval *)oldPtr)->refcount__gc != watch->addr.zv->refcount__gc && !zend_symtable_exists(watch->parent_container, watch->name_in_parent, watch->name_in_parent_len + 1); - int show_value = memcmp(oldPtr, watch->addr.zv, sizeof(zvalue_value)); - int show_ref = ((zval *)oldPtr)->refcount__gc != watch->addr.zv->refcount__gc || ((zval *)oldPtr)->is_ref__gc != watch->addr.zv->is_ref__gc; - - if (removed || show_value) { - phpdbg_write("Old value: "); - if ((Z_TYPE_P((zval *)oldPtr) == IS_ARRAY || Z_TYPE_P((zval *)oldPtr) == IS_OBJECT) && removed) { - phpdbg_writeln("Value inaccessible, HashTable already destroyed"); + zend_bool show_value = memcmp(oldPtr, watch->addr.zv, sizeof(zend_value) + sizeof(uint32_t) /* no metadata info */) != 0; + + if ((watch->flags & PHPDBG_WATCH_NORMAL) && (removed || show_value)) { +/* TODO: Merge with refcounting watches, store if watched ref value is to be dropped etc. [for example: manually increment refcount transparently for displaying and drop it if it decrements to 1] */ + if (Z_REFCOUNTED_P((zval *) oldPtr)) { + phpdbg_writeln("watchvalue", "type=\"old\" inaccessible=\"inaccessible\"", "Old value inaccessible or destroyed"); } else { - zend_print_flat_zval_r((zval *)oldPtr TSRMLS_CC); - phpdbg_writeln(""); + phpdbg_out("Old value: "); + phpdbg_xml("<watchvalue %r type=\"old\">"); + zend_print_flat_zval_r((zval *) oldPtr); + phpdbg_xml("</watchvalue>"); + phpdbg_out("\n"); } } - if (PHPDBG_G(flags) & PHPDBG_SHOW_REFCOUNTS && (removed || show_ref)) { - phpdbg_writeln("Old refcount: %d; Old is_ref: %d", ((zval *)oldPtr)->refcount__gc, ((zval *)oldPtr)->is_ref__gc); - } /* check if zval was removed */ if (removed) { - phpdbg_notice("Watchpoint %s was unset, removing watchpoint", watch->str); - zend_hash_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); + if (watch->flags & PHPDBG_WATCH_NORMAL) { + phpdbg_notice("watchdelete", "variable=\"%.*s\"", "Watchpoint %.*s was unset, removing watchpoint", (int) ZSTR_LEN(watch->str), ZSTR_VAL(watch->str)); + } + zend_hash_del(&PHPDBG_G(watchpoints), watch->str); reenable = 0; - if (Z_TYPE_P((zval *)oldPtr) == IS_ARRAY || Z_TYPE_P((zval *)oldPtr) == IS_OBJECT) { - goto remove_ht_watch; + if (Z_REFCOUNTED_P((zval *) oldPtr)) { + phpdbg_remove_watch_collision(watch); } - break; } - if (show_value) { - phpdbg_write("New value: "); - zend_print_flat_zval_r(watch->addr.zv TSRMLS_CC); - phpdbg_writeln(""); - } - if (PHPDBG_G(flags) & PHPDBG_SHOW_REFCOUNTS && show_ref) { - phpdbg_writeln("New refcount: %d; New is_ref: %d", watch->addr.zv->refcount__gc, watch->addr.zv->is_ref__gc); + if ((watch->flags & PHPDBG_WATCH_NORMAL) && show_value) { + phpdbg_out("New value%s: ", Z_ISREF_P(watch->addr.zv) ? " (reference)" : ""); + phpdbg_xml("<watchvalue %r%s type=\"new\">", Z_ISREF_P(watch->addr.zv) ? " reference=\"reference\"" : ""); + zend_print_flat_zval_r(watch->addr.zv); + phpdbg_xml("</watchvalue>"); + phpdbg_out("\n"); } - if ((Z_TYPE_P(watch->addr.zv) == IS_ARRAY && Z_ARRVAL_P(watch->addr.zv) != Z_ARRVAL_P((zval *)oldPtr)) || (Z_TYPE_P(watch->addr.zv) != IS_OBJECT && Z_OBJ_HANDLE_P(watch->addr.zv) == Z_OBJ_HANDLE_P((zval *)oldPtr))) { - /* add new watchpoints if necessary */ - if (watch->flags & PHPDBG_WATCH_RECURSIVE) { - phpdbg_create_recursive_watchpoint(watch TSRMLS_CC); + /* add new watchpoints if necessary */ + if (Z_PTR_P(watch->addr.zv) != Z_PTR_P((zval *) oldPtr) || Z_TYPE_P(watch->addr.zv) != Z_TYPE_P((zval *) oldPtr)) { + if (Z_REFCOUNTED_P((zval *) oldPtr)) { + zval *new_zv = watch->addr.zv; + watch->addr.ptr = oldPtr; + phpdbg_remove_watch_collision(watch); + watch->addr.zv = new_zv; + } + if (Z_REFCOUNTED_P(watch->addr.zv)) { + if ((watch->flags & PHPDBG_WATCH_NORMAL) && (PHPDBG_G(flags) & PHPDBG_SHOW_REFCOUNTS)) { + phpdbg_writeln("watchrefcount", "type=\"new\" refcount=\"%d\"", "New refcount: %d", Z_REFCOUNT_P(watch->addr.zv)); + } + if (watch->flags & PHPDBG_WATCH_RECURSIVE) { + phpdbg_create_recursive_watchpoint(watch); + } else if (Z_ISREF_P(watch->addr.zv)) { + phpdbg_create_reference_watch(watch); + } } - } - - if ((Z_TYPE_P((zval *)oldPtr) != IS_ARRAY || Z_ARRVAL_P(watch->addr.zv) == Z_ARRVAL_P((zval *)oldPtr)) && (Z_TYPE_P((zval *)oldPtr) != IS_OBJECT || Z_OBJ_HANDLE_P(watch->addr.zv) == Z_OBJ_HANDLE_P((zval *)oldPtr))) { - break; - } - -remove_ht_watch: - if ((htresult = phpdbg_btree_find(&PHPDBG_G(watchpoint_tree), (zend_ulong)Z_ARRVAL_P((zval *)oldPtr)))) { - htwatch = htresult->ptr; - zend_hash_del(&PHPDBG_G(watchpoints), htwatch->str, htwatch->str_len); } break; } case WATCH_ON_HASHTABLE: - -#if ZEND_DEBUG - if (watch->addr.ht->inconsistent) { - phpdbg_notice("Watchpoint %s was unset, removing watchpoint", watch->str); - zend_hash_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); - - reenable = 0; - - break; - } -#endif - - elementDiff = zend_hash_num_elements((HashTable *)oldPtr) - zend_hash_num_elements(watch->addr.ht); - if (elementDiff) { + /* We should be safely able to assume the HashTable to be consistent (inconsistent HashTables should have been caught by phpdbg_watch_efree() */ + elementDiff = zend_hash_num_elements(HT_PTR_HT(oldPtr)) - zend_hash_num_elements(HT_WATCH_HT(watch)); + if ((watch->flags & PHPDBG_WATCH_NORMAL) && elementDiff) { if (elementDiff > 0) { - phpdbg_writeln("%d elements were removed from the array", elementDiff); + phpdbg_writeln("watchsize", "removed=\"%d\"", "%d elements were removed from the array", elementDiff); } else { - phpdbg_writeln("%d elements were added to the array", -elementDiff); - - /* add new watchpoints if necessary */ - if (watch->flags & PHPDBG_WATCH_RECURSIVE) { - phpdbg_create_recursive_watchpoint(watch TSRMLS_CC); - } + phpdbg_writeln("watchsize", "added=\"%d\"", "%d elements were added to the array", -elementDiff); } } - if (((HashTable *)oldPtr)->pInternalPointer != watch->addr.ht->pInternalPointer) { - phpdbg_writeln("Internal pointer of array was changed"); + /* add new watchpoints if necessary */ + if (watch->flags & PHPDBG_WATCH_RECURSIVE) { + phpdbg_create_recursive_ht_watch(watch); + } + if ((watch->flags & PHPDBG_WATCH_NORMAL) && HT_WATCH_HT(watch)->nInternalPointer != HT_PTR_HT(oldPtr)->nInternalPointer) { + phpdbg_writeln("watcharrayptr", "", "Internal pointer of array was changed"); } break; + case WATCH_ON_REFCOUNTED: { + if ((watch->flags & PHPDBG_WATCH_NORMAL) && (PHPDBG_G(flags) & PHPDBG_SHOW_REFCOUNTS)) { + phpdbg_writeln("watchrefcount", "type=\"old\" refcount=\"%d\"", "Old refcount: %d", GC_REFCOUNT((zend_refcounted *) oldPtr)); + phpdbg_writeln("watchrefcount", "type=\"new\" refcount=\"%d\"", "New refcount: %d", GC_REFCOUNT(watch->addr.ref)); + } + break; + } } - } + + if (do_break) { + phpdbg_xml("</watchdata>"); + } + } end: dump->reenable_writing = dump->reenable_writing | reenable; } } -int phpdbg_print_changed_zvals(TSRMLS_D) { +int phpdbg_print_changed_zvals(void) { zend_llist_position pos; phpdbg_watch_memdump **dump; int ret; @@ -746,44 +1104,63 @@ int phpdbg_print_changed_zvals(TSRMLS_D) { return FAILURE; } - dump = (phpdbg_watch_memdump **)zend_llist_get_last_ex(&PHPDBG_G(watchlist_mem), &pos); + dump = (phpdbg_watch_memdump **) zend_llist_get_last_ex(&PHPDBG_G(watchlist_mem), &pos); do { - phpdbg_print_changed_zval(*dump TSRMLS_CC); - } while ((dump = (phpdbg_watch_memdump **)zend_llist_get_prev_ex(&PHPDBG_G(watchlist_mem), &pos))); + phpdbg_print_changed_zval(*dump); + } while ((dump = (phpdbg_watch_memdump **) zend_llist_get_prev_ex(&PHPDBG_G(watchlist_mem), &pos))); zend_llist_clean(&PHPDBG_G(watchlist_mem)); - ret = PHPDBG_G(watchpoint_hit)?SUCCESS:FAILURE; + ret = PHPDBG_G(watchpoint_hit) ? SUCCESS : FAILURE; PHPDBG_G(watchpoint_hit) = 0; return ret; } -void phpdbg_list_watchpoints(TSRMLS_D) { - HashPosition position; - phpdbg_watchpoint_t **watch; +void phpdbg_list_watchpoints(void) { + phpdbg_watchpoint_t *watch; + + phpdbg_xml("<watchlist %r>"); - for (zend_hash_internal_pointer_reset_ex(&PHPDBG_G(watchpoints), &position); - zend_hash_get_current_data_ex(&PHPDBG_G(watchpoints), (void**) &watch, &position) == SUCCESS; - zend_hash_move_forward_ex(&PHPDBG_G(watchpoints), &position)) { - phpdbg_writeln("%.*s", (int)(*watch)->str_len, (*watch)->str); - } + ZEND_HASH_FOREACH_PTR(&PHPDBG_G(watchpoints), watch) { + if (watch->flags & PHPDBG_WATCH_NORMAL) { + phpdbg_writeln("watchvariable", "variable=\"%.*s\" on=\"%s\" type=\"%s\"", "%.*s (%s, %s)", (int) ZSTR_LEN(watch->str), ZSTR_VAL(watch->str), watch->type == WATCH_ON_HASHTABLE ? "array" : watch->type == WATCH_ON_REFCOUNTED ? "refcount" : "variable", watch->flags == PHPDBG_WATCH_RECURSIVE ? "recursive" : "simple"); + } + } ZEND_HASH_FOREACH_END(); + + phpdbg_xml("</watchlist>"); } void phpdbg_watch_efree(void *ptr) { phpdbg_btree_result *result; - TSRMLS_FETCH(); - result = phpdbg_btree_find_closest(&PHPDBG_G(watchpoint_tree), (zend_ulong)ptr); + result = phpdbg_btree_find_closest(&PHPDBG_G(watchpoint_tree), (zend_ulong) ptr); if (result) { phpdbg_watchpoint_t *watch = result->ptr; - if ((size_t)watch->addr.ptr + watch->size > (size_t)ptr) { - zend_hash_del(&PHPDBG_G(watchpoints), watch->str, watch->str_len); + if ((size_t) watch->addr.ptr + watch->size > (size_t) ptr) { + if (watch->type == WATCH_ON_REFCOUNTED) { + /* remove watchpoint here from btree, zval watchpoint will remove it via remove_watch_collison */ + phpdbg_deactivate_watchpoint(watch); + phpdbg_remove_watchpoint(watch); + } else { + if (watch->type == WATCH_ON_ZVAL) { + phpdbg_remove_watch_collision(watch); + } + if (watch->type == WATCH_ON_HASHTABLE && (watch->flags & PHPDBG_WATCH_SIMPLE)) { + /* when a HashTable is freed, we can safely assume the other zvals all were dtor'ed */ + phpdbg_notice("watchdelete", "variable=\"%.*s\" recursive=\"%s\"", "Array %.*s was removed, removing watchpoint%s", (int) ZSTR_LEN(watch->str), ZSTR_VAL(watch->str), (watch->flags & PHPDBG_WATCH_RECURSIVE) ? " recursively" : ""); + } + if (watch->type == WATCH_ON_HASHTABLE || watch->parent == NULL || watch->parent->type != WATCH_ON_ZVAL) { /* no references */ + zend_hash_del(&PHPDBG_G(watchpoints), watch->str); + } + } } } - PHPDBG_G(original_free_function)(ptr); + if (PHPDBG_G(original_free_function)) { + PHPDBG_G(original_free_function)(ptr); + } } diff --git a/sapi/phpdbg/phpdbg_watch.h b/sapi/phpdbg/phpdbg_watch.h index 4b83c24cf7..82c925e011 100644 --- a/sapi/phpdbg/phpdbg_watch.h +++ b/sapi/phpdbg/phpdbg_watch.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -21,11 +21,10 @@ #ifndef PHPDBG_WATCH_H #define PHPDBG_WATCH_H -#include "TSRM.h" #include "phpdbg_cmd.h" #ifdef _WIN32 -# include "phpdbg_win.h" +# include "phpdbg_win.h" #endif #define PHPDBG_WATCH(name) PHPDBG_COMMAND(watch_##name) @@ -37,64 +36,75 @@ PHPDBG_WATCH(array); PHPDBG_WATCH(delete); PHPDBG_WATCH(recursive); -/** - * Commands - */ - -static const phpdbg_command_t phpdbg_watch_commands[] = { - PHPDBG_COMMAND_D_EX(array, "create watchpoint on an array", 'a', watch_array, NULL, "s"), - PHPDBG_COMMAND_D_EX(delete, "delete watchpoint", 'd', watch_delete, NULL, "s"), - PHPDBG_COMMAND_D_EX(recursive, "create recursive watchpoints", 'r', watch_recursive, NULL, "s"), - PHPDBG_END_COMMAND -}; +extern const phpdbg_command_t phpdbg_watch_commands[]; /* Watchpoint functions/typedefs */ +/* References are managed through their parent zval *, being a simple WATCH_ON_ZVAL and eventually WATCH_ON_REFCOUNTED */ typedef enum { WATCH_ON_ZVAL, WATCH_ON_HASHTABLE, + WATCH_ON_REFCOUNTED, } phpdbg_watchtype; -#define PHPDBG_WATCH_SIMPLE 0x0 -#define PHPDBG_WATCH_RECURSIVE 0x1 +#define PHPDBG_WATCH_SIMPLE 0x01 +#define PHPDBG_WATCH_RECURSIVE 0x02 +#define PHPDBG_WATCH_ARRAY 0x04 +#define PHPDBG_WATCH_OBJECT 0x08 +#define PHPDBG_WATCH_NORMAL (PHPDBG_WATCH_SIMPLE | PHPDBG_WATCH_RECURSIVE) +#define PHPDBG_WATCH_IMPLICIT 0x10 + +#define PHPDBG_DESTRUCTED_ZVAL 0x80 typedef struct _phpdbg_watchpoint_t phpdbg_watchpoint_t; struct _phpdbg_watchpoint_t { - phpdbg_watchpoint_t *parent; - HashTable *parent_container; - char *name_in_parent; - size_t name_in_parent_len; - char *str; - size_t str_len; union { zval *zv; - HashTable *ht; + zend_refcounted *ref; void *ptr; } addr; size_t size; phpdbg_watchtype type; char flags; + unsigned int implicit_ht_count; + phpdbg_watchpoint_t *parent; + phpdbg_watchpoint_t *reference; + HashTable *parent_container; + zend_string *name_in_parent; + zend_string *str; }; -void phpdbg_setup_watchpoints(TSRMLS_D); +typedef struct { + phpdbg_watchpoint_t *watch; + unsigned int refs; + HashTable watches; + HashTable implicit_watches; +} phpdbg_watch_collision; + +typedef struct { + dtor_func_t dtor; + HashTable watches; +} phpdbg_watch_ht_info; + +void phpdbg_setup_watchpoints(void); #ifndef _WIN32 -int phpdbg_watchpoint_segfault_handler(siginfo_t *info, void *context TSRMLS_DC); +int phpdbg_watchpoint_segfault_handler(siginfo_t *info, void *context); #else -int phpdbg_watchpoint_segfault_handler(void *addr TSRMLS_DC); +int phpdbg_watchpoint_segfault_handler(void *addr); #endif void phpdbg_create_addr_watchpoint(void *addr, size_t size, phpdbg_watchpoint_t *watch); void phpdbg_create_zval_watchpoint(zval *zv, phpdbg_watchpoint_t *watch); -int phpdbg_delete_var_watchpoint(char *input, size_t len TSRMLS_DC); -int phpdbg_create_var_watchpoint(char *input, size_t len TSRMLS_DC); +int phpdbg_delete_var_watchpoint(char *input, size_t len); +int phpdbg_create_var_watchpoint(char *input, size_t len); -int phpdbg_print_changed_zvals(TSRMLS_D); +int phpdbg_print_changed_zvals(void); -void phpdbg_list_watchpoints(TSRMLS_D); +void phpdbg_list_watchpoints(void); void phpdbg_watch_efree(void *ptr); @@ -102,11 +112,11 @@ void phpdbg_watch_efree(void *ptr); static long phpdbg_pagesize; static zend_always_inline void *phpdbg_get_page_boundary(void *addr) { - return (void *)((size_t)addr & ~(phpdbg_pagesize - 1)); + return (void *) ((size_t) addr & ~(phpdbg_pagesize - 1)); } static zend_always_inline size_t phpdbg_get_total_page_size(void *addr, size_t size) { - return (size_t)phpdbg_get_page_boundary((void *)((size_t)addr + size - 1)) - (size_t)phpdbg_get_page_boundary(addr) + phpdbg_pagesize; + return (size_t) phpdbg_get_page_boundary((void *) ((size_t) addr + size - 1)) - (size_t) phpdbg_get_page_boundary(addr) + phpdbg_pagesize; } #endif diff --git a/sapi/phpdbg/phpdbg_webdata_transfer.c b/sapi/phpdbg/phpdbg_webdata_transfer.c new file mode 100644 index 0000000000..1805519a75 --- /dev/null +++ b/sapi/phpdbg/phpdbg_webdata_transfer.c @@ -0,0 +1,175 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2016 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: Bob Weinand <bwoebi@php.net> | + +----------------------------------------------------------------------+ +*/ + +#include "phpdbg_webdata_transfer.h" +#include "ext/standard/php_var.h" + +static int phpdbg_is_auto_global(char *name, int len) { + int ret; + zend_string *str = zend_string_init(name, len, 0); + ret = zend_is_auto_global(str); + efree(str); + return ret; +} + +PHPDBG_API void phpdbg_webdata_compress(char **msg, int *len) { + zval array; + HashTable *ht; + zval zv[9] = {{{0}}}; + + array_init(&array); + ht = Z_ARRVAL(array); + + /* fetch superglobals */ + { + phpdbg_is_auto_global(ZEND_STRL("GLOBALS")); + /* might be JIT */ + phpdbg_is_auto_global(ZEND_STRL("_ENV")); + phpdbg_is_auto_global(ZEND_STRL("_SERVER")); + phpdbg_is_auto_global(ZEND_STRL("_REQUEST")); + array_init(&zv[1]); + zend_hash_copy(Z_ARRVAL(zv[1]), &EG(symbol_table), NULL); + Z_ARRVAL(zv[1])->pDestructor = NULL; /* we're operating on a copy! Don't double free zvals */ + zend_hash_str_del(Z_ARRVAL(zv[1]), ZEND_STRL("GLOBALS")); /* do not use the reference to itself in json */ + zend_hash_str_add(ht, ZEND_STRL("GLOBALS"), &zv[1]); + } + + /* save php://input */ + { + php_stream *stream; + zend_string *str; + + stream = php_stream_temp_create_ex(TEMP_STREAM_DEFAULT, SAPI_POST_BLOCK_SIZE, PG(upload_tmp_dir)); + if ((str = php_stream_copy_to_mem(stream, PHP_STREAM_COPY_ALL, 0))) { + ZVAL_STR(&zv[2], str); + } else { + ZVAL_EMPTY_STRING(&zv[2]); + } + Z_SET_REFCOUNT(zv[2], 1); + zend_hash_str_add(ht, ZEND_STRL("input"), &zv[2]); + } + + /* change sapi name */ + { + if (sapi_module.name) { + ZVAL_STRING(&zv[6], sapi_module.name); + } else { + Z_TYPE_INFO(zv[6]) = IS_NULL; + } + zend_hash_str_add(ht, ZEND_STRL("sapi_name"), &zv[6]); + Z_SET_REFCOUNT(zv[6], 1); + } + + /* handle modules / extensions */ + { + zend_module_entry *module; + zend_extension *extension; + zend_llist_position pos; + + array_init(&zv[7]); + ZEND_HASH_FOREACH_PTR(&module_registry, module) { + zval *value = ecalloc(sizeof(zval), 1); + ZVAL_STRING(value, module->name); + zend_hash_next_index_insert(Z_ARRVAL(zv[7]), value); + } ZEND_HASH_FOREACH_END(); + zend_hash_str_add(ht, ZEND_STRL("modules"), &zv[7]); + + array_init(&zv[8]); + extension = (zend_extension *) zend_llist_get_first_ex(&zend_extensions, &pos); + while (extension) { + zval *value = ecalloc(sizeof(zval), 1); + ZVAL_STRING(value, extension->name); + zend_hash_next_index_insert(Z_ARRVAL(zv[8]), value); + extension = (zend_extension *) zend_llist_get_next_ex(&zend_extensions, &pos); + } + zend_hash_str_add(ht, ZEND_STRL("extensions"), &zv[8]); + } + + /* switch cwd */ + if (SG(options) & SAPI_OPTION_NO_CHDIR) { + char *ret = NULL; + char path[MAXPATHLEN]; + +#if HAVE_GETCWD + ret = VCWD_GETCWD(path, MAXPATHLEN); +#elif HAVE_GETWD + ret = VCWD_GETWD(path); +#endif + if (ret) { + ZVAL_STRING(&zv[5], path); + Z_SET_REFCOUNT(zv[5], 1); + zend_hash_str_add(ht, ZEND_STRL("cwd"), &zv[5]); + } + } + + /* get system ini entries */ + { + zend_ini_entry *ini_entry; + + array_init(&zv[3]); + ZEND_HASH_FOREACH_PTR(EG(ini_directives), ini_entry) { + zval *value = ecalloc(sizeof(zval), 1); + if (ini_entry->modified) { + if (!ini_entry->orig_value) { + efree(value); + continue; + } + ZVAL_STR(value, ini_entry->orig_value); + } else { + if (!ini_entry->value) { + efree(value); + continue; + } + ZVAL_STR(value, ini_entry->value); + } + zend_hash_add(Z_ARRVAL(zv[3]), ini_entry->name, value); + } ZEND_HASH_FOREACH_END(); + zend_hash_str_add(ht, ZEND_STRL("systemini"), &zv[3]); + } + + /* get perdir ini entries */ + if (EG(modified_ini_directives)) { + zend_ini_entry *ini_entry; + + array_init(&zv[4]); + ZEND_HASH_FOREACH_PTR(EG(ini_directives), ini_entry) { + zval *value = ecalloc(sizeof(zval), 1); + if (!ini_entry->value) { + efree(value); + continue; + } + ZVAL_STR(value, ini_entry->value); + zend_hash_add(Z_ARRVAL(zv[4]), ini_entry->name, value); + } ZEND_HASH_FOREACH_END(); + zend_hash_str_add(ht, ZEND_STRL("userini"), &zv[4]); + } + + /* encode data */ + { + php_serialize_data_t var_hash; + smart_str buf = {0}; + + PHP_VAR_SERIALIZE_INIT(var_hash); + php_var_serialize(&buf, &array, &var_hash); + PHP_VAR_SERIALIZE_DESTROY(var_hash); + *msg = ZSTR_VAL(buf.s); + *len = ZSTR_LEN(buf.s); + } + + zval_dtor(&array); +} diff --git a/sapi/phttpd/php_phttpd.h b/sapi/phpdbg/phpdbg_webdata_transfer.h index 52cd01a62c..df205251a6 100644 --- a/sapi/phttpd/php_phttpd.h +++ b/sapi/phpdbg/phpdbg_webdata_transfer.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -12,13 +12,16 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: Thies C. Arntzen <thies@thieso.net> | + | Authors: Bob Weinand <bwoebi@php.net> | +----------------------------------------------------------------------+ */ -#ifndef PHP_PHTTPD_H -#define PHP_PHTTPD_H +#ifndef PHPDBG_WEBDATA_TRANSFER_H +#define PHPDBG_WEBDATA_TRANSFER_H -#include <phttpd.h> +#include "zend.h" +#include "phpdbg.h" -#endif +PHPDBG_API void phpdbg_webdata_compress(char **msg, int *len); + +#endif /* PHPDBG_WEBDATA_TRANSFER_H */ diff --git a/sapi/phpdbg/phpdbg_win.c b/sapi/phpdbg/phpdbg_win.c index a1cc580f81..4b4511b7a6 100644 --- a/sapi/phpdbg/phpdbg_win.c +++ b/sapi/phpdbg/phpdbg_win.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -31,9 +31,8 @@ int phpdbg_exception_handler_win32(EXCEPTION_POINTERS *xp) { CONTEXT *xc = xp->ContextRecord; if(xr->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) { - TSRMLS_FETCH(); - if (phpdbg_watchpoint_segfault_handler((void *)xr->ExceptionInformation[1] TSRMLS_CC) == SUCCESS) { + if (phpdbg_watchpoint_segfault_handler((void *)xr->ExceptionInformation[1]) == SUCCESS) { return EXCEPTION_CONTINUE_EXECUTION; } } diff --git a/sapi/phpdbg/phpdbg_win.h b/sapi/phpdbg/phpdbg_win.h index 5bb105f569..56892bab28 100644 --- a/sapi/phpdbg/phpdbg_win.h +++ b/sapi/phpdbg/phpdbg_win.h @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ @@ -34,4 +34,4 @@ void phpdbg_win_set_mm_heap(zend_mm_heap *heap); int phpdbg_exception_handler_win32(EXCEPTION_POINTERS *xp); -#endif
\ No newline at end of file +#endif diff --git a/sapi/phpdbg/tests/basic_run.phpt b/sapi/phpdbg/tests/basic_run.phpt new file mode 100644 index 0000000000..beb19b535a --- /dev/null +++ b/sapi/phpdbg/tests/basic_run.phpt @@ -0,0 +1,8 @@ +--TEST-- +Basic run +--PHPDBG-- +r +q +--EXPECTF-- +prompt> [Nothing to execute!] +prompt> diff --git a/sapi/phpdbg/tests/breakpoints_001.phpt b/sapi/phpdbg/tests/breakpoints_001.phpt new file mode 100644 index 0000000000..934f0d3554 --- /dev/null +++ b/sapi/phpdbg/tests/breakpoints_001.phpt @@ -0,0 +1,33 @@ +--TEST-- +Fundamental breakpoints functionality +--PHPDBG-- +b 3 +r +b 4 +c + +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Breakpoint #0 added at %s:3] +prompt> [Breakpoint #0 at %s:3, hits: 1] +>00003: echo 1; + 00004: echo 2; + 00005: echo 3; +prompt> [Breakpoint #1 added at %s:4] +prompt> 1 +[Breakpoint #1 at %s:4, hits: 1] +>00004: echo 2; + 00005: echo 3; + 00006: echo 4; +prompt> 234 +[Script ended normally] +prompt> +--FILE-- +<?php + +echo 1; +echo 2; +echo 3; +echo 4; + diff --git a/sapi/phpdbg/tests/breakpoints_002.phpt b/sapi/phpdbg/tests/breakpoints_002.phpt new file mode 100644 index 0000000000..18aaef1f36 --- /dev/null +++ b/sapi/phpdbg/tests/breakpoints_002.phpt @@ -0,0 +1,40 @@ +--TEST-- +Preserve breakpoints on restart +--PHPDBG-- +b breakpoints_002.php:4 +r +b 3 +r +y +c + +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Breakpoint #0 added at %s:4] +prompt> 1 +[Breakpoint #0 at %s:4, hits: 1] +>00004: echo 2; + 00005: echo 3; + 00006: echo 4; +prompt> [Breakpoint #1 added at %s:3] +prompt> Do you really want to restart execution? (type y or n): [Breakpoint #1 at %s:3, hits: 1] +>00003: echo 1; + 00004: echo 2; + 00005: echo 3; +prompt> 1 +[Breakpoint #0 at %s:4, hits: 1] +>00004: echo 2; + 00005: echo 3; + 00006: echo 4; +prompt> 234 +[Script ended normally] +prompt> +--FILE-- +<?php + +echo 1; +echo 2; +echo 3; +echo 4; + diff --git a/sapi/phpdbg/tests/breakpoints_003.phpt b/sapi/phpdbg/tests/breakpoints_003.phpt new file mode 100644 index 0000000000..8caa64632b --- /dev/null +++ b/sapi/phpdbg/tests/breakpoints_003.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test deleting breakpoints +--PHPDBG-- +b 4 +b del 0 +b 5 +r +b del 1 +r +y +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Breakpoint #0 added at %s:4] +prompt> [Deleted breakpoint #0] +prompt> [Breakpoint #1 added at %s:5] +prompt> 12 +[Breakpoint #1 at %s:5, hits: 1] +>00005: echo 3; + 00006: echo 4; + 00007: +prompt> [Deleted breakpoint #1] +prompt> Do you really want to restart execution? (type y or n): 1234 +[Script ended normally] +prompt> +--FILE-- +<?php + +echo 1; +echo 2; +echo 3; +echo 4; + diff --git a/sapi/phpdbg/tests/breakpoints_004.phpt b/sapi/phpdbg/tests/breakpoints_004.phpt new file mode 100644 index 0000000000..27ebd0bea2 --- /dev/null +++ b/sapi/phpdbg/tests/breakpoints_004.phpt @@ -0,0 +1,41 @@ +--TEST-- +Test opcode breakpoints +--PHPDBG-- +b ZEND_ECHO +r +c + + + +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Breakpoint #0 added at ZEND_ECHO] +prompt> [Breakpoint #0 in ZEND_ECHO at %s:3, hits: 1] +>00003: echo 1; + 00004: echo 2; + 00005: echo 3; +prompt> 1 +[Breakpoint #0 in ZEND_ECHO at %s:4, hits: 2] +>00004: echo 2; + 00005: echo 3; + 00006: echo 4; +prompt> 2 +[Breakpoint #0 in ZEND_ECHO at %s:5, hits: 3] +>00005: echo 3; + 00006: echo 4; + 00007: +prompt> 3 +[Breakpoint #0 in ZEND_ECHO at %s:6, hits: 4] +>00006: echo 4; + 00007: +prompt> 4 +[Script ended normally] +prompt> +--FILE-- +<?php + +echo 1; +echo 2; +echo 3; +echo 4; diff --git a/sapi/phpdbg/tests/breakpoints_005.phpt b/sapi/phpdbg/tests/breakpoints_005.phpt new file mode 100644 index 0000000000..653dab9fcc --- /dev/null +++ b/sapi/phpdbg/tests/breakpoints_005.phpt @@ -0,0 +1,28 @@ +--TEST-- +Test breakpoint into function context +--PHPDBG-- +b breakpoints_005.php:4 +r +ev $bar +c +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Breakpoint #0 added at %s:4] +prompt> [Breakpoint #0 at %s:4, hits: 1] +>00004: var_dump($bar); + 00005: } + 00006: +prompt> test +prompt> string(4) "test" +[Script ended normally] +prompt> +--FILE-- +<?php + +function foo($bar) { + var_dump($bar); +} + +foo("test"); + diff --git a/sapi/phpdbg/tests/breakpoints_006.phpt b/sapi/phpdbg/tests/breakpoints_006.phpt new file mode 100644 index 0000000000..fa6f0cdc5b --- /dev/null +++ b/sapi/phpdbg/tests/breakpoints_006.phpt @@ -0,0 +1,26 @@ +--TEST-- +Basic function breakpoints +--PHPDBG-- +b foo +r +c +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Breakpoint #0 added at foo] +prompt> [Breakpoint #0 in foo() at %s:4, hits: 1] +>00004: var_dump($bar); + 00005: } + 00006: +prompt> string(4) "test" +[Script ended normally] +prompt> +--FILE-- +<?php + +function foo($bar) { + var_dump($bar); +} + +foo("test"); + diff --git a/sapi/phpdbg/tests/breakpoints_007.phpt b/sapi/phpdbg/tests/breakpoints_007.phpt new file mode 100644 index 0000000000..f921c257c5 --- /dev/null +++ b/sapi/phpdbg/tests/breakpoints_007.phpt @@ -0,0 +1,25 @@ +--TEST-- +Basic method breakpoints +--PHPDBG-- +b bar::foo +r +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Breakpoint #0 added at bar::foo] +prompt> [Breakpoint #0 in bar::foo() at %s:5, hits: 1] +>00005: var_dump($bar); + 00006: } + 00007: } +prompt> +--FILE-- +<?php + +class bar { + function foo($bar) { + var_dump($bar); + } +} + +(new bar)->foo("test"); + diff --git a/sapi/phpdbg/tests/breakpoints_008.phpt b/sapi/phpdbg/tests/breakpoints_008.phpt new file mode 100644 index 0000000000..cbe5042c2b --- /dev/null +++ b/sapi/phpdbg/tests/breakpoints_008.phpt @@ -0,0 +1,34 @@ +--TEST-- +Test namespaced and non-lowercase breakpoint names +--PHPDBG-- +b foo\bar::foo +b \Foo\Bar::Foo +r +c +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Breakpoint #0 added at foo\bar::foo] +prompt> [Breakpoint exists at Foo\Bar::Foo] +prompt> [Breakpoint #0 in foo\bar::foo() at %s:6, hits: 1] +>00006: var_dump($bar); + 00007: } + 00008: } +prompt> string(4) "test" +[Script ended normally] +prompt> +--FILE-- +<?php + +namespace Foo { + class Bar { + function Foo($bar) { + var_dump($bar); + } + } +} + +namespace { + (new \Foo\Bar)->Foo("test"); +} + diff --git a/sapi/phpdbg/tests/clean_001.phpt b/sapi/phpdbg/tests/clean_001.phpt new file mode 100644 index 0000000000..0500850448 --- /dev/null +++ b/sapi/phpdbg/tests/clean_001.phpt @@ -0,0 +1,60 @@ +--TEST-- +Cleaning must preserve breakpoints +--INI-- +opcache.enable_cli=0 +--PHPDBG-- +b 4 +b foo +r +c +clean +y +c +r +c + +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Breakpoint #0 added at %s:4] +prompt> [Breakpoint #1 added at foo] +prompt> 1 +[Breakpoint #0 at %s:4, hits: 1] +>00004: echo 2; + 00005: echo 3; + 00006: foo(); +prompt> 23 +[Breakpoint #1 in foo() at %s:9, hits: 1] +>00009: echo 4; + 00010: } + 00011: +prompt> Do you really want to clean your current environment? (type y or n): Cleaning Execution Environment +Classes %d +Functions %d +Constants %d +Includes 0 +prompt> [Not running] +prompt> 1 +[Breakpoint #0 at %s:4, hits: 1] +>00004: echo 2; + 00005: echo 3; + 00006: foo(); +prompt> 23 +[Breakpoint #1 in foo() at %s:9, hits: 1] +>00009: echo 4; + 00010: } + 00011: +prompt> 4 +[Script ended normally] +prompt> +--FILE-- +<?php + +echo 1; +echo 2; +echo 3; +foo(); + +function foo() { + echo 4; +} diff --git a/sapi/phpdbg/tests/clear_001.phpt b/sapi/phpdbg/tests/clear_001.phpt new file mode 100644 index 0000000000..96d73990eb --- /dev/null +++ b/sapi/phpdbg/tests/clear_001.phpt @@ -0,0 +1,44 @@ +--TEST-- +Test clearing breakpoints +--INI-- +opcache.enable_cli=0 +--PHPDBG-- +b 4 +b foo +r +clear +c +i b +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Breakpoint #0 added at %s:4] +prompt> [Breakpoint #1 added at foo] +prompt> 1 +[Breakpoint #0 at %s:4, hits: 1] +>00004: echo 2; + 00005: echo 3; + 00006: foo(); +prompt> Clearing Breakpoints +File 1 +Functions 1 +Methods 0 +Oplines 0 +File oplines 0 +Function oplines 0 +Method oplines 0 +Conditionals 0 +prompt> 234 +[Script ended normally] +prompt> prompt> +--FILE-- +<?php + +echo 1; +echo 2; +echo 3; +foo(); + +function foo() { + echo 4; +} diff --git a/sapi/phpdbg/tests/commands/0001_basic.test b/sapi/phpdbg/tests/commands/0001_basic.test deleted file mode 100644 index 08aa9ab664..0000000000 --- a/sapi/phpdbg/tests/commands/0001_basic.test +++ /dev/null @@ -1,8 +0,0 @@ -####################################################### -# name: basic -# purpose: check basic functionality of phpdbg console -# expect: TEST::EXACT -# options: -rr -####################################################### -# [Nothing to execute!] -####################################################### diff --git a/sapi/phpdbg/tests/commands/0002_set.test b/sapi/phpdbg/tests/commands/0002_set.test deleted file mode 100644 index 468ac6d9ea..0000000000 --- a/sapi/phpdbg/tests/commands/0002_set.test +++ /dev/null @@ -1,21 +0,0 @@ -################################################# -# name: set -# purpose: tests for set commands -# expect: TEST::CISTRING -# options: -rr -################################################# -# setting prompt color -# setting error color -# setting notice color -# Failed to find breakpoint #0 -# oplog disabled -# opened oplog test.log -# nothing -################################################# -set color prompt none -set color error none -set color notice none -set prompt promot> -set break 0 -set oplog -set oplog test.log diff --git a/sapi/phpdbg/tests/commands/0101_info.test b/sapi/phpdbg/tests/commands/0101_info.test deleted file mode 100644 index 397a45c992..0000000000 --- a/sapi/phpdbg/tests/commands/0101_info.test +++ /dev/null @@ -1,19 +0,0 @@ -################################################# -# name: info -# purpose: test info commands -# expect: TEST::FORMAT -# options: -rr -################################################# -#[User Classes (%d)] -#User Class test (3) -#|---- in phpdbginit code on line %d -################################################# -<: -class test { - public function testMethod(){} - private function testPrivateMethod(){} - protected function testProtectedMethod(){} -} -:> -info classes -q diff --git a/sapi/phpdbg/tests/commands/0102_print.test b/sapi/phpdbg/tests/commands/0102_print.test deleted file mode 100644 index de4acb7651..0000000000 --- a/sapi/phpdbg/tests/commands/0102_print.test +++ /dev/null @@ -1,28 +0,0 @@ -################################################# -# name: print -# purpose: test print commands -# expect: TEST::FORMAT -# options: -rr -################################################# -#[User Class: test] -#Methods (3): -#L%d-%d test::testMethod() %s -# L%d %s ZEND_RETURN C%d <unused> <unused> -# L%d-%d test::testPrivateMethod() %s -# L%d %s ZEND_RETURN C%d <unused> <unused> -# L%d-%d test::testProtectedMethod() %s -# L%d %s ZEND_RETURN C%d <unused> <unused> -#[User Method testMethod] -# L%d-%d test::testMethod() %s -# L%d %s ZEND_RETURN C%d <unused> <unused> -################################################# -<: -class test { - public function testMethod(){} - private function testPrivateMethod(){} - protected function testProtectedMethod(){} -} -:> -print class test -print method test::testMethod -q diff --git a/sapi/phpdbg/tests/commands/0103_register.test b/sapi/phpdbg/tests/commands/0103_register.test deleted file mode 100644 index 703a12f771..0000000000 --- a/sapi/phpdbg/tests/commands/0103_register.test +++ /dev/null @@ -1,28 +0,0 @@ -################################################# -# name: register -# purpose: test registration functions -# expect: TEST::FORMAT -# options: -rr -################################################# -#[Registered test_function] -#array(5) { -# [0]=> -# int(1) -# [1]=> -# int(2) -# [2]=> -# int(3) -# [3]=> -# int(4) -# [4]=> -# int(5) -#} -################################################# -<: -function test_function() { - var_dump(func_get_args()); -} -:> -R test_function -test_function 1 2 3 4 5 -q diff --git a/sapi/phpdbg/tests/commands/0104_clean.test b/sapi/phpdbg/tests/commands/0104_clean.test deleted file mode 100644 index c7a579be17..0000000000 --- a/sapi/phpdbg/tests/commands/0104_clean.test +++ /dev/null @@ -1,15 +0,0 @@ -################################################# -# name: clean -# purpose: test cleaning environment -# expect: TEST::FORMAT -# options: -rr -################################################# -#[Cleaning Execution Environment] -#Classes %d -#Functions %d -#Constants %d -#Includes %d -#[Nothing to execute!] -################################################# -clean -quit diff --git a/sapi/phpdbg/tests/commands/0105_clear.test b/sapi/phpdbg/tests/commands/0105_clear.test deleted file mode 100644 index b547b0d6ba..0000000000 --- a/sapi/phpdbg/tests/commands/0105_clear.test +++ /dev/null @@ -1,18 +0,0 @@ -################################################# -# name: clear -# purpose: test clearing breakpoints -# expect: TEST::FORMAT -# options: -rr -################################################# -#[Clearing Breakpoints] -#File%w%d -#Functions%w%d -#Methods%w%d -#Oplines%w%d -#File oplines%w%d -#Function oplines%w%d -#Method oplines%w%d -#Conditionals%w%d -################################################# -clear -quit diff --git a/sapi/phpdbg/tests/commands/0106_compile.test b/sapi/phpdbg/tests/commands/0106_compile.test deleted file mode 100644 index 7193600ea3..0000000000 --- a/sapi/phpdbg/tests/commands/0106_compile.test +++ /dev/null @@ -1,18 +0,0 @@ -################################################# -# name: compile -# purpose: test compiling code -# expect: TEST::FORMAT -# options: -rr -################################################# -#[Attempting compilation of %s] -#[Success] -#Hello World -################################################# -<: -define('OUT', - tempnam(null, "phpdbg")); -file_put_contents(OUT, "<?php echo \"Hello World\"; ?>"); -phpdbg_exec(OUT); -:> -run -quit diff --git a/sapi/phpdbg/tests/delimiter.phpt b/sapi/phpdbg/tests/delimiter.phpt new file mode 100644 index 0000000000..da5f681783 --- /dev/null +++ b/sapi/phpdbg/tests/delimiter.phpt @@ -0,0 +1,7 @@ +--TEST-- +Test # delimiter parsing and execution +--PHPDBG-- +ev 1 + 3 # ev 2 ** 3#q +--EXPECTF-- +prompt> 4 +8 diff --git a/sapi/phpdbg/tests/exceptions_001.phpt b/sapi/phpdbg/tests/exceptions_001.phpt new file mode 100644 index 0000000000..991ea1cc71 --- /dev/null +++ b/sapi/phpdbg/tests/exceptions_001.phpt @@ -0,0 +1,46 @@ +--TEST-- +Properly handle exceptions going to be uncaught +--PHPDBG-- +r +t +ev 1 + 2 +c +q +--EXPECTF-- +[Successful compilation of %s] +prompt> handle first +[Uncaught Error in %s on line 16: Call to undefined function foo()] +>00016: foo(); // Error + 00017: } catch (\Exception $e) { + 00018: var_dump($e); +prompt> frame #0: {closure}() at %s:16 +frame #1: {main} at %s:20 +prompt> 3 +prompt> [Uncaught Error in %s on line 16] +Error: Call to undefined function foo() in %s:16 +Stack trace: +#0 %s(20): {closure}() +#1 {main} +[Script ended normally] +prompt> +--FILE-- +<?php + +(function() { + try { + foo(); // Error + } catch (\Exception $e) { + var_dump($e); + } finally { + print "handle first\n"; + return "ok"; + } +})(); + +(function() { + try { + foo(); // Error + } catch (\Exception $e) { + var_dump($e); + } +})(); diff --git a/sapi/phpdbg/tests/exceptions_002.phpt b/sapi/phpdbg/tests/exceptions_002.phpt new file mode 100644 index 0000000000..f304cc25db --- /dev/null +++ b/sapi/phpdbg/tests/exceptions_002.phpt @@ -0,0 +1,51 @@ +--TEST-- +Test exceptions in eval during exception +--PHPDBG-- +r +ev next_error() +c + +q +--EXPECTF-- +[Successful compilation of %s] +prompt> handle first +[Uncaught Error in %s on line 16: Call to undefined function foo()] +>00016: foo(); // Error + 00017: } catch (\Exception $e) { + 00018: var_dump($e); +prompt> +Fatal error: Uncaught Error: Call to undefined function next_error() in eval()'d code:1 +Stack trace: +#0 %s(16): unknown() +#1 %s(20): {closure}() +#2 {main} + thrown in eval()'d code on line 1 +prompt> [Uncaught Error in %s on line 16] +Error: Call to undefined function foo() in %s:16 +Stack trace: +#0 %s(20): {closure}() +#1 {main} +[Script ended normally] +prompt> [The stack contains nothing !] +prompt> +--FILE-- +<?php + +(function() { + try { + foo(); // Error + } catch (\Exception $e) { + var_dump($e); + } finally { + print "handle first\n"; + return "ok"; + } +})(); + +(function() { + try { + foo(); // Error + } catch (\Exception $e) { + var_dump($e); + } +})(); diff --git a/sapi/phpdbg/tests/exceptions_003.phpt b/sapi/phpdbg/tests/exceptions_003.phpt new file mode 100644 index 0000000000..fffe7a9296 --- /dev/null +++ b/sapi/phpdbg/tests/exceptions_003.phpt @@ -0,0 +1,54 @@ +--TEST-- +Test breaks on HANDLE_EXCEPTION +--PHPDBG-- +b 5 +r +s + +s + + +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Breakpoint #0 added at %s:5] +prompt> [Breakpoint #0 at %s:5, hits: 1] +>00005: x(); + 00006: } finally { + 00007: print "ok\n"; +prompt> [L0 %s HANDLE_EXCEPTION %s] +>00005: x(); + 00006: } finally { + 00007: print "ok\n"; +prompt> [L7 %s ECHO "ok " %s] +>00007: print "ok\n"; + 00008: } + 00009: } catch (Error $e) { +prompt> ok +[L7 %s FAST_RET<TO_CATCH> ~%d J7 %s] +[L9 %s CATCH "Error" $e 1 %s] +>00005: x(); + 00006: } finally { + 00007: print "ok\n"; +prompt> [L10 %s ECHO "caught " %s] +>00010: print "caught\n"; + 00011: } + 00012: +prompt> caught +[L10 %s RETURN 1 %s] +[Script ended normally] +prompt> +--FILE-- +<?php + +try { + try { + x(); + } finally { + print "ok\n"; + } +} catch (Error $e) { + print "caught\n"; +} + +?> diff --git a/sapi/phpdbg/tests/finish_leave_001.phpt b/sapi/phpdbg/tests/finish_leave_001.phpt new file mode 100644 index 0000000000..774776c05f --- /dev/null +++ b/sapi/phpdbg/tests/finish_leave_001.phpt @@ -0,0 +1,41 @@ +--TEST-- +test finish and leave commands +--PHPDBG-- +b bar +b 5 +r +finish +leave +leave +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Breakpoint #0 added at bar] +prompt> [Breakpoint #1 added at %s:5] +prompt> [Breakpoint #0 in bar() at %s:9, hits: 1] +>00009: return "world"; + 00010: } + 00011: +prompt> [Breakpoint #1 at %s:5, hits: 1] +>00005: return ["hello", $other]; + 00006: } + 00007: +prompt> [Breaking for leave at %s:5] +>00005: return ["hello", $other]; + 00006: } + 00007: +prompt> [Already at the end of the function] +prompt> +--FILE-- +<?php +function foo() { + $other = bar(); + + return ["hello", $other]; +} + +function bar() { + return "world"; +} + +foo(); diff --git a/sapi/phpdbg/tests/generator_run.phpt b/sapi/phpdbg/tests/generator_run.phpt new file mode 100644 index 0000000000..798d77051e --- /dev/null +++ b/sapi/phpdbg/tests/generator_run.phpt @@ -0,0 +1,24 @@ +--TEST-- +Ensure proper saving of EX(opline) +--PHPDBG-- +r +q +--EXPECTF-- +[Successful compilation of %s] +prompt> caught Generator exception +[Script ended normally] +prompt> +--FILE-- +<?php + +function gen() { + try { + throw new Exception; + } catch(Exception $e) { + yield "caught Generator exception"; + } +} + +foreach (gen() as $v) { + print $v; +} diff --git a/sapi/phpdbg/tests/info_001.phpt b/sapi/phpdbg/tests/info_001.phpt new file mode 100644 index 0000000000..b988235757 --- /dev/null +++ b/sapi/phpdbg/tests/info_001.phpt @@ -0,0 +1,80 @@ +--TEST-- +Test basic info functionality +--INI-- +auto_globals_jit=0 +--PHPDBG-- +i classes +i funcs +b foo +r +i v +i g +i b +i d +i F +i e +i l +c +i v +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [User Classes (1)] +User Class Foo\Bar (2) +|---- in %s on line 4 +prompt> [User Functions (1)] +|-------- foo in %s on line 14 +prompt> [Breakpoint #0 added at foo] +prompt> string(4) "test" +[Breakpoint #0 in foo() at %s:15, hits: 1] +>00015: var_dump(strrev($baz)); + 00016: } + 00017: +prompt> [Variables in foo() (1)] +Address Refs Type Variable +%s 1 string $baz +string (4) "test" +prompt> [Superglobal variables (8)] +Address Refs Type Variable +%s 2 array $_GET +%s 2 array $_POST +%s 2 array $_COOKIE +%s 2 array $_SERVER +%s 2 array $_ENV +%s 1 array $_REQUEST +%s 2 array $_FILES +%s 1 array &$GLOBALS +prompt> ------------------------------------------------ +Function Breakpoints: +#0 foo +prompt> [User-defined constants (0)] +prompt> [Included files: 0] +prompt> [No error found!] +prompt> [Literal Constants in foo() (2)] +|-------- C0 -------> [var_dump] +|-------- C1 -------> [strrev] +prompt> string(4) "tset" +[Script ended normally] +prompt> [No active op array!] +prompt> +--FILE-- +<?php + +namespace Foo { + class Bar { + function Foo($bar) { + var_dump($bar); + } + + function baz() { } + } +} + +namespace { + function foo($baz) { + var_dump(strrev($baz)); + } + + (new \Foo\Bar)->Foo("test"); + foo("test"); +} diff --git a/sapi/phpdbg/tests/info_002.phpt b/sapi/phpdbg/tests/info_002.phpt new file mode 100644 index 0000000000..faeca0e430 --- /dev/null +++ b/sapi/phpdbg/tests/info_002.phpt @@ -0,0 +1,31 @@ +--TEST-- +info constants test +--PHPDBG-- +b 10 +r +i d +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Breakpoint #0 added at %s:10] +prompt> [Breakpoint #0 at %s:10, hits: 1] +>00010: print B; + 00011: +prompt> [User-defined constants (2)] +Address Refs Type Constant +%s 1 integer A +int (10) +%s 1 integer B +int (100) +prompt> +--FILE-- +<?php + +const A = 10; +const B = C::D * A; + +class C { + const D = 10; +} + +print B; diff --git a/sapi/phpdbg/tests/normal_exit.phpt b/sapi/phpdbg/tests/normal_exit.phpt new file mode 100644 index 0000000000..692614e98f --- /dev/null +++ b/sapi/phpdbg/tests/normal_exit.phpt @@ -0,0 +1,15 @@ +--TEST-- +A script with die() must end "normally" +--PHPDBG-- +r +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Script ended normally] +prompt> +--FILE-- +<?php + +(function($argv) { + die(); +})($argv); diff --git a/sapi/phpdbg/tests/phpdbg_break_next.phpt b/sapi/phpdbg/tests/phpdbg_break_next.phpt new file mode 100644 index 0000000000..37ee2e8282 --- /dev/null +++ b/sapi/phpdbg/tests/phpdbg_break_next.phpt @@ -0,0 +1,22 @@ +--TEST-- +Test phpdbg_break_next() function +--PHPDBG-- +r +c +q +--EXPECTF-- +[Successful compilation of %s] +prompt> A +[Breakpoint #0 added at %s] +[Breakpoint #0 in %s at %s:5, hits: 1] +>00005: echo 'B'; + 00006: +prompt> B +[Script ended normally] +prompt> +--FILE-- +<?php + +echo 'A'; +phpdbg_break_next(); +echo 'B'; diff --git a/sapi/phpdbg/tests/phpdbg_oplog_001.phpt b/sapi/phpdbg/tests/phpdbg_oplog_001.phpt new file mode 100644 index 0000000000..e4e558b9fa --- /dev/null +++ b/sapi/phpdbg/tests/phpdbg_oplog_001.phpt @@ -0,0 +1,58 @@ +--TEST-- +Test phpdbg_*_oplog() functions +--INI-- +opcache.enable_cli=0 +--PHPDBG-- +r +q +--EXPECTF-- +[Successful compilation of %s] +prompt> halloarray(2) { + ["%s"]=> + array(5) { + [13]=> + int(1) + [17]=> + int(2) + [18]=> + int(2) + [19]=> + int(3) + [21]=> + int(4) + } + ["A::b"]=> + array(3) { + [4]=> + int(1) + [5]=> + int(3) + [8]=> + int(2) + } +} +[Script ended normally] +prompt> +--FILE-- +<?php + +class A { + public function b($c = 1) { + if ($c == 1) { + // comment + } + } +} + +phpdbg_start_oplog(); + +echo "hallo"; + +// fcalls + +$a = new A(); +$a->b(); +$a->b('ha'); + +var_dump(phpdbg_end_oplog(["functions" => true])); + diff --git a/sapi/phpdbg/tests/phpdbg_oplog_002.phpt b/sapi/phpdbg/tests/phpdbg_oplog_002.phpt new file mode 100644 index 0000000000..b9ba905caa --- /dev/null +++ b/sapi/phpdbg/tests/phpdbg_oplog_002.phpt @@ -0,0 +1,16 @@ +--TEST-- +phpdbg_end_oplog() alone must not crash +--PHPDBG-- +r +q +--EXPECTF-- +[Successful compilation of %s] +prompt> +Warning: Can not end an oplog without starting it in %s on line 3 +NULL +[Script ended normally] +prompt> +--FILE-- +<?php + +var_dump(phpdbg_end_oplog()); diff --git a/sapi/phpdbg/tests/print_001.phpt b/sapi/phpdbg/tests/print_001.phpt new file mode 100644 index 0000000000..1f7a5ac0b9 --- /dev/null +++ b/sapi/phpdbg/tests/print_001.phpt @@ -0,0 +1,67 @@ +--TEST-- +Basic print functionality +--INI-- +opcache.enable_cli=0 +--PHPDBG-- +p foo +p class \Foo\bar +p +p e +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [User Function foo (8 ops)] +L14-16 foo() %s - %s + 8 ops + L14 #0 RECV 1 $baz + L15 #1 INIT_FCALL%s %d %s "var_dump" + L15 #2 INIT_FCALL%s %d %s "strrev" + L15 #3 SEND_VAR $baz 1 + L15 #4 DO_%cCALL @0 + L15 #5 SEND_VAR @0 1 + L15 #6 DO_%cCALL + L16 #7 RETURN null +prompt> [User Class: Foo\Bar (2 methods)] +L5-7 Foo\Bar::Foo() %s - %s + 5 ops + L5 #0 RECV 1 $bar + L6 #1 INIT_NS_FCALL_BY_NAME "Foo\\var_dump" + L6 #2 SEND_VAR_EX $bar 1 + L6 #3 DO_FCALL + L7 #4 RETURN null +L9-9 Foo\Bar::baz() %s - %s + 1 ops + L9 #0 RETURN null +prompt> [Not Executing!] +prompt> [Context %s (11 ops)] +L1-19 {main}() %s - %s + 11 ops + L4 #0 NOP + L14 #1 NOP + L18 #2 NEW "Foo\\Bar" @1 + L18 #3 DO_FCALL + L18 #4 INIT_METHOD_CALL @1 "Foo" + L18 #5 SEND_VAL_EX "test" 1 + L18 #6 DO_FCALL + L19 #7 INIT_FCALL%s %d %s "foo" + L19 #8 SEND_VAL "test" 1 + L19 #9 DO_FCALL + L19 #10 RETURN 1 +prompt> +--FILE-- +<?php + +namespace Foo { + class Bar { + function Foo($bar) { + var_dump($bar); + } + + function baz() { } + } +} + +namespace { + function foo($baz) { + var_dump(strrev($baz)); + } + + (new \Foo\Bar)->Foo("test"); + foo("test"); +} diff --git a/sapi/phpdbg/tests/print_002.phpt b/sapi/phpdbg/tests/print_002.phpt new file mode 100644 index 0000000000..3a824986c1 --- /dev/null +++ b/sapi/phpdbg/tests/print_002.phpt @@ -0,0 +1,51 @@ +--TEST-- +Relative print commands +--INI-- +opcache.enable_cli=0 +--PHPDBG-- +b foo +r +p +p o +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Breakpoint #0 added at foo] +prompt> string(4) "test" +[Breakpoint #0 in foo() at %s:15, hits: 1] +>00015: var_dump(strrev($baz)); + 00016: } + 00017: +prompt> [Stack in foo() (8 ops)] +L14-16 foo() %s - %s + 8 ops + L14 #0 RECV 1 $baz + L15 #1 INIT_FCALL%s %d %s "var_dump" + L15 #2 INIT_FCALL%s %d %s "strrev" + L15 #3 SEND_VAR $baz 1 + L15 #4 DO_%cCALL @0 + L15 #5 SEND_VAR @0 1 + L15 #6 DO_%cCALL + L16 #7 RETURN null +prompt> [L15 %s INIT_FCALL%s %d %s "var_dump" %s] +prompt> +--FILE-- +<?php + +namespace Foo { + class Bar { + function Foo($bar) { + var_dump($bar); + } + + function baz() { } + } +} + +namespace { + function foo($baz) { + var_dump(strrev($baz)); + } + + (new \Foo\Bar)->Foo("test"); + foo("test"); +} diff --git a/sapi/phpdbg/tests/run-tests.php b/sapi/phpdbg/tests/run-tests.php deleted file mode 100644 index 1cc31d815e..0000000000 --- a/sapi/phpdbg/tests/run-tests.php +++ /dev/null @@ -1,597 +0,0 @@ -<?php -namespace phpdbg\testing { - - /* - * Workaround ... - */ - if (!defined('DIR_SEP')) - define('DIR_SEP', '\\' . DIRECTORY_SEPARATOR); - - /** - * TestConfigurationExceptions are thrown - * when the configuration prohibits tests executing - * - * @package phpdbg - * @subpackage testing - */ - class TestConfigurationException extends \Exception { - - /** - * - * @param array Tests confguration - * @param message Exception message - * @param ... formatting parameters - */ - public function __construct() { - $argv = func_get_args(); - - if (count($argv)) { - - $this->config = array_shift($argv); - $this->message = vsprintf( - array_shift($argv), $argv); - } - } - } - - /** - * - * @package phpdbg - * @subpackage testing - */ - class TestsConfiguration implements \ArrayAccess { - - /** - * - * @param array basic configuration - * @param array argv - */ - public function __construct($config, $cmd) { - $this->options = $config; - while (($key = array_shift($cmd))) { - switch (substr($key, 0, 1)) { - case '-': switch(substr($key, 1, 1)) { - case '-': { - $arg = substr($key, 2); - if (($e=strpos($arg, '=')) !== false) { - $key = substr($arg, 0, $e); - $value = substr($arg, $e+1); - } else { - $key = $arg; - $value = array_shift($cmd); - } - - if (isset($key) && isset($value)) { - switch ($key) { - case 'phpdbg': - case 'width': - $this->options[$key] = $value; - break; - - default: { - if (isset($config[$key])) { - if (is_array($config[$key])) { - $this->options[$key][] = $value; - } else { - $this->options[$key] = array($config[$key], $value); - } - } else { - $this->options[$key] = $value; - } - } - } - - } - } break; - - default: - $this->flags[] = substr($key, 1); - } break; - } - } - - if (!is_executable($this->options['phpdbg'])) { - throw new TestConfigurationException( - $this->options, 'phpdbg could not be found at the specified path (%s)', $this->options['phpdbg']); - } else $this->options['phpdbg'] = realpath($this->options['phpdbg']); - - $this->options['width'] = (integer) $this->options['width']; - - /* display properly, all the time */ - if ($this->options['width'] < 50) { - $this->options['width'] = 50; - } - - /* calculate column widths */ - $this->options['lwidth'] = ceil($this->options['width'] / 3); - $this->options['rwidth'] = ceil($this->options['width'] - $this->options['lwidth']) - 5; - } - - public function hasFlag($flag) { - return in_array( - $flag, $this->flags); - } - - public function offsetExists($offset) { return isset($this->options[$offset]); } - public function offsetGet($offset) { return $this->options[$offset]; } - public function offsetUnset($offset) { unset($this->options[$offset]); } - public function offsetSet($offset, $data) { $this->options[$offset] = $data; } - - protected $options = array(); - protected $flags = array(); - } - - /** - * Tests is the console programming API for the test suite - * - * @package phpdbg - * @subpackage testing - */ - class Tests { - - /** - * Construct the console object - * - * @param array basic configuration - * @param array command line - */ - public function __construct(TestsConfiguration $config) { - $this->config = $config; - - if ($this->config->hasFlag('help') || - $this->config->hasFlag('h')) { - $this->showUsage(); - exit; - } - } - - /** - * Find valid paths as specified by configuration - * - */ - public function findPaths($in = null) { - $paths = array(); - $where = ($in != null) ? array($in) : $this->config['path']; - - foreach ($where as $path) { - if ($path) { - if (is_dir($path)) { - $paths[] = $path; - foreach (scandir($path) as $child) { - if ($child != '.' && $child != '..') { - $paths = array_merge( - $paths, $this->findPaths("$path/$child")); - } - } - } - } - } - - return $paths; - } - - /** - * - * @param string the path to log - */ - public function logPath($path) { - printf( - '%s [%s]%s', - str_repeat( - '-', $this->config['width'] - strlen($path)), - $path, PHP_EOL); - } - - /** - * - * @param string the path to log - */ - public function logPathStats($path) { - if (!isset($this->stats[$path])) { - return; - } - - $total = array_sum($this->stats[$path]); - - if ($total) { - @$this->totals[true] += $this->stats[$path][true]; - @$this->totals[false] += $this->stats[$path][false]; - - $stats = @sprintf( - "%d/%d %%%d", - $this->stats[$path][true], - $this->stats[$path][false], - (100 / $total) * $this->stats[$path][true]); - - printf( - '%s [%s]%s', - str_repeat( - ' ', $this->config['width'] - strlen($stats)), - $stats, PHP_EOL); - - printf("%s%s", str_repeat('-', $this->config['width']+3), PHP_EOL); - printf("%s", PHP_EOL); - } - } - - /** - * - */ - public function logStats() { - $total = array_sum($this->totals); - $stats = @sprintf( - "%d/%d %%%d", - $this->totals[true], - $this->totals[false], - (100 / $total) * $this->totals[true]); - printf( - '%s [%s]%s', - str_repeat( - ' ', $this->config['width'] - strlen($stats)), - $stats, PHP_EOL); - - } - - /** - * - */ - protected function showUsage() { - printf('usage: php %s [flags] [options]%s', $this->config['exec'], PHP_EOL); - printf('[options]:%s', PHP_EOL); - printf("\t--path\t\tadd a path to scan outside of tests directory%s", PHP_EOL); - printf("\t--width\t\tset line width%s", PHP_EOL); - printf("\t--options\toptions to pass to phpdbg%s", PHP_EOL); - printf("\t--phpdbg\tpath to phpdbg binary%s", PHP_EOL); - printf('[flags]:%s', PHP_EOL); - printf("\t-diff2stdout\t\twrite diff to stdout instead of files%s", PHP_EOL); - printf("\t-nodiff\t\tdo not write diffs on failure%s", PHP_EOL); - printf("\t-nolog\t\tdo not write logs on failure%s", PHP_EOL); - printf('[examples]:%s', PHP_EOL); - printf("\tphp %s --phpdbg=/usr/local/bin/phpdbg --path=/usr/src/phpdbg/tests --options -n%s", - $this->config['exec'], PHP_EOL); - - } - - /** - * Find valid tests at the specified path (assumed valid) - * - * @param string a valid path - */ - public function findTests($path) { - $tests = array(); - - foreach (scandir($path) as $file) { - if ($file == '.' || $file == '..') - continue; - - $test = sprintf('%s/%s', $path, $file); - - if (preg_match('~\.test$~', $test)) { - $tests[] = new Test($this->config, $test); - } - } - - return $tests; - } - - /** - * - * @param Test the test to log - */ - public function logTest($path, Test $test) { - @$this->stats[$path][($result=$test->getResult())]++; - - printf( - "%-{$this->config['lwidth']}s %-{$this->config['rwidth']}s [%s]%s", - $test->name, - $test->purpose, - $result ? "PASS" : "FAIL", - PHP_EOL); - - return $result; - } - - protected $config; - } - - class Test { - /* - * Expect exact line for line match - */ - const EXACT = 0x00000001; - - /* - * Expect strpos() !== false - */ - const STRING = 0x00000010; - - /* - * Expect stripos() !== false - */ - const CISTRING = 0x00000100; - - /* - * Formatted output - */ - const FORMAT = 0x00001000; - - /** - * Format specifiers - */ - private static $format = array( - 'search' => array( - '%e', - '%s', - '%S', - '%a', - '%A', - '%w', - '%i', - '%d', - '%x', - '%f', - '%c', - '%t', - '%T' - ), - 'replace' => array( - DIR_SEP, - '[^\r\n]+', - '[^\r\n]*', - '.+', - '.*', - '\s*', - '[+-]?\d+', - '\d+', - '[0-9a-fA-F]+', - '[+-]?\.?\d+\.?\d*(?:[Ee][+-]?\d+)?', - '.', - '\t', - '\t+' - ) - ); - - /** - * Constructs a new Test object given a specilized phpdbginit file - * - * @param array configuration - * @param string file - */ - public function __construct(TestsConfiguration $config, $file) { - if (($handle = fopen($file, 'r'))) { - while (($line = fgets($handle))) { - $trim = trim($line); - - switch (substr($trim, 0, 1)) { - case '#': if (($chunks = array_map('trim', preg_split('~:~', substr($trim, 1), 2)))) { - if (property_exists($this, $chunks[0])) { - switch ($chunks[0]) { - case 'expect': { - if ($chunks[1]) { - switch (strtoupper($chunks[1])) { - case 'TEST::EXACT': - case 'EXACT': { $this->expect = TEST::EXACT; } break; - - case 'TEST::STRING': - case 'STRING': { $this->expect = TEST::STRING; } break; - - case 'TEST::CISTRING': - case 'CISTRING': { $this->expect = TEST::CISTRING; } break; - - case 'TEST::FORMAT': - case 'FORMAT': { $this->expect = TEST::FORMAT; } break; - - default: - throw new TestConfigurationException( - $this->config, "unknown type of expectation (%s)", $chunks[1]); - } - } - } break; - - default: { - $this->$chunks[0] = $chunks[1]; - } - } - } else switch(substr($trim, 1, 1)) { - case '#': { /* do nothing */ } break; - - default: { - $line = preg_replace( - "~(\r\n)~", "\n", substr($trim, 1)); - - $line = trim($line); - - switch ($this->expect) { - case TEST::FORMAT: - $this->match[] = str_replace( - self::$format['search'], - self::$format['replace'], preg_quote($line)); - break; - - default: $this->match[] = $line; - } - } - } - } break; - - default: - break 2; - } - } - fclose($handle); - - $this->config = $config; - $this->file = $file; - } - } - - /** - * Obvious!! - * - */ - public function getResult() { - $options = sprintf('-i%s -nqb', $this->file); - - if ($this->options) { - $options = sprintf( - '%s %s %s', - $options, - $this->config['options'], - $this->options - ); - } else { - $options = sprintf( - '%s %s', $options, $this->config['options'] - ); - } - - $result = `{$this->config['phpdbg']} {$options}`; - - if ($result) { - foreach (preg_split('~(\r|\n)~', $result) as $num => $line) { - if (!$line && !isset($this->match[$num])) - continue; - - switch ($this->expect) { - case TEST::EXACT: { - if (strcmp($line, $this->match[$num]) !== 0) { - $this->diff['wants'][$num] = &$this->match[$num]; - $this->diff['gets'][$num] = $line; - } - } continue 2; - - case TEST::STRING: { - if (strpos($line, $this->match[$num]) === false) { - $this->diff['wants'][$num] = &$this->match[$num]; - $this->diff['gets'][$num] = $line; - } - } continue 2; - - case TEST::CISTRING: { - if (stripos($line, $this->match[$num]) === false) { - $this->diff['wants'][$num] = &$this->match[$num]; - $this->diff['gets'][$num] = $line; - } - } continue 2; - - case TEST::FORMAT: { - $line = trim($line); - if (!preg_match("/^{$this->match[$num]}\$/s", $line)) { - $this->diff['wants'][$num] = &$this->match[$num]; - $this->diff['gets'][$num] = $line; - } - } continue 2; - } - } - } - - $this->writeLog($result); - $this->writeDiff(); - - return (count($this->diff) == 0); - } - - /** - * Write diff to disk if configuration allows it - * - */ - protected function writeDiff() { - if (count($this->diff['wants'])) { - if (!$this->config->hasFlag('nodiff')) { - if ($this->config->hasFlag('diff2stdout')) { - $difffile = "php://stdout"; - file_put_contents($difffile, "====DIFF====\n"); - } else { - $difffile = sprintf( - '%s/%s.diff', - dirname($this->file), basename($this->file)); - } - - if (($diff = fopen($difffile, 'w+'))) { - - foreach ($this->diff['wants'] as $line => $want) { - $got = $this->diff['gets'][$line]; - - fprintf( - $diff, '(%d) -%s%s', $line+1, $want, PHP_EOL); - fprintf( - $diff, '(%d) +%s%s', $line+1, $got, PHP_EOL); - } - - fclose($diff); - } - } - } else unlink($diff); - } - - /** - * Write log to disk if configuration allows it - * - */ - protected function writeLog($result = null) { - $log = sprintf( - '%s/%s.log', - dirname($this->file), basename($this->file)); - - if (count($this->diff) && $result) { - if (!in_array('nolog', $this->config['flags'])) { - @file_put_contents( - $log, $result); - } - } else unlink($log); - } - - public $name; - public $purpose; - public $file; - public $options; - public $expect; - - protected $match; - protected $diff; - protected $stats; - protected $totals; - } -} - -namespace { - use \phpdbg\Testing\Test; - use \phpdbg\Testing\Tests; - use \phpdbg\Testing\TestsConfiguration; - - $cwd = dirname(__FILE__); - $cmd = $_SERVER['argv']; - - $retval = 0; - - { - $config = new TestsConfiguration(array( - 'exec' => realpath(array_shift($cmd)), - 'phpdbg' => realpath(sprintf( - '%s/../phpdbg', $cwd - )), - 'path' => array( - realpath(dirname(__FILE__)) - ), - 'flags' => array(), - 'width' => 75 - ), $cmd); - - $tests = new Tests($config); - - foreach ($tests->findPaths() as $path) { - $tests->logPath($path); - - foreach ($tests->findTests($path) as $test) { - $retval |= !$tests->logTest($path, $test); - } - - $tests->logPathStats($path); - } - - $tests->logStats(); - } - - die($retval); -} -?> diff --git a/sapi/phpdbg/tests/run_001.phpt b/sapi/phpdbg/tests/run_001.phpt new file mode 100644 index 0000000000..30aab1f17a --- /dev/null +++ b/sapi/phpdbg/tests/run_001.phpt @@ -0,0 +1,56 @@ +--TEST-- +Test argv passing +--PHPDBG-- +r +r 1 2 3 +r +q +--EXPECTF-- +[Successful compilation of %s] +prompt> int(5) +array(5) { + [0]=> + string(%d) "%s" + [1]=> + string(2) "--" + [2]=> + string(1) "1" + [3]=> + string(1) "2" + [4]=> + string(1) "3" +} +[Script ended normally] +prompt> int(5) +array(4) { + [0]=> + string(%d) "%s" + [1]=> + string(1) "1" + [2]=> + string(1) "2" + [3]=> + string(1) "3" +} +[Script ended normally] +prompt> int(5) +array(5) { + [0]=> + string(%d) "%s" + [1]=> + string(2) "--" + [2]=> + string(1) "1" + [3]=> + string(1) "2" + [4]=> + string(1) "3" +} +[Script ended normally] +prompt> +--ARGS-- +1 2 3 +--FILE-- +<?php + +var_dump($argc, $argv); diff --git a/sapi/phpdbg/tests/stepping_001.phpt b/sapi/phpdbg/tests/stepping_001.phpt new file mode 100644 index 0000000000..5c92ba2f0b --- /dev/null +++ b/sapi/phpdbg/tests/stepping_001.phpt @@ -0,0 +1,67 @@ +--TEST-- +Stepping with exceptions must not be stuck at CATCH +--PHPDBG-- +b ZEND_THROW +r +s + + + + + + +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Breakpoint #0 added at ZEND_THROW] +prompt> [Breakpoint #0 in ZEND_THROW at %s:4, hits: 1] +>00004: throw new Exception; + 00005: } + 00006: +prompt> [L0 %s HANDLE_EXCEPTION %s] +>00004: throw new Exception; + 00005: } + 00006: +prompt> [L0 %s HANDLE_EXCEPTION %s] +[L9 %s CATCH "Exception" $e 1 %s] +>00008: foo(); + 00009: } catch (Exception $e) { + 00010: echo "ok"; +prompt> [L10 %s ECHO "ok" %s] +>00010: echo "ok"; + 00011: } finally { + 00012: echo " ... ok"; +prompt> ok +[L11 %s FAST_CALL J8 ~%d %s] +>00011: } finally { + 00012: echo " ... ok"; + 00013: } +prompt> [L12 %s ECHO " ... ok" %s] +>00012: echo " ... ok"; + 00013: } + 00014: +prompt> ... ok +[L12 %s FAST_RET ~%d %s] +[L11 %s JMP J10 %s] +>00011: } finally { + 00012: echo " ... ok"; + 00013: } +prompt> [L12 %s RETURN 1 %s] +>00012: echo " ... ok"; + 00013: } + 00014: +prompt> +--FILE-- +<?php + +function foo() { + throw new Exception; +} + +try { + foo(); +} catch (Exception $e) { + echo "ok"; +} finally { + echo " ... ok"; +} diff --git a/sapi/phpdbg/tests/watch_001.phpt b/sapi/phpdbg/tests/watch_001.phpt new file mode 100644 index 0000000000..1183bb0e57 --- /dev/null +++ b/sapi/phpdbg/tests/watch_001.phpt @@ -0,0 +1,46 @@ +--TEST-- +Test simple recursive watchpoint +--PHPDBG-- +b 3 +r +w r $b +c + + + +q +--EXPECTF-- +[Successful compilation of %s] +prompt> [Breakpoint #0 added at %s:3] +prompt> [Breakpoint #0 at %s:3, hits: 1] +>00003: $a = 1; + 00004: $b = [$a]; + 00005: +prompt> [Set recursive watchpoint on $b] +prompt> [Breaking on watchpoint $b] +Old value: +New value: Array ([0] => 1) +>00006: unset($b); + 00007: $b = 2; + 00008: +prompt> [Breaking on watchpoint $b] +Old value inaccessible or destroyed +New value: +>00007: $b = 2; + 00008: +prompt> [Breaking on watchpoint $b] +Old value: +New value: 2 +>00007: $b = 2; + 00008: +prompt> [$b was removed, removing watchpoint recursively] +[Script ended normally] +prompt> +--FILE-- +<?php + +$a = 1; +$b = [$a]; + +unset($b); +$b = 2; diff --git a/sapi/phpdbg/xml.md b/sapi/phpdbg/xml.md new file mode 100644 index 0000000000..56dcaaa1f7 --- /dev/null +++ b/sapi/phpdbg/xml.md @@ -0,0 +1,651 @@ +phpdbg XML format +================= + +Common attributes +================= + +severity +-------- + +- indicates the genre of phpdbg system output +- usually one of these values: + - normal + - notice + - error + +msgout +------ + +- text message output related to the xml data (e.g. <intro severity="normal" help="help" msgout="To get help using phpdbg type &quot;help&quot; and press enter" />) + +req +--- + +- the request id, if one was passed to the last command (via -r %d, where %d is the id) (and the output is related to that message) + +file +---- + +- refers to a filename + +method +------ + +- format classname::methodname +- refers to a method + +function +-------- + +- refers to a function + +symbol +------ + +- either function or method (is method if "::" are present) + +opline +------ + +- in hexadecimal format +- refers to a specific pointer to a (zend_)op + +opcode +------ + +- refers to an opcode (ZEND_*) + +type +---- + +- general attribute for most errors, describes the genre of the error + +General tags +============ + +intro +----- + +- appears on startup if -q flag wasn't provided as command line arg +- before any input possibility +- attributes may be spread over multiple tags +- wrapped in <intros> tag + +### attributes ### + +- version: current phpdbg version (as string) +- help: command name for help +- report: URL for bug reporting + + +phpdbg +------ + +- general text message output from phpdbg system + +stream +------ + +- any output by PHP itself (e.g. <stream type="stdout">test</stream>) + +### attributes ### + +- type: stderr or stdout + +php +--- + +- php error output + +### attributes ### + +- msg: the error message + + +General error tags +================== + +command +------- + +- general errors about commands + +### possible attributes ### + +- type + - toomanyargs: more arguments than allowed + - noarg: argument missing + - wrongarg: wrong type of argument (e.g. letters instead of integer) + - toofewargs: not enough arguments + - notfound: command (or subcommand) doesn't exist + - ambiguous: command was ambiguous + - invalidcommand: command input is totally invalid + - (nostack: should not happen: is an internal error) + - (emptystack: should not happen: is an internal error) +- command: passed command +- subcommand: passed subcommand (present if the error is related to the subcommand) +- expected: count of expected arguments +- got: type of argument for type "wrongarg" +- num: if possible, information about which parameter had a wrong argument + +inactive +-------- + +- by type + - op_array: nothing was yet compiled (probably because no execution context set) + - symbol_table: no symbol table present (not yet initiailized or already destructed) + - noexec: not in execution + - memory_manager: using the native memory manager (malloc, free, realloc) instead of e.g. the Zend MM + - notfound: file not found + - nocontext: execution context was not set (or compilation had failed) + - isrunning: command requires no running script + + +Commands +======== + +export +------ + +- tag: <exportbreakpoint /> +- usually triggered by successful export command +- may appear when cleaning to temporary store breakpoints +- errors by type + - openfailure: could not create file + +### attributes ### + +- count: number of exported breakpoints + +break / info break +------------------ + +- General tag for breakpoint creation, deletion and hits is "<breakpoint />" + +### possible attributes ### + +- id: the breakpoint id (if the leave command was executed, the id has the value "leave") +- num: the nth opline of a function/method/file +- add: has value "success"/"fail": a brekpoint was successfully/not added +- pending: the breakpoint is waiting for resolving (e.g. a file opline on a not yet loaded file) +- deleted: has value "success"/"fail": a breakpoint was successfully/not deleted +- eval: the condition on conditional breakpoints +- file +- opline +- opcode +- symbol +- function +- method +- line + + +- listing breakpoints always in a container element "<breakpoints>" + - Child nodes: + - function + - method + - file + - opline + - methodopline + - functionopline + - fileopline + - evalfunction + - evalfunctionopline + - evalmethod + - evalmethodopline + - evalfile + - evalopline + - eval + - opcode + - attributes: + - name: name of the symbol (function/method/file/opcode) + - disabled: empty value if enabled, non-empty if enabled + +- errors (by type) + - exists: the breakpoint already exists + - maxoplines: tries to break at an opline (usedoplinenum) higher than the number of present oplines (in maxoplinenum) + - nomethod: method doesn't exist + - internalfunction: one cannot break on an opline of an internal function + - notregular: tries to set a breakpoint in not a regular file + - (invalidparameter: should not happen: is an internal error) + +frame +----- + +- General tag for frames is "<frame>" +- always has id attribute; if it only has id attribute, it just indicates current frame number, no other elements follow +- may contain other elements (of type <arg>) when contained in <backtrace> tag +- <arg> always contains a <stream> element, the value of the variable + +### possible attributes ### + +- id: the frame id, current frame has id 0 (frames with internal function calls have the same id than their called frame) +- symbol ("{main}" is root frame) +- file +- line +- internal: has value "internal" when being an internal function call (one cannot inspect that frame) + +- being an error: (by type) + - maxnum: tried to access a frame with a number higher than existing (or < 0) + +### attributes on <arg> ### + +- variadic: has a non-empty value if the argument is variadic +- name: variable name of parameter + +info (subcommands) +------------------ + +### break ### + +- See above ("break / info break") + +###Â files ### + +- lists included files +- <includedfileinfo num="" /> with num having an integer value, indicating the number of included files +- <includedfile name=""/>: one per file, with name being the file path of the included file + +### error ### + +- gets last error +- <lasterror error="" (file="" line="") /> +- error attribute contains the last error as a string, is empty if there's no last error + +### vars / globals ### + +- <variableinfo num="" /> with num having an integer value, indicating the number of (local or superglobal) variables +- if info vars was used it'll have also one of these attributes: + - method + - function + - file + - opline +- for each variable there is a <variable> followed by a <variabledetails> element +- <variable address="" refcount="" type="" name="" /> + - address: pointer to zval (hexadecimal) + - refcount: refcount of zval + - type: the variable type (long, string, ...). If the value is "unknown", the other attributes are meaningless + - name: the name of the variable + - refstatus: empty if the zval is not a reference + - class: the class the object in the zval is an instance of + - resource: the type of the resource in the zval + +### literal ### + +- <literalinfo num="" /> with num having an integer value, indicating the number of literals, optional arguments are: + - method + - function + - file + - opline +- for each literal there is a <literal> followed by a <stream type="stdout"> which prints the value of the literal +- <literal id="" />: where id is the internal identifier of the literal + +### memory ### + +- Format: + + <meminfo /> + <current /> + <used mem="" /> + <real mem="" /> + <peak /> + <used mem="" /> + <real mem="" /> + +- mem is an attribute whose value is a float. The memory is given in kilobytes (1 kB == 1024 bytes) + +### classes ### + +- <classinfo num="" /> with num having an integer value, indicating the number of loaded user-defined classes +- Each class is enumerated with first a <class>, then an optional <parents> container and then a <classsource> element +- The <parents> container contains the <class> elements of the parent of the last <class> element. +- <class type="" flags="" name="" methodcount="" /> + - type: either "User" or "Internal" + - flags: either "Interface", "Class" or "Abstract Class" +- <classsource /> where the class was defined, if there are no attributes, location is unknown, usually defined by + - file + - line + +### funcs ### + +- <functioninfo num="" /> with num having an integer value, indicating the number of loaded user-defined functions +- Each class is enumerated with first a <function> and then a <functionsource> element +- <function name="" /> +- <functionsource /> where the function was defined, if there are no attributes, location is unknown, usually defined by + - file + - line + +list +---- + +- consists of <line> elements wrapped in a <list> container +- <list file=""> is the container element with file being the filename +- <line line="" code="" /> with value of code being the whole line of code in the line specified in the line attribute + - current: this attribute is set to "current" if that line is the line where the executor currently is + +print +----- + +### without a subcommand ### + +- <print> elements are wrapped in a <printinfo> element +- there may be a variable number of <print> elements with a variable count of args inside the <printinfo> element +- possible args are: + - readline: yes/no - readline enabled or disabled + - libedit: yes/no - libedit enabled or disabled + - context: current executing context + - compiled: yes/no - are there actual compiled ops? + - stepping: @@ TODO (meaningless for now) @@ + - quiet: on/off - should it always print the opline being currently executed? + - oplog: on/off - are oplines logged in a file? + - ops: number of opcodes in current executing context + - vars: number of compiled variables (CV) + - executing: yes/no - in executor? + - vmret: the return value of the last executed opcode + - default: continue + - 1: return from vm + - 2: enter stack frame + - 3: leave stack frame + - classes: number of classes + - functions: number of functions + - constants: number of constants + - includes: number of included files + +### with a subcommand ### + +- introduced by <printinfo num="" /> (except for print opline) with num being the number of opcodes and one of these args: + - file + - method + - function + - class (then also type and flags attributes, see info classes command for their meanings) + - symbol (also type and flags attributes; here the value of flags is either "Method" or "Function") +- if there is a class method, the methods are all wrapped in a <printmethods> container +- then comes a <printoplineinfo type="" /> where type is either "User" or "Internal" +- the <printoplineinfo> has either a method or a function attribute +- if the type is "Internal" + - there are no oplines, it's an internal method or function +- if the type is "User" + - it has these attributes + - startline: the first line of code where the method or function is defined + - endline: the lastt line of code where the method or function is defined + - file: the file of code where the method or function is defined + - is followed by the oplines of that method or function (<print> elements) +- <print line="%u" opline="%p" opcode="%s" op="%s" /> +- in case of print opline it emits a single <opline line="" opline="" opcode="" op="" file="" /> + +exec +---- + +- command executing and compiling a given file + - <exec type="unset" context="" />: indicates unsetting of the old context + - <exec type="unsetops" />: indicates unsetting of the old compiled opcodes + - <exec type="unchanged" />: same execution context chosen again + - <exec type="set" context="" />: indicates setting of the new context +- errors by tag + - <compile> + - openfailure: couldn't open file + - compilefailure: The file indicated in context couldn't be compiled + - <exec> + - invalid: given context (attribute) is not matching a valid file or symlink + - notfound: given context (attribute) does not exist + +run / <stop> tag +------------------- + +- runs the script (set via exec command) +- <stop type="end" />: script execution ended normally +- (error) <stop type="bailout" /> the VM bailed out (usually because there was some error) +- compile failures see under exec, errors, <compile> + +step +---- + +- steps by one line or opcode (as defined via set stepping) default is one line +- returns back to the executor + +continue +-------- + +- returns back to the executor + +until +----- + +- temporarily disables all the breakpoints on that line until that line was left once +- returns back to the executor + +finish +------ + +- temporarily disables all the breakpoints until the end of the current frame +- returns back to the executor + +leave +------ + +- temporarily disables all the breakpoints past the end of the current frame and then stops +- returns back to the executor + +back +---- + +- prints backtrace +- see frame command + +ev +-- + +- eval()uates some code +- output wrapped in <eval> tags + +sh +-- + +- executes shell command +- still pipes to stdout ... without wrapping <stream> !!! (@@ TODO @@) + +source +------ + +- executes a file in .phpdbginit format +- errors by type + - notfound: file not found + +register +-------- + +- registers a function to be used like a command +- <register function="" />: successfully registered function +- errors by type + - notfound: no such function + - inuse: function already registered + +quit +---- + +- quits phpdbg +- if successful connection will be closed... + +clean +----- + +- cleans environment (basically a shutdown + new startup) +- <clean> tags wrapped in a <cleaninfo> container +- possible attributes of <clean> tag + - classes: number of classes + - functions: number of functions + - constants: number of constants + - includes: number of included files + +clear +----- + +- removes all breakpoints +- <clear> tags wrapped in a <clearinfo> container +- possible attributes of <clear> tag (value is always the number of defined breakpoints of that type) + - files + - functions + - methods + - oplines + - fileoplines + - functionoplines + - methodoplines + - eval + +watch +----- + +- watchpoints generally are identified by a variable (one may need to switch frames first...) +- <watch variable="" />, <watchrecursive variable="" /> and <watcharray variable="" /> (normal, array, recursive) +- <watch> if error, by type: + - undefined: tried to set a watchpoint on a not (yet) defined variable + - notiterable: element which is tried to be accessed as an object or array is nor array nor object + - invalidinput: generally malformed input +- <watchdelete variable="" />: when "watch delete" was used on a watchpoint +- (error) <watchdelete type="nowatch" />: that watchpoint doesn't exist, so couldn't be deleted +- for hit watchpoints etc., see Other tags, <watch*> +- when using watch list, <watchvariable> elements are wrapped in a <watchlist> container + - <watchvariable variable="" on="" type="" /> + - variable: watched variable (may be a variable of another scope!) + - on: values are array or variable, depending on what is watched + - type: values are recursive or simple, depending on whether the watchpoint is checked recursively or not + +set +--- + +- a general error is type="wrongargs" where a wrong argument was passed to a subcommand; tag is then <set*> + +### prompt ### + +- without other args, a <setpromt str="" /> tag is emitted where the value of the str attribue is the value of the prompt +- when there is another arg, the prompt is changed to that arg, no further xml answer + +### break ### + +- enables / disables a given breakpoint silently with no further xml answer +- if the boolean switch is omitted, it emits current state in a <setbreak id="" active="" /> where active is on or off +- error with type="nobreak", when no breakpoint with the given id exists + +### breaks ### + +- generally enables / disables breakpoint functionality silently with no further xml answer +- if the boolean switch is omitted, it emits current state in a <setbreaks active="" /> where active is on or off + +### color ### + +- sets the color on prompt, error or notices +- <setcolor type="" color="" code="" />: code is the color code of color, type is either: + - prompt + - error + - notice +- errors by type: + - nocolor: color doesn't exist + - invalidtype: type wasn't one of the three allowed types + +### colors ### + +- generally enables / disables colors silently with no further xml answer +- if the boolean switch is omitted, it emits current state in a <setcolors active="" /> where active is on or off + +### oplog ### + +- sets oplog +- (error) <setoplog type="openfailure" file="" /> when it couldn't open the passed file path +- <setoplog type="closingold" /> is emitted when there was a previous open oplog (and a file is passed) +- if no further argument is passed, it emits current state in a <setoplog active="" /> where active is on or off + +### quiet ### + +- generally enables / disables quietness silently with no further xml answer +- if the boolean switch is omitted, it emits current state in a <setquiet active="" /> where active is on or off + +### setpping ### + +- sets stepping to either opcode or line (so a step command will either advance one op or one line) +- if no further argument is passed, it emits current state in a <setoplog type="" /> where active is opcode or line + +### refcount ### + +- generally enables / disables showing of refcount in watchpoint breaks silently with no further xml answer +- if the boolean switch is omitted, it emits current state in a <setrefcount active="" /> where active is on or off + +wait +---- + +- internally executes exec, so exec will output first (if binding to socket worked) + +### attributes ### + +- import: has value "success"/"fail" +- missingmodule/missingextension: modules/extensions loaded in the target SAPI, but not in phpdbg + +### errors (by type) ### + +- nosocket: couldn't establish socket +- invaliddata: invalid JSON passed to socket + +dl +-- + +- loads a module or Zend extension at a given path +- if a relative path is passed, it's relative to the extension_dir ini setting + +### attributes ### + +- extensiontype: "Zend extension" or "module" +- name: the extension name +- path: the path where it was loaded + +### errors (by type) ### + +- unsupported: dynamic extension loading is unsupported +- relpath: relative path given, but no extension_dir defined +- unknown: general error with internal DL_LOAD() (for message see msg attribute) +- wrongapi: wrong Zend engine version (apineeded / apiinstalled attributes give information about the API versions) +- wrongbuild: unmatched build versions (buildneeded / buildinstalled attributes give information about the build versions) +- registerfailure: registering module failed +- startupfailure: couldn't startup Zend extension / module +- initfailure: couldn't initialize module +- nophpso: passed shared object is not a valid Zend extension nor module + +- errors may have the module or extension attribute when their name is already known at the point of failure + +Other tags +========== + +<signal> +----------- + +- received caught signal + +### attributes ### + +- type: type of signal (e.g. SIGINT) + +### by type ### + +- SIGINT: interactive mode is entered... + +<watch*> +----------- + +- generally emitted on hit watchpoint +- <watchdelete variable="" />: when a variable was unset, the watchpoint is removed too +- <watchhit variable="" />: when ever a watched variable is changed, followed by a <watchdata> container +- <watchdata> may contain + - for watchpoints on variables: + - each of these <watch*> tags conatins a type attribute whose value is either "old" or "new") + - <watchvalue type="" inaccessible="inaccessible" />: old value is inaccessible + - <watchvalue type=""> may contain a <stream> element which indicates the old/new (type attribute) value of the variable + - <watchrefcount type="" refcount="" isref="" />: old/new (type attribute) refcount and isref, both numbers + - isref: if the value is 0, it's not a reference, else it is one + - for watchpoints on arrays: + - <watchsize> inspects size variations of an array (the sum): + - removed: number of elements removed + - added: number of elements added + - <watcharrayptr>: if this tag appears, the internal pointer of the array way changed + +<signalsegv> +--------------- + +- generally emitted when data couldn't be fetched (e.g. by accessing inconsistent data); only used in hard interrupt mode +- it might mean that data couldn't be fetched at all, or that only incomplete data was fetched (e.g. when a fixed number of following attributes are fetched, this tag will mark a stop of fetching if none or not all tags were printed) diff --git a/sapi/phttpd/CREDITS b/sapi/phttpd/CREDITS deleted file mode 100644 index 134cc54825..0000000000 --- a/sapi/phttpd/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -phttpd -Thies C. Arntzen diff --git a/sapi/phttpd/README b/sapi/phttpd/README deleted file mode 100644 index cdb6f7c381..0000000000 --- a/sapi/phttpd/README +++ /dev/null @@ -1,5 +0,0 @@ -phttpd sapi module. - -THIS IS BY NO MEANS COMPLETE NOR USABLE RIGHT NOW! - -thies@thieso.net 03.01.2000 diff --git a/sapi/phttpd/config.m4 b/sapi/phttpd/config.m4 deleted file mode 100644 index 91339a5278..0000000000 --- a/sapi/phttpd/config.m4 +++ /dev/null @@ -1,21 +0,0 @@ -dnl -dnl $Id$ -dnl - -PHP_ARG_WITH(phttpd, for PHTTPD support, -[ --with-phttpd=DIR Build PHP as phttpd module], no, no) - -if test "$PHP_PHTTPD" != "no"; then - if test ! -d $PHP_PHTTPD ; then - AC_MSG_ERROR([You did not specify a directory]) - fi - PHP_BUILD_THREAD_SAFE - PHP_ADD_INCLUDE($PHP_PHTTPD/include) - AC_DEFINE(HAVE_PHTTPD, 1, [Whether you have phttpd]) - PHP_SELECT_SAPI(phttpd, shared, phttpd.c) - INSTALL_IT="\$(INSTALL) -m 0755 $SAPI_SHARED \$(INSTALL_ROOT)$PHP_PHTTPD/modules/" -fi - -dnl ## Local Variables: -dnl ## tab-width: 4 -dnl ## End: diff --git a/sapi/phttpd/php.sym b/sapi/phttpd/php.sym deleted file mode 100644 index f10b883a99..0000000000 --- a/sapi/phttpd/php.sym +++ /dev/null @@ -1,4 +0,0 @@ -pm_init -pm_exit -pm_request - diff --git a/sapi/phttpd/phttpd.c b/sapi/phttpd/phttpd.c deleted file mode 100644 index a4d359fe52..0000000000 --- a/sapi/phttpd/phttpd.c +++ /dev/null @@ -1,301 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 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: Thies C. Arntzen <thies@thieso.net> | - | Based on aolserver SAPI by Sascha Schumann <sascha@schumann.cx> | - +----------------------------------------------------------------------+ -*/ - -#include "php.h" -#include "SAPI.h" -#include "php_main.h" - -#ifdef HAVE_PHTTPD - -#include "ext/standard/info.h" - -#ifndef ZTS -#error PHTTPD module is only useable in thread-safe mode -#endif - -#include "php_phttpd.h" - -typedef struct { - struct connectioninfo *cip; - struct stat sb; -} phttpd_globals_struct; - -static int ph_globals_id; - -#define PHG(v) TSRMG(ph_globals_id, phttpd_globals_struct *, v) - -static int -php_phttpd_startup(sapi_module_struct *sapi_module) -{ - fprintf(stderr,"***php_phttpd_startup\n"); - - if (php_module_startup(sapi_module, NULL, 0)) { - return FAILURE; - } else { - return SUCCESS; - } -} - -static int -php_phttpd_sapi_ub_write(const char *str, uint str_length TSRMLS_DC) -{ - int sent_bytes; - - sent_bytes = fd_write(PHG(cip)->fd, str, str_length); - - if (sent_bytes == -1) { - php_handle_aborted_connection(); - } - - return sent_bytes; -} - -static int -php_phttpd_sapi_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - char *header_name, *header_content; - char *p; - - http_sendheaders(PHG(cip)->fd, PHG(cip), SG(sapi_headers).http_response_code, NULL); - - header_name = sapi_header->header; - header_content = p = strchr(header_name, ':'); - - if (p) { - *p = '\0'; - do { - header_content++; - } while (*header_content == ' '); - - fd_printf(PHG(cip)->fd,"%s: %s\n", header_name, header_content); - - *p = ':'; - } - - sapi_free_header(sapi_header); - - return 0; -} - -static int -php_phttpd_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - if (SG(sapi_headers).send_default_content_type) { - fd_printf(PHG(cip)->fd,"Content-Type: text/html\n"); - } - - fd_putc('\n', PHG(cip)->fd); - - return SAPI_HEADER_SENT_SUCCESSFULLY; -} - -static char * -php_phttpd_sapi_read_cookies(TSRMLS_D) -{ - -/* - int i; - char *http_cookie = NULL; - - i = Ns_SetIFind(NSG(conn->headers), "cookie"); - if(i != -1) { - http_cookie = Ns_SetValue(NSG(conn->headers), i); - } - - return http_cookie; -*/ - fprintf(stderr,"***php_phttpd_sapi_read_cookies\n"); - - return 0; -} - -static int -php_phttpd_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC) -{ -/* - uint max_read; - uint total_read = 0; - - max_read = MIN(NSG(data_avail), count_bytes); - - total_read = Ns_ConnRead(NSG(conn), buf, max_read); - - if(total_read == NS_ERROR) { - total_read = -1; - } else { - NSG(data_avail) -= total_read; - } - - return total_read; -*/ - fprintf(stderr,"***php_phttpd_sapi_read_post\n"); - return 0; -} - -static sapi_module_struct phttpd_sapi_module = { - "phttpd", - "PHTTPD", - - php_phttpd_startup, /* startup */ - php_module_shutdown_wrapper, /* shutdown */ - - NULL, /* activate */ - NULL, /* deactivate */ - - php_phttpd_sapi_ub_write, /* unbuffered write */ - NULL, /* flush */ - NULL, /* get uid */ - NULL, /* getenv */ - - php_error, /* error handler */ - - php_phttpd_sapi_header_handler, /* header handler */ - php_phttpd_sapi_send_headers, /* send headers handler */ - NULL, /* send header handler */ - - php_phttpd_sapi_read_post, /* read POST data */ - php_phttpd_sapi_read_cookies, /* read Cookies */ - - NULL, /* register server variables */ - NULL, /* Log message */ - NULL, /* Get request time */ - NULL, /* Child terminate */ - - STANDARD_SAPI_MODULE_PROPERTIES -}; - -static void -php_phttpd_request_ctor(TSRMLS_D TSRMLS_DC) -{ - memset(&SG(request_info), 0, sizeof(sapi_globals_struct)); /* pfusch! */ - - SG(request_info).query_string = PHG(cip)->hip->request; - SG(request_info).request_method = PHG(cip)->hip->method; - SG(request_info).path_translated = malloc(MAXPATHLEN); - SG(sapi_headers).http_response_code = 200; - if (url_expand(PHG(cip)->hip->url, SG(request_info).path_translated, MAXPATHLEN, &PHG(sb), NULL, NULL) == NULL) { - /* handle error */ - } - -#if 0 - char *server; - Ns_DString ds; - char *root; - int index; - char *tmp; - - server = Ns_ConnServer(NSG(conn)); - - Ns_DStringInit(&ds); - Ns_UrlToFile(&ds, server, NSG(conn->request->url)); - - /* path_translated is the absolute path to the file */ - SG(request_info).path_translated = strdup(Ns_DStringValue(&ds)); - Ns_DStringFree(&ds); - root = Ns_PageRoot(server); - SG(request_info).request_uri = SG(request_info).path_translated + strlen(root); - SG(request_info).content_length = Ns_ConnContentLength(NSG(conn)); - index = Ns_SetIFind(NSG(conn)->headers, "content-type"); - SG(request_info).content_type = index == -1 ? NULL : - Ns_SetValue(NSG(conn)->headers, index); - - tmp = Ns_ConnAuthUser(NSG(conn)); - if(tmp) { - tmp = estrdup(tmp); - } - SG(request_info).auth_user = tmp; - - tmp = Ns_ConnAuthPasswd(NSG(conn)); - if(tmp) { - tmp = estrdup(tmp); - } - SG(request_info).auth_password = tmp; - - NSG(data_avail) = SG(request_info).content_length; -#endif -} - -static void -php_phttpd_request_dtor(TSRMLS_D TSRMLS_DC) -{ - free(SG(request_info).path_translated); -} - - -int php_doit(TSRMLS_D) -{ - struct stat sb; - zend_file_handle file_handle; - struct httpinfo *hip = PHG(cip)->hip; - - if (php_request_startup(TSRMLS_C) == FAILURE) { - return -1; - } - - file_handle.type = ZEND_HANDLE_FILENAME; - file_handle.filename = SG(request_info).path_translated; - file_handle.free_filename = 0; - -/* - php_phttpd_hash_environment(TSRMLS_C); -*/ - php_execute_script(&file_handle TSRMLS_CC); - php_request_shutdown(NULL); - - return SG(sapi_headers).http_response_code; -} - -int pm_init(const char **argv) -{ - tsrm_startup(1, 1, 0, NULL); - sapi_startup(&phttpd_sapi_module); - phttpd_sapi_module.startup(&phttpd_sapi_module); - - ts_allocate_id(&ph_globals_id, sizeof(phttpd_globals_struct), NULL, NULL); - - return 0; -} - -void pm_exit(void) -{ - fprintf(stderr,"***pm_exit\n"); -} - -int pm_request(struct connectioninfo *cip) -{ - struct httpinfo *hip = cip->hip; - int status; - TSRMLS_FETCH(); - - if (strcasecmp(hip->method, "GET") == 0 || - strcasecmp(hip->method, "HEAD") == 0 || - strcasecmp(hip->method, "POST") == 0) { - PHG(cip) = cip; - - php_phttpd_request_ctor(TSRMLS_C); - status = php_doit(TSRMLS_C); - php_phttpd_request_dtor(TSRMLS_C); - - return status; - } else { - return -2; - } -} - -#endif diff --git a/sapi/pi3web/CREDITS b/sapi/pi3web/CREDITS deleted file mode 100644 index c4541f89da..0000000000 --- a/sapi/pi3web/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -pi3web -Holger Zimmermann diff --git a/sapi/pi3web/README b/sapi/pi3web/README deleted file mode 100644 index e3e523e940..0000000000 --- a/sapi/pi3web/README +++ /dev/null @@ -1,50 +0,0 @@ -PHP5 Module -========== -This module requires PHP5 as thread safe shared library. Have a look -into the INSTALL file which accompanies that distribution. - -If you distribute this software bundled with the PHP software in source -or binary form, then you must adhere to the PHP copyright conditions - -the terms are reasonable. - -You should have checked out and built the PHP5 source package from the -PHP CVS tree into the Pi3Web source directory called 'PHP5' first. Then -build PHP5 as Pi3Web module and after that build the Pi3Web PHP5 wrapper: - -1. Checkout PHP5 -================ -cvs -d :pserver:cvsread@cvs.php.net:/repository login -The required password is phpfi - -cvs -z3 -d :pserver:cvsread@cvs.php.net:/repository co php5 - -You must also checkout the TSRM and the ZEND module from the ZEND cvs tree -into the PHP5 root directory - -cvs -d :pserver:cvsread@cvs.zend.com:/repository login -The required password is zend - -cvs -z3 -d :pserver:cvsread@cvs.zend.com:/repository co Zend TSRM - -2. Build PHP5 -============= -2.1 POSIX ---------- -cd ./php5 -./buildconf -./configure --with-pi3web -make - -2.2 Win32 ---------- -other required downloads from the php website - - bison 1.25 - - bindlib32 - - number4.tar.gz -nmake php5dllts.mak - -3. Build Pi3Web PHP5 wrapper -============================ -Run make in the Pi3Web /Source/PHP5 directory. - -For further information refer to http://www.php.net/version4/ diff --git a/sapi/pi3web/config.m4 b/sapi/pi3web/config.m4 deleted file mode 100644 index 347a74ca06..0000000000 --- a/sapi/pi3web/config.m4 +++ /dev/null @@ -1,27 +0,0 @@ -dnl -dnl $Id$ -dnl - -PHP_ARG_WITH(pi3web, for Pi3Web support, -[ --with-pi3web[=DIR] Build PHP as Pi3Web module], no, no) - -if test "$PHP_PI3WEB" != "no"; then - if test "$PHP_PI3WEB" = "yes"; then - PI3PATH=../.. # the default - else - PI3PATH=$PHP_PI3WEB - fi - test -f "$PI3PATH/PiAPI/PiAPI.h" || AC_MSG_ERROR([Unable to find PiAPI.h in $PI3PATH/PiAPI]) - PHP_BUILD_THREAD_SAFE - AC_DEFINE(WITH_PI3WEB, 1, [whether you want Pi3Web support]) - PHP_ADD_INCLUDE($PI3PATH/PiAPI) - PHP_ADD_INCLUDE($PI3PATH/Pi2API) - PHP_ADD_INCLUDE($PI3PATH/Pi3API) - PHP_ADD_INCLUDE($PI3PATH/PHP5) - PHP_SELECT_SAPI(pi3web, shared, pi3web_sapi.c) - INSTALL_IT="\$(SHELL) \$(srcdir)/install-sh -m 0755 $SAPI_SHARED \$(INSTALL_ROOT)$PI3PATH/bin/" -fi - -dnl ## Local Variables: -dnl ## tab-width: 4 -dnl ## End: diff --git a/sapi/pi3web/config.w32 b/sapi/pi3web/config.w32 deleted file mode 100644 index a5393e621b..0000000000 --- a/sapi/pi3web/config.w32 +++ /dev/null @@ -1,16 +0,0 @@ -// vim:ft=javascript -// $Id$ - -ARG_WITH('pi3web', 'Pi3Web', 'no'); - -if (PHP_PI3WEB != "no") { - if (CHECK_HEADER_ADD_INCLUDE('PiAPI.h', 'CFLAGS_PI3WEB', PHP_PHP_BUILD + "\\Pi3Web\\include;" + PHP_PI3WEB) && - CHECK_LIB('piapi.lib', 'pi3web', PHP_PHP_BUILD + "\\Pi3Web\\lib;" + PHP_PI3WEB) && - CHECK_LIB('pi2api.lib', 'pi3web', PHP_PHP_BUILD + "\\Pi3Web\\lib;" + PHP_PI3WEB) && - CHECK_LIB('pi3api.lib', 'pi3web', PHP_PHP_BUILD + "\\Pi3Web\\lib;" + PHP_PI3WEB)) { - SAPI('pi3web', 'pi3web_sapi.c', 'php' + PHP_VERSION + 'pi3web.dll', '/D PHP5PI3WEB_EXPORTS'); - AC_DEFINE('WITH_PI3WEB', 1); - } else { - WARNING('Pi3Web not enabled; headers/libraries not found'); - } -} diff --git a/sapi/pi3web/php.sym b/sapi/pi3web/php.sym deleted file mode 100644 index e69de29bb2..0000000000 --- a/sapi/pi3web/php.sym +++ /dev/null diff --git a/sapi/pi3web/php5pi3web.dsp b/sapi/pi3web/php5pi3web.dsp deleted file mode 100644 index bb5a248802..0000000000 --- a/sapi/pi3web/php5pi3web.dsp +++ /dev/null @@ -1,136 +0,0 @@ -# Microsoft Developer Studio Project File - Name="php5pi3web" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=php5pi3web - 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 "php5pi3web.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 "php5pi3web.mak" CFG="php5pi3web - Win32 Debug_TS"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "php5pi3web - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "php5pi3web - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "php5pi3web - Win32 Release_TS_inline" (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)" == "php5pi3web - 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 Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MTd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "php5pi3web_EXPORTS" /YX /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "...\..\include" /I "..\..\win32" /I "..\..\Zend" /I "..\.." /I "..\..\main" /I "..\..\TSRM" /I "..\..\..\..\PIAPI" /I "..\..\..\..\PI2API" /I "..\..\..\..\PI3API" /D "_DEBUG" /D ZEND_DEBUG=1 /D "_WINDOWS" /D "_USRDLL" /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "_MBCS" /D "PHP5PI3WEB_EXPORTS" /FR /YX /FD /GZ /c
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x40d /d "_DEBUG"
-# ADD RSC /l 0x40d /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 php5ts_debug.lib kernel32.lib user32.lib gdi32.lib wsock32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib PiAPI.lib Pi2API.lib Pi3API.lib /nologo /version:4.0 /dll /debug /machine:I386 /nodefaultlib:"libcmt" /nodefaultlib:"libc" /pdbtype:sept /libpath:"..\..\Debug_TS" /libpath:"..\..\..\..\PIAPI" /libpath:"..\..\..\..\PI2API" /libpath:"..\..\..\..\PI3API"
-
-!ELSEIF "$(CFG)" == "php5pi3web - 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 "php5pi3web_EXPORTS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "...\..\include" /I "..\..\win32" /I "..\..\Zend" /I "..\.." /I "..\..\main" /I "..\..\TSRM" /I "..\..\..\..\PIAPI" /I "..\..\..\..\PI2API" /I "..\..\..\..\PI3API" /D "NDEBUG" /D ZEND_DEBUG=0 /D "_WINDOWS" /D "_USRDLL" /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "_MBCS" /D "PHP5PI3WEB_EXPORTS" /FR /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x40d /d "NDEBUG"
-# ADD RSC /l 0x409 /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 php5ts.lib kernel32.lib user32.lib gdi32.lib wsock32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib PiAPI.lib Pi2API.lib Pi3API.lib /nologo /version:4.0 /dll /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcmt.lib" /libpath:"..\..\Release_TS" /libpath:"..\..\..\..\PIAPI" /libpath:"..\..\..\..\PI2API" /libpath:"..\..\..\..\PI3API"
-
-!ELSEIF "$(CFG)" == "php5pi3web - Win32 Release_TS_inline"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "php5pi3web___Win32_Release_TS_inline"
-# PROP BASE Intermediate_Dir "php5pi3web___Win32_Release_TS_inline"
-# PROP BASE Ignore_Export_Lib 0
-# 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 /MD /W3 /GX /O2 /I ".." /I "..\main" /I "..\regex" /I "..\..\bindlib_w32" /I "..\Zend" /I "..\TSRM" /I "..\ext\mysql\libmysql" /I "..\..\..\PiAPI" /I "..\..\..\Pi2API" /I "..\..\..\Pi3API" /D "NDEBUG" /D ZEND_DEBUG=0 /D "_WINDOWS" /D "_USRDLL" /D "PHP5DLLTS_EXPORTS" /D "PHP_EXPORTS" /D "LIBZEND_EXPORTS" /D "TSRM_EXPORTS" /D "SAPI_EXPORTS" /D "MSVC5" /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "_MBCS" /FR /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "...\..\include" /I "..\..\win32" /I "..\..\Zend" /I "..\.." /I "..\..\main" /I "..\..\TSRM" /I "..\..\..\..\PIAPI" /I "..\..\..\..\PI2API" /I "..\..\..\..\PI3API" /D "NDEBUG" /D ZEND_DEBUG=0 /D "ZEND_WIN32_FORCE_INLINE" /D "_WINDOWS" /D "_USRDLL" /D "ZTS" /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "_MBCS" /D "PHP5PI3WEB_EXPORTS" /FR /YX /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib wsock32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ZendTS.lib TSRM.lib resolv.lib libmysql.lib PiAPI.lib Pi2API.lib Pi3API.lib /nologo /version:4.0 /dll /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcmt.lib" /out:"..\Release_TS\php5ts.dll" /libpath:"..\TSRM\Release_TS" /libpath:"..\Zend\Release_TS" /libpath:"..\..\bindlib_w32\Release" /libpath:"..\ext\mysql\libmysql\Release_TS" /libpath:"Release_TS" /libpath:"..\..\..\PiAPI" /libpath:"..\..\..\Pi2API" /libpath:"..\..\..\Pi3API"
-# ADD LINK32 php5ts.lib kernel32.lib user32.lib gdi32.lib wsock32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib PiAPI.lib Pi2API.lib Pi3API.lib /nologo /version:4.0 /dll /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcmt.lib" /libpath:"..\..\Release_TS_inline" /libpath:"..\..\..\..\PIAPI" /libpath:"..\..\..\..\PI2API" /libpath:"..\..\..\..\PI3API"
-
-!ENDIF
-
-# Begin Target
-
-# Name "php5pi3web - Win32 Debug_TS"
-# Name "php5pi3web - Win32 Release_TS"
-# Name "php5pi3web - Win32 Release_TS_inline"
-# Begin Group "Source Files"
-
-# PROP Default_Filter ".c"
-# Begin Source File
-
-SOURCE=.\pi3web_sapi.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter ".h"
-# Begin Source File
-
-SOURCE=.\pi3web_sapi.h
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/sapi/pi3web/pi3web_sapi.c b/sapi/pi3web/pi3web_sapi.c deleted file mode 100644 index 6525edf5b3..0000000000 --- a/sapi/pi3web/pi3web_sapi.c +++ /dev/null @@ -1,439 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 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. | - +----------------------------------------------------------------------+ - | Pi3Web version 2.0 | - +----------------------------------------------------------------------+ - | This file is committed by the Pi3 development group. | - | (pi3web.sourceforge.net) | - | | - | Author: Holger Zimmermann (zimpel@users.sourceforge.net) | - +----------------------------------------------------------------------+ - */ - -/* $Id$ */ - -#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS - -#include "php.h" -#include "php_main.h" -#include "php_variables.h" -#include "SAPI.h" -#include "php_globals.h" -#include "ext/standard/info.h" -#include "zend_highlight.h" -#include "zend_indent.h" -#include "zend_alloc.h" -#include "ext/standard/basic_functions.h" -#include "TSRM/TSRM.h" -#include "PiAPI.h" -#include "Pi3API.h" - -#include "pi3web_sapi.h" - -#define PI3WEB_SERVER_VAR_BUF_SIZE 1024 - -int IWasLoaded=0; - - -static void php_info_pi3web(ZEND_MODULE_INFO_FUNC_ARGS) -{ - char variable_buf[PI3WEB_SERVER_VAR_BUF_SIZE]; - DWORD variable_len; - LPCONTROL_BLOCK lpCB = (LPCONTROL_BLOCK) SG(server_context); - PIDB *pDB = (PIDB *)lpCB->GetVariableNames(lpCB->ConnID); - PIDBIterator *pIter = PIDB_getIterator( pDB, PIDBTYPE_STRING, 0, 0 ); - - PUTS("<table border=0 cellpadding=3 cellspacing=1 width=600 align=center>\n"); - PUTS("<tr><th colspan=2 bgcolor=\"" PHP_HEADER_COLOR "\">Pi3Web Server Information</th></tr>\n"); - php_info_print_table_header(2, "Information Field", "Value"); - php_info_print_table_row(2, "Pi3Web SAPI module version", "$Id$"); - php_info_print_table_row(2, "Server Name Stamp", HTTPCore_getServerStamp()); - snprintf(variable_buf, 511, "%d", HTTPCore_debugEnabled()); - php_info_print_table_row(2, "Debug Enabled", variable_buf); - PIPlatform_getCurrentDirectory( variable_buf, PI3WEB_SERVER_VAR_BUF_SIZE); - php_info_print_table_row(2, "Current Path", variable_buf); - if (lpCB->GetServerVariable(lpCB->ConnID, "SERVER_NAME", variable_buf, &variable_len) - && variable_buf[0]) { - php_info_print_table_row(2, "Main Virtual Hostname", variable_buf); - }; - snprintf(variable_buf, 511, "%d", PIPlatform_getProcessId()); - php_info_print_table_row(2, "Server PID", variable_buf); - php_info_print_table_row(2, "Server Platform", PIPlatform_getDescription()); - - PUTS("</table><br />"); - - PUTS("<table border=0 cellpadding=3 cellspacing=1 width=600 align=center>\n"); - PUTS("<tr><th colspan=2 bgcolor=\"" PHP_HEADER_COLOR "\">HTTP Request Information</th></tr>\n"); - php_info_print_table_row(2, "HTTP Request Line", lpCB->lpszReq); - PUTS("<tr><th colspan=2 bgcolor=\"" PHP_HEADER_COLOR "\">HTTP Headers</th></tr>\n"); - php_info_print_table_header(2, "Server Variable", "Value"); - - /* --- loop over all registered server variables --- */ - for(; pIter && PIDBIterator_atValidElement( pIter ); PIDBIterator_next( pIter ) ) - { - PCHAR pKey; - PIDBIterator_current( pIter, &pKey ); - if ( !pKey ) { /* sanity */ continue; }; - - variable_len = PI3WEB_SERVER_VAR_BUF_SIZE; - if (lpCB->GetServerVariable(lpCB->ConnID, pKey, variable_buf, &variable_len) - && variable_buf[0]) { - php_info_print_table_row(2, pKey, variable_buf); - } else if (PIPlatform_getLastError() == PIAPI_EINVAL) { - char *tmp_variable_buf; - - tmp_variable_buf = (char *) emalloc(variable_len); - if (lpCB->GetServerVariable(lpCB->ConnID, pKey, tmp_variable_buf, &variable_len) - && variable_buf[0]) { - php_info_print_table_row(2, pKey, tmp_variable_buf); - } - efree(tmp_variable_buf); - } - } - - PUTS("</table>"); -} - - -static zend_module_entry php_pi3web_module = { - STANDARD_MODULE_HEADER, - "PI3WEB", - NULL, - NULL, - NULL, - NULL, - NULL, - php_info_pi3web, - NULL, - STANDARD_MODULE_PROPERTIES -}; - - -static int zend_pi3web_ub_write(const char *str, uint str_length TSRMLS_DC) -{ - DWORD num_bytes = str_length; - LPCONTROL_BLOCK cb; - - cb = (LPCONTROL_BLOCK) SG(server_context); - - if ( !IWasLoaded ) return 0; - cb->WriteClient(cb->ConnID, (char *) str, &num_bytes, 0 ); - - if (num_bytes != str_length) - php_handle_aborted_connection(); - return num_bytes; -} - - -static int sapi_pi3web_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - return SAPI_HEADER_ADD; -} - - -static void accumulate_header_length(sapi_header_struct *sapi_header, uint *total_length TSRMLS_DC) -{ - *total_length += sapi_header->header_len+2; -} - - -static void concat_header(sapi_header_struct *sapi_header, char **combined_headers_ptr TSRMLS_DC) -{ - memcpy(*combined_headers_ptr, sapi_header->header, sapi_header->header_len); - *combined_headers_ptr += sapi_header->header_len; - **combined_headers_ptr = '\r'; - (*combined_headers_ptr)++; - **combined_headers_ptr = '\n'; - (*combined_headers_ptr)++; -} - - -static int sapi_pi3web_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - uint total_length = 2; /* account for the trailing \r\n */ - char *combined_headers, *combined_headers_ptr; - LPCONTROL_BLOCK lpCB = (LPCONTROL_BLOCK) SG(server_context); - sapi_header_struct default_content_type; - - if ( !IWasLoaded ) return SAPI_HEADER_SENT_SUCCESSFULLY; - - - if (SG(sapi_headers).send_default_content_type) { - sapi_get_default_content_type_header(&default_content_type TSRMLS_CC); - accumulate_header_length(&default_content_type, (void *) &total_length TSRMLS_CC); - } - zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) accumulate_header_length, (void *) &total_length TSRMLS_CC); - - /* Generate headers */ - combined_headers = (char *) emalloc(total_length+1); - combined_headers_ptr = combined_headers; - if (SG(sapi_headers).send_default_content_type) { - concat_header(&default_content_type, (void *) &combined_headers_ptr TSRMLS_CC); - sapi_free_header(&default_content_type); /* we no longer need it */ - } - zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) concat_header, (void *) &combined_headers_ptr TSRMLS_CC); - *combined_headers_ptr++ = '\r'; - *combined_headers_ptr++ = '\n'; - *combined_headers_ptr = 0; - - lpCB->dwHttpStatusCode = SG(sapi_headers).http_response_code; - lpCB->SendHeaderFunction(lpCB->ConnID, &total_length, (LPDWORD) combined_headers); - - efree(combined_headers); - if (SG(sapi_headers).http_status_line) { - efree(SG(sapi_headers).http_status_line); - SG(sapi_headers).http_status_line = 0; - } - return SAPI_HEADER_SENT_SUCCESSFULLY; -} - - -static int php_pi3web_startup(sapi_module_struct *sapi_module) -{ - if (php_module_startup(sapi_module, &php_pi3web_module, 1)==FAILURE) { - return FAILURE; - } else { - return SUCCESS; - } -} - - -static int sapi_pi3web_read_post(char *buffer, uint count_bytes TSRMLS_DC) -{ - LPCONTROL_BLOCK lpCB = (LPCONTROL_BLOCK) SG(server_context); - DWORD read_from_buf=0; - DWORD read_from_input=0; - DWORD total_read=0; - - if ((DWORD)SG(read_post_bytes) < lpCB->cbAvailable) { - read_from_buf = MIN(lpCB->cbAvailable-SG(read_post_bytes), count_bytes); - memcpy(buffer, lpCB->lpbData+SG(read_post_bytes), read_from_buf); - total_read += read_from_buf; - } - if (read_from_buf<count_bytes - && (SG(read_post_bytes)+read_from_buf) < lpCB->cbTotalBytes) { - DWORD cbRead=0, cbSize; - - read_from_input = MIN(count_bytes-read_from_buf, lpCB->cbTotalBytes-SG(read_post_bytes)-read_from_buf); - while (cbRead < read_from_input) { - cbSize = read_from_input - cbRead; - if (!lpCB->ReadClient(lpCB->ConnID, buffer+read_from_buf+cbRead, &cbSize) || cbSize==0) { - break; - } - cbRead += cbSize; - } - total_read += cbRead; - } - - /* removed after re-testing POST with Pi3Web 2.0.2 */ - /* SG(read_post_bytes) += total_read; */ - return total_read; -} - - -static char *sapi_pi3web_read_cookies(TSRMLS_D) -{ - LPCONTROL_BLOCK lpCB = (LPCONTROL_BLOCK) SG(server_context); - char variable_buf[PI3WEB_SERVER_VAR_BUF_SIZE]; - DWORD variable_len = PI3WEB_SERVER_VAR_BUF_SIZE; - - if (lpCB->GetServerVariable(lpCB->ConnID, "HTTP_COOKIE", variable_buf, &variable_len)) { - return estrndup(variable_buf, variable_len); - } else if (PIPlatform_getLastError()==PIAPI_EINVAL) { - char *tmp_variable_buf = (char *) emalloc(variable_len+1); - - if (lpCB->GetServerVariable(lpCB->ConnID, "HTTP_COOKIE", tmp_variable_buf, &variable_len)) { - tmp_variable_buf[variable_len] = 0; - return tmp_variable_buf; - } else { - efree(tmp_variable_buf); - } - } - return NULL; -} - -static void init_request_info(LPCONTROL_BLOCK lpCB TSRMLS_DC) -{ - SG(server_context) = lpCB; - SG(request_info).request_method = lpCB->lpszMethod; - SG(request_info).query_string = lpCB->lpszQueryString; - SG(request_info).path_translated = lpCB->lpszPathTranslated; - SG(request_info).request_uri = lpCB->lpszUri; - SG(request_info).content_type = lpCB->lpszContentType; - SG(request_info).content_length = lpCB->cbTotalBytes; - SG(request_info).auth_user = (lpCB->lpszUser) ? (char *)estrdup((const char *)(lpCB->lpszUser)) : 0; - SG(request_info).auth_password = (lpCB->lpszPassword) ? (char *)estrdup((const char *)(lpCB->lpszPassword)) : 0; - SG(sapi_headers).http_response_code = 200; -} - -static void sapi_pi3web_register_variables(zval *track_vars_array TSRMLS_DC) -{ - char static_variable_buf[PI3WEB_SERVER_VAR_BUF_SIZE]; - char *variable_buf; - DWORD variable_len = PI3WEB_SERVER_VAR_BUF_SIZE; - LPCONTROL_BLOCK lpCB = (LPCONTROL_BLOCK) SG(server_context); - PIDB *pDB = (PIDB *)lpCB->GetVariableNames(lpCB->ConnID); - PIDBIterator *pIter = PIDB_getIterator( pDB, PIDBTYPE_STRING, 0, 0 ); - - /* --- loop over all registered server variables --- */ - for(; pIter && PIDBIterator_atValidElement( pIter ); PIDBIterator_next( pIter ) ) - { - PCHAR pKey; - PIDBIterator_current( pIter, &pKey ); - if ( !pKey ) { /* sanity */ continue; }; - - variable_len = PI3WEB_SERVER_VAR_BUF_SIZE; - if (lpCB->GetServerVariable(lpCB->ConnID, pKey, static_variable_buf, &variable_len) - && (variable_len > 1)) { - php_register_variable(pKey, static_variable_buf, track_vars_array TSRMLS_CC); - } else if (PIPlatform_getLastError()==PIAPI_EINVAL) { - variable_buf = (char *) emalloc(variable_len); - if (lpCB->GetServerVariable(lpCB->ConnID, pKey, variable_buf, &variable_len)) { - php_register_variable(pKey, variable_buf, track_vars_array TSRMLS_CC); - } - efree(variable_buf); - } - - } - - - /* PHP_SELF support */ - variable_len = PI3WEB_SERVER_VAR_BUF_SIZE; - if (lpCB->GetServerVariable(lpCB->ConnID, "SCRIPT_NAME", static_variable_buf, &variable_len) - && (variable_len > 1)) { - php_register_variable("PHP_SELF", static_variable_buf, track_vars_array TSRMLS_CC); - } -} - -static sapi_module_struct pi3web_sapi_module = { - "pi3web", /* name */ - "PI3WEB", /* pretty name */ - - php_pi3web_startup, /* startup */ - php_module_shutdown_wrapper, /* shutdown */ - NULL, /* activate */ - NULL, /* deactivate */ - zend_pi3web_ub_write, /* unbuffered write */ - NULL, /* flush */ - NULL, /* get uid */ - NULL, /* getenv */ - php_error, /* error handler */ - sapi_pi3web_header_handler, /* header handler */ - sapi_pi3web_send_headers, /* send headers handler */ - NULL, /* send header handler */ - sapi_pi3web_read_post, /* read POST data */ - sapi_pi3web_read_cookies, /* read Cookies */ - sapi_pi3web_register_variables, /* register server variables */ - NULL, /* Log message */ - NULL, /* Get request time */ - NULL, /* Child terminate */ - - STANDARD_SAPI_MODULE_PROPERTIES -}; - -MODULE_API DWORD PHP5_wrapper(LPCONTROL_BLOCK lpCB) -{ - zend_file_handle file_handle = {0}; - int iRet = PIAPI_COMPLETED; - TSRMLS_FETCH(); - - zend_first_try { - file_handle.filename = lpCB->lpszFileName; - file_handle.free_filename = 0; - file_handle.type = ZEND_HANDLE_FILENAME; - file_handle.opened_path = NULL; - - init_request_info(lpCB TSRMLS_CC); - php_request_startup(TSRMLS_C); - - switch ( lpCB->dwBehavior ) { - case PHP_MODE_STANDARD: - iRet = ( php_execute_script( &file_handle TSRMLS_CC ) ) ? - PIAPI_COMPLETED : PIAPI_ERROR; - break; - case PHP_MODE_HIGHLIGHT: { - zend_syntax_highlighter_ini syntax_highlighter_ini; - if ( open_file_for_scanning( &file_handle TSRMLS_CC ) == SUCCESS ) - { - php_get_highlight_struct( &syntax_highlighter_ini ); - zend_highlight( &syntax_highlighter_ini TSRMLS_CC ); - } - else - { - iRet = PIAPI_ERROR; - }; - }; - break; - case PHP_MODE_INDENT: { - sapi_header_line ctr = {0}; - - ctr.line = "Content-Type: text/plain"; - ctr.line_len = strlen(ctr.line); - - sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC); - } - if ( open_file_for_scanning( &file_handle TSRMLS_CC ) == SUCCESS ) - { - zend_indent(); - } - else - { - iRet = PIAPI_ERROR; - }; - break; - case PHP_MODE_LINT: - iRet = (php_lint_script(&file_handle TSRMLS_CC) == SUCCESS) ? - PIAPI_COMPLETED : PIAPI_ERROR; - break; - default: - iRet = PIAPI_ERROR;; - } - - if (SG(request_info).cookie_data) { - efree(SG(request_info).cookie_data); - }; - - php_request_shutdown(NULL); - } zend_catch { - iRet = PIAPI_ERROR; - } zend_end_try(); - return iRet; -} - -MODULE_API BOOL PHP5_startup() { - tsrm_startup(1, 1, 0, NULL); - sapi_startup(&pi3web_sapi_module); - if (pi3web_sapi_module.startup) { - pi3web_sapi_module.startup(&pi3web_sapi_module); - }; - IWasLoaded = 1; - return IWasLoaded; -}; - -MODULE_API BOOL PHP5_shutdown() { - if (pi3web_sapi_module.shutdown) { - pi3web_sapi_module.shutdown(&pi3web_sapi_module); - }; - sapi_shutdown(); - tsrm_shutdown(); - IWasLoaded = 0; - return !IWasLoaded; -}; - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - */ diff --git a/sapi/pi3web/pi3web_sapi.h b/sapi/pi3web/pi3web_sapi.h deleted file mode 100644 index d229fec53f..0000000000 --- a/sapi/pi3web/pi3web_sapi.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef _PI3WEB_SAPI_H_ -#define _PI3WEB_SAPI_H_ - -#ifdef PHP_WIN32 -# include <windows.h> -# ifdef PHP5PI3WEB_EXPORTS -# define MODULE_API __declspec(dllexport) -# else -# define MODULE_API __declspec(dllimport) -# endif -#else -# if defined(__GNUC__) && __GNUC__ >= 4 -# define MODULE_API __attribute__ ((visibility("default"))) -# else -# define MODULE_API -# endif -# define far - - typedef int BOOL; - typedef void far *LPVOID; - typedef unsigned long DWORD; - typedef DWORD far *LPDWORD; - typedef char CHAR; - typedef CHAR *LPSTR; - typedef unsigned char BYTE; - typedef BYTE far *LPBYTE; -#endif - - typedef LPVOID HCONN; - -#ifdef __cplusplus -extern "C" { -#endif - -#define PHP_MODE_STANDARD 1 -#define PHP_MODE_HIGHLIGHT 2 -#define PHP_MODE_INDENT 3 -#define PHP_MODE_LINT 4 - -// -// passed to the procedure on a new request -// -typedef struct _CONTROL_BLOCK { - DWORD cbSize; // size of this struct. - HCONN ConnID; // Context number not to be modified! - DWORD dwHttpStatusCode; // HTTP Status code - CHAR lpszLogData[80]; // null terminated log info - - LPSTR lpszMethod; // REQUEST_METHOD - LPSTR lpszQueryString; // QUERY_STRING - LPSTR lpszPathInfo; // PATH_INFO - LPSTR lpszPathTranslated; // PATH_TRANSLATED - LPSTR lpszFileName; // FileName to PHP3 physical file - LPSTR lpszUri; // The request URI - LPSTR lpszReq; // The whole HTTP request line - LPSTR lpszUser; // The authenticated user - LPSTR lpszPassword; // The authenticated password - - DWORD cbTotalBytes; // Total bytes indicated from client - DWORD cbAvailable; // Available number of bytes - LPBYTE lpbData; // pointer to cbAvailable bytes - - LPSTR lpszContentType; // Content type of client data - DWORD dwBehavior; // PHP behavior (standard, highlight, intend - - - LPVOID (* GetVariableNames) (HCONN hConn); - - BOOL (* GetServerVariable) ( HCONN hConn, - LPSTR lpszVariableName, - LPVOID lpvBuffer, - LPDWORD lpdwSize ); - - BOOL (* WriteClient) ( HCONN hConn, - LPVOID lpvBuffer, - LPDWORD lpdwBytes, - DWORD dwReserved ); - - BOOL (* ReadClient) ( HCONN hConn, - LPVOID lpvBuffer, - LPDWORD lpdwSize ); - - BOOL (* SendHeaderFunction)( HCONN hConn, - LPDWORD lpdwSize, - LPDWORD lpdwDataType ); - -} CONTROL_BLOCK, *LPCONTROL_BLOCK; - -MODULE_API DWORD PHP5_wrapper(LPCONTROL_BLOCK lpCB); -MODULE_API BOOL PHP5_startup(); -MODULE_API BOOL PHP5_shutdown(); - -// the following type declaration is for the server side -typedef DWORD ( * PFN_WRAPPERFUNC )( CONTROL_BLOCK *pCB ); - - - -#ifdef __cplusplus -} -#endif - -#endif // end definition _PI3WEB_SAPI_H_ diff --git a/sapi/roxen/README b/sapi/roxen/README deleted file mode 100644 index d834a0000e..0000000000 --- a/sapi/roxen/README +++ /dev/null @@ -1,18 +0,0 @@ -Roxen PHP support. Early version. Don't expect to be able to get it to -work. Requires Pike 0.7.79 and Roxen 1.4. Anything less won't work. - -The module is now thread safe, in a couple of different modes. First -mode, the default, uses a process global PHP lock in the Roxen -module. This means that all PHP-requests are serialized (ie only one -script is executed at any one time). The second option is using ZTS -(Zend Thread Safe mode). Unless --enable-roxen-zts is specified, this -won't be used. - -This solution now works fine and is recommended. Multiple PHP5 -requests will be run in parallell. The maximum number of parallell -PHP5-execution is limited to the number of handle threads Roxen is -started with. - -Support for this module is lacking. Please contact Roxen Internet -Software for support and help. See http://www.roxen.com/company/contact/ -for contact information. diff --git a/sapi/roxen/TODO b/sapi/roxen/TODO deleted file mode 100644 index 248f36f52e..0000000000 --- a/sapi/roxen/TODO +++ /dev/null @@ -1,33 +0,0 @@ -BUGS: - -- fix backtraces -- exit in PHP exits Roxen -- POST newline added? -- Rewriting header handling so that more than one header with the same - name can be set (most importantly, cookies). -- Recursive mutex lock problem: - - And another error (when trying to include a class) - - Recursive mutex locks! - /Usr/local/pike/7.0.54/lib/modules/PHP5.so.Interpreter: - run("/home/www/www.tx.pl/news/test.php",mapping[3],modules/scripting/php5.pike.PHPScript(),modules/scripting/php5.pike.PHPScript.done) - modules/scripting/php5.pike:169: run() - base_server/roxen.pike:569: handler_thread(3). - - And after this every access to any php script (on other virtual sites - also) ends (of course there is no proper output) with this error: - - Php4.Interpreter->run: Tried to run a PHP-script from a PHP - callback!/usr/local/pike/7.0.54/lib/modules/PHP5.so.Interpreter: - run("/home/www/biall.com.pl/index.php3",mapping[2],modules/scripting/php5.pike.PHPScript(),modules/scripting/php5.pike.PHPScript.done) - modules/scripting/php5.pike:169: run() - base_server/roxen.pike:569: handler_thread(3). - - -ADDITIONS: - -- use th_farm -- change cwd in single threaded mode -- per-virtual-server configuration - diff --git a/sapi/roxen/config.m4 b/sapi/roxen/config.m4 deleted file mode 100644 index 7601b0c1ed..0000000000 --- a/sapi/roxen/config.m4 +++ /dev/null @@ -1,55 +0,0 @@ -dnl -dnl $Id$ -dnl - -PHP_ARG_WITH(roxen,, -[ --with-roxen=DIR Build PHP as a Pike module. DIR is the base Roxen - directory, normally /usr/local/roxen/server], no, no) - -PHP_ARG_ENABLE(roxen-zts, whether Roxen module is build using ZTS, -[ --enable-roxen-zts ROXEN: Build the Roxen module using Zend Thread Safety], no, no) - -RESULT= -AC_MSG_CHECKING([for Roxen/Pike support]) -if test "$PHP_ROXEN" != "no"; then - if test ! -d $PHP_ROXEN ; then - AC_MSG_ERROR([You did not specify a directory]) - fi - if test -f $PHP_ROXEN/bin/roxen; then - PIKE=$PHP_ROXEN/bin/roxen - elif test -f $PHP_ROXEN/bin/pike; then - PIKE=$PHP_ROXEN/bin/pike - else - AC_MSG_ERROR([Could not find a pike in $PHP_ROXEN/bin/]) - fi - - if $PIKE -e 'float v; catch(v = __VERSION__ + (__BUILD__/10000.0)); if(v < 0.7079) exit(1); exit(0);'; then - PIKE_MODULE_DIR=`$PIKE --show-paths 2>&1| grep '^Module' | sed -e 's/.*: //'` - PIKE_INCLUDE_DIR=`echo $PIKE_MODULE_DIR | sed -e 's,lib/pike/modules,include/pike,' -e 's,lib/modules,include/pike,'` - if test -z "$PIKE_INCLUDE_DIR" || test -z "$PIKE_MODULE_DIR"; then - AC_MSG_ERROR([Failed to figure out Pike module and include directories]) - fi - else - AC_MSG_ERROR([Roxen/PHP requires Pike 0.7.79 or newer]) - fi - - PHP_ADD_INCLUDE($PIKE_INCLUDE_DIR) - AC_DEFINE(HAVE_ROXEN, 1, [Whether you use Roxen]) - PHP_SELECT_SAPI(roxen, shared, roxen.c) - INSTALL_IT="\$(INSTALL) -m 0755 $SAPI_SHARED $PIKE_MODULE_DIR/PHP5.so" - RESULT="yes - Pike binary used: $PIKE - Pike include dir: $PIKE_INCLUDE_DIR - Pike module directory: $PIKE_MODULE_DIR" - PIKE_INCLUDE_DIR=" -I$PIKE_INCLUDE_DIR " - - if test "$PHP_ROXEN_ZTS" != "no"; then - PHP_BUILD_THREAD_SAFE - AC_DEFINE(ROXEN_USE_ZTS, 1, [Whether to use Roxen in ZTS mode]) - fi -fi -AC_MSG_RESULT([$RESULT]) - -dnl ## Local Variables: -dnl ## tab-width: 4 -dnl ## End: diff --git a/sapi/roxen/roxen.c b/sapi/roxen/roxen.c deleted file mode 100644 index 105585f2bc..0000000000 --- a/sapi/roxen/roxen.c +++ /dev/null @@ -1,727 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 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: David Hedbor <neotron@php.net> | - | Based on aolserver SAPI by Sascha Schumann <sascha@schumann.cx> | - +----------------------------------------------------------------------+ - */ - -/* $Id$ */ - -#include "php.h" -#ifdef HAVE_ROXEN - -#include "php_ini.h" -#include "php_globals.h" -#include "SAPI.h" -#include "php_main.h" -#include "ext/standard/info.h" - -#include "php_version.h" - -#ifndef ZTS -/* Only valid if thread safety is enabled. */ -#undef ROXEN_USE_ZTS -#endif - - -/* Pike Include Files - * - * conflicts with pike avoided by only using long names. Requires a new - * Pike 0.7 since it was implemented for this interface only. - * - */ -#define NO_PIKE_SHORTHAND - -#include <fdlib.h> -#include <program.h> -#include <pike_types.h> -#include <interpret.h> -#include <module_support.h> -#include <error.h> -#include <array.h> -#include <backend.h> -#include <stralloc.h> -#include <mapping.h> -#include <object.h> -#include <threads.h> -#include <builtin_functions.h> -#include <operators.h> - -#undef HIDE_GLOBAL_VARIABLES -#undef REVEAL_GLOBAL_VARIABLES -#define HIDE_GLOBAL_VARIABLES() -#define REVEAL_GLOBAL_VARIABLES() - -/* php_roxen_request is per-request object storage */ - -typedef struct -{ - struct mapping *request_data; - struct object *my_fd_obj; - int my_fd; - char *filename; -} php_roxen_request; - - -/* Defines to get to the data supplied when the script is started. */ - -#ifdef ROXEN_USE_ZTS - -/* ZTS does work now, but it seems like it's faster using the "serialization" - * method I previously used. Thus it's not used unless ROXEN_USE_ZTS is defined. - */ - -/* Per thread storage area id... */ -static int roxen_globals_id; - -# define GET_THIS() php_roxen_request *_request = ts_resource(roxen_globals_id) -# define THIS _request -#else -static php_roxen_request *current_request = NULL; - -# define GET_THIS() current_request = ((php_roxen_request *)Pike_fp->current_storage) -# define THIS current_request -#endif - -/* File descriptor integer. Used to write directly to the FD without - * passing Pike - */ -#define MY_FD (THIS->my_fd) - -/* FD object. Really a PHPScript object from Pike which implements a couple - * of functions to handle headers, writing and buffering. - */ -#define MY_FD_OBJ ((struct object *)(THIS->my_fd_obj)) - -/* Mapping with data supplied from the calling Roxen module. Contains - * a mapping with headers, an FD object etc. - */ -#define REQUEST_DATA ((struct mapping *)(THIS->request_data)) - - -#if defined(_REENTRANT) && !defined(ROXEN_USE_ZTS) -/* Lock used to serialize the PHP execution. If ROXEN_USE_ZTS is defined, we - * are using the PHP thread safe mechanism instead. - */ -static PIKE_MUTEX_T roxen_php_execution_lock; -# define PHP_INIT_LOCK() mt_init(&roxen_php_execution_lock) -# define PHP_LOCK(X) THREADS_ALLOW();mt_lock(&roxen_php_execution_lock);THREADS_DISALLOW() -# define PHP_UNLOCK(X) mt_unlock(&roxen_php_execution_lock); -# define PHP_DESTROY() mt_destroy(&roxen_php_execution_lock) -#else /* !_REENTRANT */ -# define PHP_INIT_LOCK() -# define PHP_LOCK(X) -# define PHP_UNLOCK(X) -# define PHP_DESTROY() -#endif /* _REENTRANT */ - -extern int fd_from_object(struct object *o); -static unsigned char roxen_php_initialized; - -/* This allows calling of pike functions from the PHP callbacks, - * which requires the Pike interpreter to be locked. - */ -#define THREAD_SAFE_RUN(COMMAND, what) do {\ - struct thread_state *state;\ - if((state = thread_state_for_id(th_self()))!=NULL) {\ - if(!state->swapped) {\ - COMMAND;\ - } else {\ - mt_lock(&interpreter_lock);\ - SWAP_IN_THREAD(state);\ - COMMAND;\ - SWAP_OUT_THREAD(state);\ - mt_unlock(&interpreter_lock);\ - }\ - }\ -} while(0) - -struct program *php_program; - - -/* To avoid executing a PHP script from a PHP callback, which would - * create a deadlock, a global thread id is used. If the thread calling the - * php-script is the same as the current thread, it fails. - */ -static int current_thread = -1; - - -/* Low level header lookup. Basically looks for the named header in the mapping - * headers in the supplied options mapping. - */ - -static INLINE struct svalue *lookup_header(char *headername) -{ - struct svalue *headers, *value; - struct pike_string *sind; -#ifdef ROXEN_USE_ZTS - GET_THIS(); -#endif - sind = make_shared_string("env"); - headers = low_mapping_string_lookup(REQUEST_DATA, sind); - free_string(sind); - if(!headers || headers->type != PIKE_T_MAPPING) return NULL; - sind = make_shared_string(headername); - value = low_mapping_string_lookup(headers->u.mapping, sind); - free_string(sind); - if(!value) return NULL; - return value; -} - -/* Lookup a header in the mapping and return the value as a string, or - * return the default if it's missing - */ -INLINE static char *lookup_string_header(char *headername, char *default_value) -{ - struct svalue *head = NULL; - THREAD_SAFE_RUN(head = lookup_header(headername), "header lookup"); - if(!head || head->type != PIKE_T_STRING) - return default_value; - return head->u.string->str; -} - -/* Lookup a header in the mapping and return the value as if it's an integer - * and otherwise return the default. - */ -INLINE static int lookup_integer_header(char *headername, int default_value) -{ - struct svalue *head = NULL; - THREAD_SAFE_RUN(head = lookup_header(headername), "header lookup"); - if(!head || head->type != PIKE_T_INT) - return default_value; - return head->u.integer; -} - -/* - * php_roxen_low_ub_write() writes data to the client connection. Might be - * rewritten to do more direct IO to save CPU and the need to lock the * - * interpreter for better threading. - */ - -static int -php_roxen_low_ub_write(const char *str, uint str_length TSRMLS_DC) { - int sent_bytes = 0; - struct pike_string *to_write = NULL; -#ifdef ROXEN_USE_ZTS - GET_THIS(); -#endif - - if(!MY_FD_OBJ->prog) { - PG(connection_status) = PHP_CONNECTION_ABORTED; - zend_bailout(); - return -1; - } - to_write = make_shared_binary_string(str, str_length); - push_string(to_write); - safe_apply(MY_FD_OBJ, "write", 1); - if(Pike_sp[-1].type == PIKE_T_INT) - sent_bytes = Pike_sp[-1].u.integer; - pop_stack(); - if(sent_bytes != str_length) { - /* This means the connection is closed. Dead. Gone. *sniff* */ - php_handle_aborted_connection(); - } - return sent_bytes; -} - -/* - * php_roxen_sapi_ub_write() calls php_roxen_low_ub_write in a Pike thread - * safe manner. - */ - -static int -php_roxen_sapi_ub_write(const char *str, uint str_length TSRMLS_DC) -{ -#ifdef ROXEN_USE_ZTS - GET_THIS(); -#endif - - int sent_bytes = 0, fd = MY_FD; - if(fd) - { - for(sent_bytes=0;sent_bytes < str_length;) - { - int written; - written = fd_write(fd, str + sent_bytes, str_length - sent_bytes); - if(written < 0) - { - switch(errno) - { - default: - /* This means the connection is closed. Dead. Gone. *sniff* */ - PG(connection_status) = PHP_CONNECTION_ABORTED; - zend_bailout(); - return sent_bytes; - case EINTR: - case EWOULDBLOCK: - continue; - } - - } else { - sent_bytes += written; - } - } - } else { - THREAD_SAFE_RUN(sent_bytes = php_roxen_low_ub_write(str, str_length TSRMLS_CC), - "write"); - } - return sent_bytes; -} - -/* php_roxen_set_header() sets a header in the header mapping. Called in a - * thread safe manner from php_roxen_sapi_header_handler. - */ -static void php_roxen_set_header(char *header_name, char *value, char *p) -{ - struct svalue hsval; - struct pike_string *hval, *ind, *hind; - struct mapping *headermap; - struct svalue *s_headermap; -#ifdef ROXEN_USE_ZTS - GET_THIS(); -#endif - hval = make_shared_string(value); - ind = make_shared_string(" _headers"); - hind = make_shared_binary_string(header_name, - (int)(p - header_name)); - - s_headermap = low_mapping_string_lookup(REQUEST_DATA, ind); - if(!s_headermap) - { - struct svalue mappie; - mappie.type = PIKE_T_MAPPING; - headermap = allocate_mapping(1); - mappie.u.mapping = headermap; - mapping_string_insert(REQUEST_DATA, ind, &mappie); - free_mapping(headermap); - } else - headermap = s_headermap->u.mapping; - - hsval.type = PIKE_T_STRING; - hsval.u.string = hval; - mapping_string_insert(headermap, hind, &hsval); - - free_string(hval); - free_string(ind); - free_string(hind); -} - -/* - * php_roxen_sapi_header_handler() sets a HTTP reply header to be - * sent to the client. - */ -static int -php_roxen_sapi_header_handler(sapi_header_struct *sapi_header, - sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - char *header_name, *header_content, *p; - header_name = sapi_header->header; - header_content = p = strchr(header_name, ':'); - - if(p) { - do { - header_content++; - } while(*header_content == ' '); - THREAD_SAFE_RUN(php_roxen_set_header(header_name, header_content, p), "header handler"); - } - sapi_free_header(sapi_header); - return 0; -} - -/* - * php_roxen_sapi_send_headers() flushes the headers to the client. - * Called before real content is sent by PHP. - */ - -static int -php_roxen_low_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - struct pike_string *ind; - struct svalue *s_headermap; -#ifdef ROXEN_USE_ZTS - GET_THIS(); -#endif - - if(!MY_FD_OBJ->prog) { - PG(connection_status) = PHP_CONNECTION_ABORTED; - zend_bailout(); - return SAPI_HEADER_SEND_FAILED; - } - ind = make_shared_string(" _headers"); - s_headermap = low_mapping_string_lookup(REQUEST_DATA, ind); - free_string(ind); - - push_int(SG(sapi_headers).http_response_code); - if(s_headermap && s_headermap->type == PIKE_T_MAPPING) - ref_push_mapping(s_headermap->u.mapping); - else - push_int(0); - safe_apply(MY_FD_OBJ, "send_headers", 2); - pop_stack(); - - return SAPI_HEADER_SENT_SUCCESSFULLY; -} - -static int -php_roxen_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - int res = 0; - THREAD_SAFE_RUN(res = php_roxen_low_send_headers(sapi_headers TSRMLS_CC), "send headers"); - return res; -} - -/* - * php_roxen_sapi_read_post() reads a specified number of bytes from - * the client. Used for POST/PUT requests. - */ - -INLINE static int php_roxen_low_read_post(char *buf, uint count_bytes) -{ - uint total_read = 0; -#ifdef ROXEN_USE_ZTS - GET_THIS(); -#endif - TSRMLS_FETCH(); - - if(!MY_FD_OBJ->prog) - { - PG(connection_status) = PHP_CONNECTION_ABORTED; - zend_bailout(); - return -1; - } - push_int(count_bytes); - safe_apply(MY_FD_OBJ, "read_post", 1); - if(Pike_sp[-1].type == PIKE_T_STRING) { - MEMCPY(buf, Pike_sp[-1].u.string->str, - (total_read = Pike_sp[-1].u.string->len)); - buf[total_read] = '\0'; - } else - total_read = 0; - pop_stack(); - return total_read; -} - -static int -php_roxen_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC) -{ - uint total_read = 0; - THREAD_SAFE_RUN(total_read = php_roxen_low_read_post(buf, count_bytes), "read post"); - return total_read; -} - -/* - * php_roxen_sapi_read_cookies() returns the Cookie header from - * the HTTP request header - */ - -static char * -php_roxen_sapi_read_cookies(TSRMLS_D) -{ - char *cookies; - cookies = lookup_string_header("HTTP_COOKIE", NULL); - return cookies; -} - -static void php_info_roxen(ZEND_MODULE_INFO_FUNC_ARGS) -{ - /* char buf[512]; */ - php_info_print_table_start(); - php_info_print_table_row(2, "SAPI module version", "$Id$"); - /* php_info_print_table_row(2, "Build date", Ns_InfoBuildDate()); - php_info_print_table_row(2, "Config file path", Ns_InfoConfigFile()); - php_info_print_table_row(2, "Error Log path", Ns_InfoErrorLog()); - php_info_print_table_row(2, "Installation path", Ns_InfoHomePath()); - php_info_print_table_row(2, "Hostname of server", Ns_InfoHostname()); - php_info_print_table_row(2, "Source code label", Ns_InfoLabel()); - php_info_print_table_row(2, "Server platform", Ns_InfoPlatform()); - snprintf(buf, 511, "%s/%s", Ns_InfoServerName(), Ns_InfoServerVersion()); - php_info_print_table_row(2, "Server version", buf); - snprintf(buf, 511, "%d day(s), %02d:%02d:%02d", - uptime / 86400, - (uptime / 3600) % 24, - (uptime / 60) % 60, - uptime % 60); - php_info_print_table_row(2, "Server uptime", buf); - */ - php_info_print_table_end(); -} - -static zend_module_entry php_roxen_module = { - STANDARD_MODULE_HEADER, - "Roxen", - NULL, - NULL, - NULL, - NULL, - NULL, - php_info_roxen, - NULL, - STANDARD_MODULE_PROPERTIES -}; - -static int php_roxen_startup(sapi_module_struct *sapi_module) -{ - if(php_module_startup(sapi_module, &php_roxen_module, 1) == FAILURE) { - return FAILURE; - } else { - return SUCCESS; - } -} - -/* this structure is static (as in "it does not change") */ - -static sapi_module_struct roxen_sapi_module = { - "roxen", - "Roxen", - php_roxen_startup, /* startup */ - php_module_shutdown_wrapper, /* shutdown */ - NULL, /* activate */ - NULL, /* deactivate */ - php_roxen_sapi_ub_write, /* unbuffered write */ - NULL, /* flush */ - NULL, /* get uid */ - NULL, /* getenv */ - php_error, /* error handler */ - php_roxen_sapi_header_handler, /* header handler */ - php_roxen_sapi_send_headers, /* send headers handler */ - NULL, /* send header handler */ - php_roxen_sapi_read_post, /* read POST data */ - php_roxen_sapi_read_cookies, /* read Cookies */ - NULL, /* register server variables */ - NULL, /* Log message */ - NULL, /* Get request time */ - NULL, /* Child terminate */ - - STANDARD_SAPI_MODULE_PROPERTIES -}; - -/* - * php_roxen_hash_environment() populates the php script environment - * with a number of variables. HTTP_* variables are created for - * the HTTP header data, so that a script can access these. - */ -#define ADD_STRING(name) \ - MAKE_STD_ZVAL(zvalue); \ - zvalue->type = IS_STRING; \ - zvalue->value.str.len = strlen(buf); \ - zvalue->value.str.val = estrndup(buf, zvalue->value.str.len); \ - zend_hash_update(&EG(symbol_table), name, sizeof(name), \ - &zvalue, sizeof(zval *), NULL) - -static void -php_roxen_hash_environment(TSRMLS_D) -{ - int i; - char buf[512]; - zval *zvalue; - struct svalue *headers; - struct pike_string *sind; - struct array *indices; - struct svalue *ind, *val; -#ifdef ROXEN_USE_ZTS - GET_THIS(); -#endif - sind = make_shared_string("env"); - headers = low_mapping_string_lookup(REQUEST_DATA, sind); - free_string(sind); - if(headers && headers->type == PIKE_T_MAPPING) { - indices = mapping_indices(headers->u.mapping); - for(i = 0; i < indices->size; i++) { - ind = &indices->item[i]; - val = low_mapping_lookup(headers->u.mapping, ind); - if(ind && ind->type == PIKE_T_STRING && - val && val->type == PIKE_T_STRING) { - int buf_len; - buf_len = MIN(511, ind->u.string->len); - strncpy(buf, ind->u.string->str, buf_len); - buf[buf_len] = '\0'; /* Terminate correctly */ - MAKE_STD_ZVAL(zvalue); - zvalue->type = IS_STRING; - zvalue->value.str.len = val->u.string->len; - zvalue->value.str.val = estrndup(val->u.string->str, zvalue->value.str.len); - - zend_hash_update(&EG(symbol_table), buf, buf_len + 1, &zvalue, sizeof(zval *), NULL); - } - } - free_array(indices); - } - - /* - MAKE_STD_ZVAL(zvalue); - zvalue->type = IS_LONG; - zvalue->value.lval = Ns_InfoBootTime(); - zend_hash_update(&EG(symbol_table), "SERVER_BOOTTIME", sizeof("SERVER_BOOTTIME"), &zvalue, sizeof(zval *), NULL); - */ -} - -/* - * php_roxen_module_main() is called by the per-request handler and - * "executes" the script - */ - -static int php_roxen_module_main(TSRMLS_D) -{ - int res, len; - char *dir; - zend_file_handle file_handle; -#ifdef ROXEN_USE_ZTS - GET_THIS(); -#endif - - file_handle.type = ZEND_HANDLE_FILENAME; - file_handle.filename = THIS->filename; - file_handle.free_filename = 0; - file_handle.opened_path = NULL; - - THREADS_ALLOW(); - res = php_request_startup(TSRMLS_C); - THREADS_DISALLOW(); - if(res == FAILURE) { - return 0; - } - php_roxen_hash_environment(TSRMLS_C); - THREADS_ALLOW(); - php_execute_script(&file_handle TSRMLS_CC); - php_request_shutdown(NULL); - THREADS_DISALLOW(); - return 1; -} - -/* - * The php_roxen_request_handler() is called per request and handles - * everything for one request. - */ - -void f_php_roxen_request_handler(INT32 args) -{ - struct object *my_fd_obj; - struct mapping *request_data; - struct svalue *done_callback, *raw_fd; - struct pike_string *script, *ind; - int status = 1; -#ifdef ROXEN_USE_ZTS - GET_THIS(); -#endif - TSRMLS_FETCH(); - - if(current_thread == th_self()) - php_error(E_WARNING, "PHP5.Interpreter->run: Tried to run a PHP-script from a PHP " - "callback!"); - get_all_args("PHP5.Interpreter->run", args, "%S%m%O%*", &script, - &request_data, &my_fd_obj, &done_callback); - if(done_callback->type != PIKE_T_FUNCTION) - php_error(E_WARNING, "PHP5.Interpreter->run: Bad argument 4, expected function.\n"); - PHP_LOCK(THIS); /* Need to lock here or reusing the same object might cause - * problems in changing stuff in that object */ -#ifndef ROXEN_USE_ZTS - GET_THIS(); -#endif - THIS->request_data = request_data; - THIS->my_fd_obj = my_fd_obj; - THIS->filename = script->str; - current_thread = th_self(); - SG(request_info).query_string = lookup_string_header("QUERY_STRING", 0); - SG(server_context) = (void *)1; /* avoid server_context == NULL */ - - /* path_translated is apparently the absolute path to the file, not - the translated PATH_INFO - */ - SG(request_info).path_translated = - lookup_string_header("SCRIPT_FILENAME", NULL); - SG(request_info).request_uri = lookup_string_header("DOCUMENT_URI", NULL); - if(!SG(request_info).request_uri) - SG(request_info).request_uri = lookup_string_header("SCRIPT_NAME", NULL); - SG(request_info).request_method = lookup_string_header("REQUEST_METHOD", "GET"); - SG(request_info).content_length = lookup_integer_header("HTTP_CONTENT_LENGTH", 0); - SG(request_info).content_type = lookup_string_header("HTTP_CONTENT_TYPE", NULL); - SG(sapi_headers).http_response_code = 200; - - /* FIXME: Check for auth stuff needs to be fixed... */ - SG(request_info).auth_user = NULL; - SG(request_info).auth_password = NULL; - - ind = make_shared_binary_string("my_fd", 5); - raw_fd = low_mapping_string_lookup(THIS->request_data, ind); - if(raw_fd && raw_fd->type == PIKE_T_OBJECT) - { - int fd = fd_from_object(raw_fd->u.object); - if(fd == -1) - php_error(E_WARNING, "PHP5.Interpreter->run: my_fd object not open or not an FD.\n"); - THIS->my_fd = fd; - } else - THIS->my_fd = 0; - - status = php_roxen_module_main(TSRMLS_C); - current_thread = -1; - - apply_svalue(done_callback, 0); - pop_stack(); - pop_n_elems(args); - push_int(status); - PHP_UNLOCK(THIS); -} - - -/* Clear the object global struct */ -static void clear_struct(struct object *o) -{ - MEMSET(Pike_fp->current_storage, 0, sizeof(php_roxen_request)); -} - - -/* - * pike_module_init() is called by Pike once at startup - * - * This functions allocates basic structures - */ - -void pike_module_init( void ) -{ - if (!roxen_php_initialized) { -#ifdef ZTS - tsrm_startup(1, 1, 0, NULL); -#ifdef ROXEN_USE_ZTS - ts_allocate_id(&roxen_globals_id, sizeof(php_roxen_request), NULL, NULL); -#endif -#endif - sapi_startup(&roxen_sapi_module); - /*php_roxen_startup(&roxen_sapi_module); removed - should be called from SAPI activation*/ - roxen_php_initialized = 1; - PHP_INIT_LOCK(); - } - start_new_program(); /* Text */ - ADD_STORAGE(php_roxen_request); - set_init_callback(clear_struct); - pike_add_function("run", f_php_roxen_request_handler, - "function(string, mapping, object, function:int)", 0); - add_program_constant("Interpreter", (php_program = end_program()), 0); -} - -/* - * pike_module_exit() performs the last steps before the - * server exists. Shutdowns basic services and frees memory - */ - -void pike_module_exit(void) -{ - roxen_php_initialized = 0; - roxen_sapi_module.shutdown(&roxen_sapi_module); - if(php_program) free_program(php_program); -#ifdef ZTS - tsrm_shutdown(); -#endif - PHP_DESTROY(); -} -#endif diff --git a/sapi/tests/test005.phpt b/sapi/tests/test005.phpt index 7415b66a0a..85143d5228 100644 --- a/sapi/tests/test005.phpt +++ b/sapi/tests/test005.phpt @@ -22,6 +22,6 @@ END; echo "HELLO"; ?> --EXPECTHEADERS-- -Status: 404 +Status: 404 Not Found --EXPECT-- -No input file specified.
\ No newline at end of file +No input file specified. diff --git a/sapi/tests/test006.phpt b/sapi/tests/test006.phpt index 45e37811ef..16d1b2b840 100644 --- a/sapi/tests/test006.phpt +++ b/sapi/tests/test006.phpt @@ -67,7 +67,7 @@ Array [type] => application/octet-stream [tmp_name] => %s [error] => 0 - [size] => 21 + [size] => 19 ) ) diff --git a/sapi/thttpd/CREDITS b/sapi/thttpd/CREDITS deleted file mode 100644 index 8f02f36f4f..0000000000 --- a/sapi/thttpd/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -thttpd -Sascha Schumann diff --git a/sapi/thttpd/README b/sapi/thttpd/README deleted file mode 100644 index 1e80a01956..0000000000 --- a/sapi/thttpd/README +++ /dev/null @@ -1,85 +0,0 @@ -README FOR THTTPD MODULE (by Sascha Schumann) -($Date$) - - This is a SAPI module for PHP 4.x supporting thttpd, the tiny, - turbo, throttling HTTP server by Jef Poskanzer. - - NOTE: All HTTP requests will be serialized. That means, one long running - script will block all other requests. Choose another web server, - if you want to execute arbitrarily long running scripts. - - The module contains a patch against version 2.21b of thttpd. The patch - fixes a number of bugs and adds some functionality: - - - HTTP/1.1 Persistent Connection/Pipeline Support - - PHP Scripting (**.php by default) - - Highlighting PHP Scripts (**.phps by default) - - Fast Accept Loop (unique to PHP) - - Periodic Connection Expiring (unique to PHP) - - Log to stdout (logfile=-) - - Fixes the Host: header vulnerability (affects vhosts only) - - Asynchronous request body handling (e.g. for POSTs) - - Accept filter for Linux - - Fix for non-blocking sending of thttpd-generated responses - - You can configure the filename extensions by creating a config file for - thttpd and setting these entries: - - phppat=PATTERN - phpspat=PATTERN - - The PATTERN has the same format as defined here: - - http://acme.com/software/thttpd/options.html#CGI_PATTERN - - "**.php" means: match any file ending in .php in any directory. - Setting the pattern from the command line is not supported. - - NOTE: This version supports *only* thttpd 2.21b, no prior or later - version. - - This is a functional and stable module (it runs a large application - like IMP 2.2.0 without any problems). Its original intention was to - demonstrate the ability of PHP to work in every web server environment. - -REQUIRED DOWNLOADS - - 1. thttpd 2.21b (2.20 or +2.22beta will _not_ work) - - Full Distribution: - http://www.acme.com/software/thttpd/thttpd-2.21b.tar.gz - - 2. PHP 4.x - - Download: - http://www.php.net/ - - Snapshots from CVS: - http://snaps.php.net/ - - -BUILD INSTRUCTIONS - - 1. Extract software packages - - $ gunzip -c thttpd-2.xx.tar.gz | tar xf - - $ gunzip -c php-*.tar.gz | tar xf - - - 2. Prepare PHP - - $ cd php-* - $ ./configure \ - --with-thttpd=../thttpd-2.xx \ - <further PHP options> - $ make install - $ cd .. - - You can see the list of valid PHP options by executing - - $ ./configure --help - - 3. Configure, compile, install thttpd - - Now follow the thttpd instructions. The Makefile template of - thttpd was changed to automatically use the components - required by PHP. diff --git a/sapi/thttpd/config.m4 b/sapi/thttpd/config.m4 deleted file mode 100644 index 371edaee84..0000000000 --- a/sapi/thttpd/config.m4 +++ /dev/null @@ -1,39 +0,0 @@ -dnl -dnl $Id$ -dnl - -PHP_ARG_WITH(thttpd,, -[ --with-thttpd=SRCDIR Build PHP as thttpd module], no, no) - -AC_MSG_CHECKING([for thttpd]) - -if test "$PHP_THTTPD" != "no"; then - if test ! -d $PHP_THTTPD; then - AC_MSG_RESULT(thttpd directory does not exist ($PHP_THTTPD)) - fi - - PHP_EXPAND_PATH($PHP_THTTPD, THTTPD) - - if grep thttpd.2.21b $PHP_THTTPD/version.h >/dev/null; then - patch="test -f $THTTPD/php_patched || \ - (cd $THTTPD && patch -p1 < $abs_srcdir/sapi/thttpd/thttpd_patch && touch php_patched)" - - elif grep Premium $PHP_THTTPD/version.h >/dev/null; then - patch= - else - AC_MSG_ERROR([This version only supports thttpd-2.21b and Premium thttpd]) - fi - PHP_TARGET_RDYNAMIC - INSTALL_IT="\ - echo 'PHP_LIBS = -L. -lphp5 \$(PHP_LIBS) \$(EXTRA_LIBS)' > $THTTPD/php_makefile; \ - echo 'PHP_LDFLAGS = \$(NATIVE_RPATHS) \$(PHP_LDFLAGS)' >> $THTTPD/php_makefile; \ - echo 'PHP_CFLAGS = \$(COMMON_FLAGS) \$(CFLAGS_CLEAN) \$(CPPFLAGS) \$(EXTRA_CFLAGS)' >> $THTTPD/php_makefile; \ - rm -f $THTTPD/php_thttpd.c $THTTPD/php_thttpd.h $THTTPD/libphp5.a; \ - \$(LN_S) $abs_srcdir/sapi/thttpd/thttpd.c $THTTPD/php_thttpd.c; \ - \$(LN_S) $abs_srcdir/sapi/thttpd/php_thttpd.h $abs_builddir/$SAPI_STATIC $THTTPD/;\ - $patch" - PHP_THTTPD="yes, using $THTTPD" - PHP_ADD_INCLUDE($THTTPD) - PHP_SELECT_SAPI(thttpd, static) -fi -AC_MSG_RESULT($PHP_THTTPD) diff --git a/sapi/thttpd/php.sym b/sapi/thttpd/php.sym deleted file mode 100644 index 2214d3964d..0000000000 --- a/sapi/thttpd/php.sym +++ /dev/null @@ -1,3 +0,0 @@ -thttpd_php_request -thttpd_php_init -thttpd_php_shutdown diff --git a/sapi/thttpd/stub.c b/sapi/thttpd/stub.c deleted file mode 100644 index e69de29bb2..0000000000 --- a/sapi/thttpd/stub.c +++ /dev/null diff --git a/sapi/thttpd/thttpd.c b/sapi/thttpd/thttpd.c deleted file mode 100644 index 7438ebda19..0000000000 --- a/sapi/thttpd/thttpd.c +++ /dev/null @@ -1,772 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 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> | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#include "php.h" -#include "SAPI.h" -#include "php_main.h" -#include "php_thttpd.h" -#include "php_variables.h" -#include "version.h" -#include "php_ini.h" -#include "zend_highlight.h" - -#include "ext/standard/php_smart_str.h" - -#include <sys/time.h> -#include <sys/types.h> -#include <sys/uio.h> -#include <stdlib.h> -#include <unistd.h> - -#ifdef HAVE_GETNAMEINFO -#include <sys/socket.h> -#include <netdb.h> -#endif - -typedef struct { - httpd_conn *hc; - void (*on_close)(int); - - size_t unconsumed_length; - smart_str sbuf; - int seen_cl; - int seen_cn; -} php_thttpd_globals; - -#define PHP_SYS_CALL(x) do { x } while (n == -1 && errno == EINTR) - -#ifdef PREMIUM_THTTPD -# define do_keep_alive persistent -#endif - -#ifdef ZTS -static int thttpd_globals_id; -#define TG(v) TSRMG(thttpd_globals_id, php_thttpd_globals *, v) -#else -static php_thttpd_globals thttpd_globals; -#define TG(v) (thttpd_globals.v) -#endif - -static int sapi_thttpd_ub_write(const char *str, uint str_length TSRMLS_DC) -{ - int n; - uint sent = 0; - - if (TG(sbuf).c != 0) { - smart_str_appendl_ex(&TG(sbuf), str, str_length, 1); - return str_length; - } - - while (str_length > 0) { - PHP_SYS_CALL(n = send(TG(hc)->conn_fd, str, str_length, 0);); - - if (n == -1) { - if (errno == EAGAIN) { - smart_str_appendl_ex(&TG(sbuf), str, str_length, 1); - - return sent + str_length; - } else - php_handle_aborted_connection(); - } - - TG(hc)->bytes_sent += n; - str += n; - sent += n; - str_length -= n; - } - - return sent; -} - -#define COMBINE_HEADERS 64 - -#if defined(IOV_MAX) -# if IOV_MAX - 64 <= 0 -# define SERIALIZE_HEADERS -# endif -#endif - -static int do_writev(struct iovec *vec, int nvec, int len TSRMLS_DC) -{ - int n; - - assert(nvec <= IOV_MAX); - - if (TG(sbuf).c == 0) { - PHP_SYS_CALL(n = writev(TG(hc)->conn_fd, vec, nvec);); - - if (n == -1) { - if (errno == EAGAIN) { - n = 0; - } else { - php_handle_aborted_connection(); - } - } - - - TG(hc)->bytes_sent += n; - } else { - n = 0; - } - - if (n < len) { - int i; - - /* merge all unwritten data into sbuf */ - for (i = 0; i < nvec; vec++, i++) { - /* has this vector been written completely? */ - if (n >= vec->iov_len) { - /* yes, proceed */ - n -= vec->iov_len; - continue; - } - - if (n > 0) { - /* adjust vector */ - vec->iov_base = (char *) vec->iov_base + n; - vec->iov_len -= n; - n = 0; - } - - smart_str_appendl_ex(&TG(sbuf), vec->iov_base, vec->iov_len, 1); - } - } - - return 0; -} - -#ifdef SERIALIZE_HEADERS -# define ADD_VEC(str,l) smart_str_appendl(&vec_str, (str), (l)) -# define VEC_BASE() smart_str vec_str = {0} -# define VEC_FREE() smart_str_free(&vec_str) -#else -# define ADD_VEC(str,l) vec[n].iov_base=str;len += (vec[n].iov_len=l); n++ -# define VEC_BASE() struct iovec vec[COMBINE_HEADERS] -# define VEC_FREE() do {} while (0) -#endif - -#define ADD_VEC_S(str) ADD_VEC((str), sizeof(str)-1) - -#define CL_TOKEN "Content-length: " -#define CN_TOKEN "Connection: " -#define KA_DO "Connection: keep-alive\r\n" -#define KA_NO "Connection: close\r\n" -#define DEF_CT "Content-Type: text/html\r\n" - -static int sapi_thttpd_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) -{ - char buf[1024], *p; - VEC_BASE(); - int n = 0; - zend_llist_position pos; - sapi_header_struct *h; - size_t len = 0; - - if (!SG(sapi_headers).http_status_line) { - ADD_VEC_S("HTTP/1.1 "); - p = smart_str_print_long(buf+sizeof(buf)-1, - SG(sapi_headers).http_response_code); - ADD_VEC(p, strlen(p)); - ADD_VEC_S(" HTTP\r\n"); - } else { - ADD_VEC(SG(sapi_headers).http_status_line, - strlen(SG(sapi_headers).http_status_line)); - ADD_VEC("\r\n", 2); - } - TG(hc)->status = SG(sapi_headers).http_response_code; - - if (SG(sapi_headers).send_default_content_type) { - ADD_VEC(DEF_CT, strlen(DEF_CT)); - } - - h = zend_llist_get_first_ex(&sapi_headers->headers, &pos); - while (h) { - - switch (h->header[0]) { - case 'c': case 'C': - if (!TG(seen_cl) && strncasecmp(h->header, CL_TOKEN, sizeof(CL_TOKEN)-1) == 0) { - TG(seen_cl) = 1; - } else if (!TG(seen_cn) && strncasecmp(h->header, CN_TOKEN, sizeof(CN_TOKEN)-1) == 0) { - TG(seen_cn) = 1; - } - } - - ADD_VEC(h->header, h->header_len); -#ifndef SERIALIZE_HEADERS - if (n >= COMBINE_HEADERS - 1) { - len = do_writev(vec, n, len TSRMLS_CC); - n = 0; - } -#endif - ADD_VEC("\r\n", 2); - - h = zend_llist_get_next_ex(&sapi_headers->headers, &pos); - } - - if (TG(seen_cl) && !TG(seen_cn) && TG(hc)->do_keep_alive) { - ADD_VEC(KA_DO, sizeof(KA_DO)-1); - } else { - TG(hc)->do_keep_alive = 0; - ADD_VEC(KA_NO, sizeof(KA_NO)-1); - } - - ADD_VEC("\r\n", 2); - -#ifdef SERIALIZE_HEADERS - sapi_thttpd_ub_write(vec_str.c, vec_str.len TSRMLS_CC); -#else - do_writev(vec, n, len TSRMLS_CC); -#endif - - VEC_FREE(); - - return SAPI_HEADER_SENT_SUCCESSFULLY; -} - -/* to understand this, read cgi_interpose_input() in libhttpd.c */ -#define SIZEOF_UNCONSUMED_BYTES() (TG(hc)->read_idx - TG(hc)->checked_idx) -#define CONSUME_BYTES(n) do { TG(hc)->checked_idx += (n); } while (0) - - -static int sapi_thttpd_read_post(char *buffer, uint count_bytes TSRMLS_DC) -{ - size_t read_bytes = 0; - - if (TG(unconsumed_length) > 0) { - read_bytes = MIN(TG(unconsumed_length), count_bytes); - memcpy(buffer, TG(hc)->read_buf + TG(hc)->checked_idx, read_bytes); - TG(unconsumed_length) -= read_bytes; - CONSUME_BYTES(read_bytes); - } - - return read_bytes; -} - -static char *sapi_thttpd_read_cookies(TSRMLS_D) -{ - return TG(hc)->cookie; -} - -#define BUF_SIZE 512 -#define ADD_STRING_EX(name,buf) \ - php_register_variable(name, buf, track_vars_array TSRMLS_CC) -#define ADD_STRING(name) ADD_STRING_EX((name), buf) - -static void sapi_thttpd_register_variables(zval *track_vars_array TSRMLS_DC) -{ - char buf[BUF_SIZE + 1]; - char *p; - - php_register_variable("PHP_SELF", SG(request_info).request_uri, track_vars_array TSRMLS_CC); - php_register_variable("SERVER_SOFTWARE", SERVER_SOFTWARE, track_vars_array TSRMLS_CC); - php_register_variable("GATEWAY_INTERFACE", "CGI/1.1", track_vars_array TSRMLS_CC); - php_register_variable("REQUEST_METHOD", (char *) SG(request_info).request_method, track_vars_array TSRMLS_CC); - php_register_variable("REQUEST_URI", SG(request_info).request_uri, track_vars_array TSRMLS_CC); - php_register_variable("PATH_TRANSLATED", SG(request_info).path_translated, track_vars_array TSRMLS_CC); - - if (TG(hc)->one_one) { - php_register_variable("SERVER_PROTOCOL", "HTTP/1.1", track_vars_array TSRMLS_CC); - } else { - php_register_variable("SERVER_PROTOCOL", "HTTP/1.0", track_vars_array TSRMLS_CC); - } - - p = httpd_ntoa(&TG(hc)->client_addr); - - ADD_STRING_EX("REMOTE_ADDR", p); - ADD_STRING_EX("REMOTE_HOST", p); - - ADD_STRING_EX("SERVER_PORT", - smart_str_print_long(buf + sizeof(buf) - 1, - TG(hc)->hs->port)); - - buf[0] = '/'; - memcpy(buf + 1, TG(hc)->pathinfo, strlen(TG(hc)->pathinfo) + 1); - ADD_STRING("PATH_INFO"); - - buf[0] = '/'; - memcpy(buf + 1, TG(hc)->origfilename, strlen(TG(hc)->origfilename) + 1); - ADD_STRING("SCRIPT_NAME"); - -#define CONDADD(name, field) \ - if (TG(hc)->field[0]) { \ - php_register_variable(#name, TG(hc)->field, track_vars_array TSRMLS_CC); \ - } - - CONDADD(QUERY_STRING, query); - CONDADD(HTTP_HOST, hdrhost); - CONDADD(HTTP_REFERER, referer); - CONDADD(HTTP_USER_AGENT, useragent); - CONDADD(HTTP_ACCEPT, accept); - CONDADD(HTTP_ACCEPT_LANGUAGE, acceptl); - CONDADD(HTTP_ACCEPT_ENCODING, accepte); - CONDADD(HTTP_COOKIE, cookie); - CONDADD(CONTENT_TYPE, contenttype); - CONDADD(REMOTE_USER, remoteuser); - CONDADD(SERVER_PROTOCOL, protocol); - - if (TG(hc)->contentlength != -1) { - ADD_STRING_EX("CONTENT_LENGTH", - smart_str_print_long(buf + sizeof(buf) - 1, - TG(hc)->contentlength)); - } - - if (TG(hc)->authorization[0]) - php_register_variable("AUTH_TYPE", "Basic", track_vars_array TSRMLS_CC); -} - -static PHP_MINIT_FUNCTION(thttpd) -{ - return SUCCESS; -} - -static zend_module_entry php_thttpd_module = { - STANDARD_MODULE_HEADER, - "thttpd", - NULL, - PHP_MINIT(thttpd), - NULL, - NULL, - NULL, - NULL, /* info */ - NULL, - STANDARD_MODULE_PROPERTIES -}; - -static int php_thttpd_startup(sapi_module_struct *sapi_module) -{ -#if PHP_API_VERSION >= 20020918 - if (php_module_startup(sapi_module, &php_thttpd_module, 1) == FAILURE) { -#else - if (php_module_startup(sapi_module) == FAILURE - || zend_startup_module(&php_thttpd_module) == FAILURE) { -#endif - return FAILURE; - } - return SUCCESS; -} - -static int sapi_thttpd_get_fd(int *nfd TSRMLS_DC) -{ - if (nfd) *nfd = TG(hc)->conn_fd; - return SUCCESS; -} - -static sapi_module_struct thttpd_sapi_module = { - "thttpd", - "thttpd", - - php_thttpd_startup, - php_module_shutdown_wrapper, - - NULL, /* activate */ - NULL, /* deactivate */ - - sapi_thttpd_ub_write, - NULL, - NULL, /* get uid */ - NULL, /* getenv */ - - php_error, - - NULL, - sapi_thttpd_send_headers, - NULL, - sapi_thttpd_read_post, - sapi_thttpd_read_cookies, - - sapi_thttpd_register_variables, - NULL, /* Log message */ - NULL, /* Get request time */ - NULL, /* Child terminate */ - - NULL, /* php.ini path override */ - NULL, /* Block interruptions */ - NULL, /* Unblock interruptions */ - - NULL, - NULL, - NULL, - 0, - sapi_thttpd_get_fd -}; - -static void thttpd_module_main(int show_source TSRMLS_DC) -{ - zend_file_handle file_handle; - - if (php_request_startup(TSRMLS_C) == FAILURE) { - return; - } - - if (show_source) { - zend_syntax_highlighter_ini syntax_highlighter_ini; - - php_get_highlight_struct(&syntax_highlighter_ini); - highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini TSRMLS_CC); - } else { - file_handle.type = ZEND_HANDLE_FILENAME; - file_handle.filename = SG(request_info).path_translated; - file_handle.free_filename = 0; - file_handle.opened_path = NULL; - - php_execute_script(&file_handle TSRMLS_CC); - } - - php_request_shutdown(NULL); -} - -static void thttpd_request_ctor(TSRMLS_D) -{ - smart_str s = {0}; - - TG(seen_cl) = 0; - TG(seen_cn) = 0; - TG(sbuf).c = 0; - SG(request_info).query_string = TG(hc)->query?strdup(TG(hc)->query):NULL; - - smart_str_appends_ex(&s, TG(hc)->hs->cwd, 1); - smart_str_appends_ex(&s, TG(hc)->expnfilename, 1); - smart_str_0(&s); - SG(request_info).path_translated = s.c; - - s.c = NULL; - smart_str_appendc_ex(&s, '/', 1); - smart_str_appends_ex(&s, TG(hc)->origfilename, 1); - smart_str_0(&s); - SG(request_info).request_uri = s.c; - SG(request_info).request_method = httpd_method_str(TG(hc)->method); - if (TG(hc)->one_one) SG(request_info).proto_num = 1001; - else SG(request_info).proto_num = 1000; - SG(sapi_headers).http_response_code = 200; - if (TG(hc)->contenttype) - SG(request_info).content_type = strdup(TG(hc)->contenttype); - SG(request_info).content_length = TG(hc)->contentlength == -1 ? 0 - : TG(hc)->contentlength; - - TG(unconsumed_length) = SG(request_info).content_length; - - php_handle_auth_data(TG(hc)->authorization TSRMLS_CC); -} - -static void thttpd_request_dtor(TSRMLS_D) -{ - smart_str_free_ex(&TG(sbuf), 1); - if (SG(request_info).query_string) - free(SG(request_info).query_string); - free(SG(request_info).request_uri); - free(SG(request_info).path_translated); - if (SG(request_info).content_type) - free(SG(request_info).content_type); -} - -#ifdef ZTS - -#ifdef TSRM_ST -#define thread_create_simple_detached(n) st_thread_create(n, NULL, 0, 0) -#define thread_usleep(n) st_usleep(n) -#define thread_exit() st_thread_exit(NULL) -/* No preemption, simple operations are safe */ -#define thread_atomic_inc(n) (++n) -#define thread_atomic_dec(n) (--n) -#else -#error No thread primitives available -#endif - -/* We might want to replace this with a STAILQ */ -typedef struct qreq { - httpd_conn *hc; - struct qreq *next; -} qreq_t; - -static MUTEX_T qr_lock; -static qreq_t *queued_requests; -static qreq_t *last_qr; -static int nr_free_threads; -static int nr_threads; -static int max_threads = 50; - -#define HANDLE_STRINGS() { \ - HANDLE_STR(encodedurl); \ - HANDLE_STR(decodedurl); \ - HANDLE_STR(origfilename); \ - HANDLE_STR(expnfilename); \ - HANDLE_STR(pathinfo); \ - HANDLE_STR(query); \ - HANDLE_STR(referer); \ - HANDLE_STR(useragent); \ - HANDLE_STR(accept); \ - HANDLE_STR(accepte); \ - HANDLE_STR(acceptl); \ - HANDLE_STR(cookie); \ - HANDLE_STR(contenttype); \ - HANDLE_STR(authorization); \ - HANDLE_STR(remoteuser); \ - } - -static httpd_conn *duplicate_conn(httpd_conn *hc, httpd_conn *nhc) -{ - memcpy(nhc, hc, sizeof(*nhc)); - -#define HANDLE_STR(m) nhc->m = nhc->m ? strdup(nhc->m) : NULL - HANDLE_STRINGS(); -#undef HANDLE_STR - - return nhc; -} - -static void destroy_conn(httpd_conn *hc) -{ -#define HANDLE_STR(m) if (hc->m) free(hc->m) - HANDLE_STRINGS(); -#undef HANDLE_STR -} - -static httpd_conn *dequeue_request(void) -{ - httpd_conn *ret = NULL; - qreq_t *m; - - tsrm_mutex_lock(qr_lock); - if (queued_requests) { - m = queued_requests; - ret = m->hc; - if (!(queued_requests = m->next)) - last_qr = NULL; - free(m); - } - tsrm_mutex_unlock(qr_lock); - - return ret; -} - -static void *worker_thread(void *); - -static void queue_request(httpd_conn *hc) -{ - qreq_t *m; - httpd_conn *nhc; - - /* Mark as long-running request */ - hc->file_address = (char *) 1; - - /* - * We cannot synchronously revoke accesses to hc in the worker - * thread, so we need to pass a copy of hc to the worker thread. - */ - nhc = malloc(sizeof *nhc); - duplicate_conn(hc, nhc); - - /* Allocate request queue container */ - m = malloc(sizeof *m); - m->hc = nhc; - m->next = NULL; - - tsrm_mutex_lock(qr_lock); - /* Create new threads when reaching a certain threshold */ - if (nr_threads < max_threads && nr_free_threads < 2) { - nr_threads++; /* protected by qr_lock */ - - thread_atomic_inc(nr_free_threads); - thread_create_simple_detached(worker_thread); - } - /* Insert container into request queue */ - if (queued_requests) - last_qr->next = m; - else - queued_requests = m; - last_qr = m; - tsrm_mutex_unlock(qr_lock); -} - -static off_t thttpd_real_php_request(httpd_conn *hc, int TSRMLS_DC); - -static void *worker_thread(void *dummy) -{ - int do_work = 50; - httpd_conn *hc; - - while (do_work) { - hc = dequeue_request(); - - if (!hc) { -/* do_work--; */ - thread_usleep(500000); - continue; - } -/* do_work = 50; */ - - thread_atomic_dec(nr_free_threads); - - thttpd_real_php_request(hc, 0 TSRMLS_CC); - shutdown(hc->conn_fd, 0); - destroy_conn(hc); - free(hc); - - thread_atomic_inc(nr_free_threads); - } - thread_atomic_dec(nr_free_threads); - thread_atomic_dec(nr_threads); - thread_exit(); -} - -static void remove_dead_conn(int fd) -{ - qreq_t *m, *prev = NULL; - - tsrm_mutex_lock(qr_lock); - m = queued_requests; - while (m) { - if (m->hc->conn_fd == fd) { - if (prev) - if (!(prev->next = m->next)) - last_qr = prev; - else - if (!(queued_requests = m->next)) - last_qr = NULL; - destroy_conn(m->hc); - free(m->hc); - free(m); - break; - } - prev = m; - m = m->next; - } - tsrm_mutex_unlock(qr_lock); -} - -#endif - -static off_t thttpd_real_php_request(httpd_conn *hc, int show_source TSRMLS_DC) -{ - TG(hc) = hc; - hc->bytes_sent = 0; - - if (hc->contentlength != -1) { - hc->should_linger = 1; - hc->do_keep_alive = 0; - } - - if (hc->contentlength != -1 - && SIZEOF_UNCONSUMED_BYTES() < hc->contentlength) { - hc->read_body_into_mem = 1; - return 0; - } - - thttpd_request_ctor(TSRMLS_C); - - thttpd_module_main(show_source TSRMLS_CC); - - /* disable kl, if no content-length was seen or Connection: was set */ - if (TG(seen_cl) == 0 || TG(seen_cn) == 1) { - TG(hc)->do_keep_alive = 0; - } - - if (TG(sbuf).c != 0) { - if (TG(hc)->response) - free(TG(hc)->response); - - TG(hc)->response = TG(sbuf).c; - TG(hc)->responselen = TG(sbuf).len; - TG(hc)->maxresponse = TG(sbuf).a; - - TG(sbuf).c = 0; - TG(sbuf).len = 0; - TG(sbuf).a = 0; - } - - thttpd_request_dtor(TSRMLS_C); - - return 0; -} - -off_t thttpd_php_request(httpd_conn *hc, int show_source) -{ -#ifdef ZTS - queue_request(hc); -#else - TSRMLS_FETCH(); - return thttpd_real_php_request(hc, show_source TSRMLS_CC); -#endif -} - -void thttpd_register_on_close(void (*arg)(int)) -{ - TSRMLS_FETCH(); - TG(on_close) = arg; -} - -void thttpd_closed_conn(int fd) -{ - TSRMLS_FETCH(); - if (TG(on_close)) TG(on_close)(fd); -} - -int thttpd_get_fd(void) -{ - TSRMLS_FETCH(); - return TG(hc)->conn_fd; -} - -void thttpd_set_dont_close(void) -{ - TSRMLS_FETCH(); -#ifndef PREMIUM_THTTPD - TG(hc)->file_address = (char *) 1; -#endif -} - - -void thttpd_php_init(void) -{ - char *ini; - -#ifdef ZTS - tsrm_startup(1, 1, 0, NULL); - ts_allocate_id(&thttpd_globals_id, sizeof(php_thttpd_globals), NULL, NULL); - qr_lock = tsrm_mutex_alloc(); - thttpd_register_on_close(remove_dead_conn); -#endif - - if ((ini = getenv("PHP_INI_PATH"))) { - thttpd_sapi_module.php_ini_path_override = ini; - } - - sapi_startup(&thttpd_sapi_module); - thttpd_sapi_module.startup(&thttpd_sapi_module); - - { - TSRMLS_FETCH(); - - SG(server_context) = (void *) 1; - } -} - -void thttpd_php_shutdown(void) -{ - TSRMLS_FETCH(); - - if (SG(server_context) != NULL) { - thttpd_sapi_module.shutdown(&thttpd_sapi_module); - sapi_shutdown(); -#ifdef ZTS - tsrm_shutdown(); -#endif - } -} diff --git a/sapi/thttpd/thttpd_patch b/sapi/thttpd/thttpd_patch deleted file mode 100644 index f6e45d5f15..0000000000 --- a/sapi/thttpd/thttpd_patch +++ /dev/null @@ -1,2377 +0,0 @@ -diff -ur thttpd-2.21b/Makefile.in thttpd-2.21b-cool/Makefile.in ---- thttpd-2.21b/Makefile.in Thu Mar 29 20:36:21 2001 -+++ thttpd-2.21b-cool/Makefile.in Sat Sep 20 14:43:20 2003 -@@ -46,13 +46,15 @@ - - # You shouldn't need to edit anything below here. - -+include php_makefile -+ - CC = @CC@ - CCOPT = @V_CCOPT@ - DEFS = @DEFS@ --INCLS = -I. -+INCLS = -I. $(PHP_CFLAGS) - CFLAGS = $(CCOPT) $(DEFS) $(INCLS) --LDFLAGS = @LDFLAGS@ --LIBS = @LIBS@ -+LDFLAGS = @LDFLAGS@ $(PHP_LDFLAGS) -+LIBS = @LIBS@ $(PHP_LIBS) - NETLIBS = @V_NETLIBS@ - INSTALL = @INSTALL@ - -@@ -62,7 +64,7 @@ - @rm -f $@ - $(CC) $(CFLAGS) -c $*.c - --SRC = thttpd.c libhttpd.c fdwatch.c mmc.c timers.c match.c tdate_parse.c syslog.c -+SRC = thttpd.c libhttpd.c fdwatch.c mmc.c timers.c match.c tdate_parse.c syslog.c php_thttpd.c - - OBJ = $(SRC:.c=.o) @LIBOBJS@ - -@@ -77,7 +79,7 @@ - all: this subdirs - this: $(ALL) - --thttpd: $(OBJ) -+thttpd: $(OBJ) libphp5.a - @rm -f $@ - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(NETLIBS) - -diff -ur thttpd-2.21b/config.h thttpd-2.21b-cool/config.h ---- thttpd-2.21b/config.h Mon Apr 9 23:57:36 2001 -+++ thttpd-2.21b-cool/config.h Sat Sep 20 14:43:20 2003 -@@ -82,6 +82,11 @@ - */ - #define IDLE_READ_TIMELIMIT 60 - -+/* CONFIGURE: How many seconds to allow for reading the subsequent requests -+** on a keep-alive connection. Should be simiar to LINGER_TIME -+*/ -+#define IDLE_KEEPALIVE_TIMELIMIT 2 -+ - /* CONFIGURE: How many seconds before an idle connection gets closed. - */ - #define IDLE_SEND_TIMELIMIT 300 -@@ -316,7 +321,7 @@ - /* CONFIGURE: A list of index filenames to check. The files are searched - ** for in this order. - */ --#define INDEX_NAMES "index.html", "index.htm", "Default.htm", "index.cgi" -+#define INDEX_NAMES "index.php", "index.html", "index.htm", "Default.htm", "index.cgi" - - /* CONFIGURE: If this is defined then thttpd will automatically generate - ** index pages for directories that don't have an explicit index file. -diff -ur thttpd-2.21b/configure thttpd-2.21b-cool/configure ---- thttpd-2.21b/configure Sat Apr 21 02:07:14 2001 -+++ thttpd-2.21b-cool/configure Sat Sep 20 14:43:20 2003 -@@ -1021,7 +1021,7 @@ - fi - echo "$ac_t""$CPP" 1>&6 - --for ac_hdr in fcntl.h grp.h memory.h paths.h poll.h sys/poll.h sys/event.h osreldate.h -+for ac_hdr in fcntl.h grp.h memory.h paths.h poll.h sys/poll.h sys/event.h osreldate.h netinet/tcp.h - do - ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` - echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -diff -ur thttpd-2.21b/configure.in thttpd-2.21b-cool/configure.in ---- thttpd-2.21b/configure.in Sat Apr 21 02:06:23 2001 -+++ thttpd-2.21b-cool/configure.in Sat Sep 20 14:43:20 2003 -@@ -64,7 +64,7 @@ - AC_MSG_RESULT(no) - fi - --AC_CHECK_HEADERS(fcntl.h grp.h memory.h paths.h poll.h sys/poll.h sys/event.h osreldate.h) -+AC_CHECK_HEADERS(fcntl.h grp.h memory.h paths.h poll.h sys/poll.h sys/event.h osreldate.h netinet/tcp.h) - AC_HEADER_TIME - AC_HEADER_DIRENT - -diff -ur thttpd-2.21b/fdwatch.c thttpd-2.21b-cool/fdwatch.c ---- thttpd-2.21b/fdwatch.c Fri Apr 13 07:36:08 2001 -+++ thttpd-2.21b-cool/fdwatch.c Sat Sep 20 14:43:20 2003 -@@ -419,6 +419,7 @@ - if ( pollfds == (struct pollfd*) 0 || poll_fdidx == (int*) 0 || - poll_rfdidx == (int*) 0 ) - return -1; -+ memset(pollfds, 0, sizeof(struct pollfd) * nfiles); - return 0; - } - -@@ -460,7 +461,7 @@ - - ridx = 0; - for ( i = 0; i < npollfds; ++i ) -- if ( pollfds[i].revents & ( POLLIN | POLLOUT ) ) -+ if ( pollfds[i].revents & ( POLLIN | POLLOUT | POLLERR | POLLHUP | POLLNVAL ) ) - poll_rfdidx[ridx++] = pollfds[i].fd; - - return r; -@@ -472,8 +473,8 @@ - { - switch ( fd_rw[fd] ) - { -- case FDW_READ: return pollfds[poll_fdidx[fd]].revents & POLLIN; -- case FDW_WRITE: return pollfds[poll_fdidx[fd]].revents & POLLOUT; -+ case FDW_READ: return pollfds[poll_fdidx[fd]].revents & ( POLLIN | POLLERR | POLLHUP | POLLNVAL ); -+ case FDW_WRITE: return pollfds[poll_fdidx[fd]].revents & ( POLLOUT | POLLERR | POLLHUP | POLLNVAL ); - default: return 0; - } - } -diff -ur thttpd-2.21b/libhttpd.c thttpd-2.21b-cool/libhttpd.c ---- thttpd-2.21b/libhttpd.c Tue Apr 24 00:42:40 2001 -+++ thttpd-2.21b-cool/libhttpd.c Sat Sep 20 14:43:29 2003 -@@ -56,6 +56,10 @@ - #include <unistd.h> - #include <stdarg.h> - -+#ifdef HAVE_NETINET_TCP_H -+#include <netinet/tcp.h> -+#endif -+ - #ifdef HAVE_OSRELDATE_H - #include <osreldate.h> - #endif /* HAVE_OSRELDATE_H */ -@@ -85,6 +89,12 @@ - #include "match.h" - #include "tdate_parse.h" - -+#include "php_thttpd.h" -+ -+#ifdef __CYGWIN__ -+# define timezone _timezone -+#endif -+ - #ifndef STDIN_FILENO - #define STDIN_FILENO 0 - #endif -@@ -111,7 +121,7 @@ - static int initialize_listen_socket( httpd_sockaddr* saP ); - static void unlisten( httpd_server* hs ); - static void add_response( httpd_conn* hc, char* str ); --static void send_mime( httpd_conn* hc, int status, char* title, char* encodings, char* extraheads, char* type, int length, time_t mod ); -+static void send_mime( httpd_conn* hc, int status, char* title, char* encodings, char* extraheads, char* type, int length, time_t mod, const char *, size_t ); - static void send_response( httpd_conn* hc, int status, char* title, char* extraheads, char* form, char* arg ); - static void send_response_tail( httpd_conn* hc ); - static void defang( char* str, char* dfstr, int dfsize ); -@@ -242,6 +252,10 @@ - free( (void*) hs->cwd ); - if ( hs->cgi_pattern != (char*) 0 ) - free( (void*) hs->cgi_pattern ); -+ if ( hs->php_pattern != (char*) 0 ) -+ free( (void*) hs->php_pattern ); -+ if ( hs->phps_pattern != (char*) 0 ) -+ free( (void*) hs->phps_pattern ); - if ( hs->charset != (char*) 0 ) - free( (void*) hs->charset ); - if ( hs->url_pattern != (char*) 0 ) -@@ -249,6 +263,7 @@ - if ( hs->local_pattern != (char*) 0 ) - free( (void*) hs->local_pattern ); - free( (void*) hs ); -+ thttpd_php_shutdown(); - } - - -@@ -257,7 +272,8 @@ - char* hostname, httpd_sockaddr* sa4P, httpd_sockaddr* sa6P, int port, - char* cgi_pattern, char* charset, char* cwd, int no_log, FILE* logfp, - int no_symlink, int vhost, int global_passwd, char* url_pattern, -- char* local_pattern, int no_empty_referers ) -+ char* local_pattern, int no_empty_referers, char* php_pattern, -+ char* phps_pattern ) - { - httpd_server* hs; - static char ghnbuf[256]; -@@ -312,6 +328,8 @@ - } - - hs->port = port; -+ hs->php_pattern = strdup(php_pattern); -+ hs->phps_pattern = strdup(phps_pattern); - if ( cgi_pattern == (char*) 0 ) - hs->cgi_pattern = (char*) 0; - else -@@ -329,7 +347,7 @@ - while ( ( cp = strstr( hs->cgi_pattern, "|/" ) ) != (char*) 0 ) - (void) strcpy( cp + 1, cp + 2 ); - } -- hs->charset = strdup( charset ); -+ hs->charset = strdup( charset ); - hs->cwd = strdup( cwd ); - if ( hs->cwd == (char*) 0 ) - { -@@ -385,6 +403,8 @@ - return (httpd_server*) 0; - } - -+ thttpd_php_init(); -+ - /* Done initializing. */ - if ( hs->binding_hostname == (char*) 0 ) - syslog( LOG_INFO, "%.80s starting on port %d", SERVER_SOFTWARE, hs->port ); -@@ -418,6 +438,11 @@ - } - (void) fcntl( listen_fd, F_SETFD, 1 ); - -+#if defined(TCP_DEFER_ACCEPT) && defined(SOL_TCP) -+ on = 30; /* give clients 30s to send first data packet */ -+ setsockopt(listen_fd, SOL_TCP, TCP_DEFER_ACCEPT, &on, sizeof(on)); -+#endif -+ - /* Allow reuse of local addresses. */ - on = 1; - if ( setsockopt( -@@ -582,6 +607,9 @@ - /* And send it, if necessary. */ - if ( hc->responselen > 0 ) - { -+/* -+printf("**RESPONSE [%d]** len = %d\n%*.*s\n", hc->conn_fd, hc->responselen, hc->responselen, hc->responselen, hc->response); -+*/ - (void) write( hc->conn_fd, hc->response, hc->responselen ); - hc->responselen = 0; - } -@@ -619,18 +647,22 @@ - } - } - -+extern time_t httpd_time_now; -+extern char httpd_now_buf[]; -+ -+#define SMART_STR_USE_REALLOC -+ -+#include "ext/standard/php_smart_str.h" - - static void --send_mime( httpd_conn* hc, int status, char* title, char* encodings, char* extraheads, char* type, int length, time_t mod ) -+send_mime( httpd_conn* hc, int status, char* title, char* encodings, char* extraheads, char* type, int length, time_t mod, const char *last_modified, size_t last_modified_len) - { -- time_t now; - const char* rfc1123fmt = "%a, %d %b %Y %H:%M:%S GMT"; -- char nowbuf[100]; - char modbuf[100]; -- char fixed_type[500]; -- char buf[1000]; - int partial_content; -- -+ smart_str s = {0}; -+ int type_len; -+ - hc->status = status; - hc->bytes_to_send = length; - if ( hc->mime_flag ) -@@ -649,41 +681,89 @@ - else - partial_content = 0; - -- now = time( (time_t*) 0 ); - if ( mod == (time_t) 0 ) -- mod = now; -- (void) strftime( nowbuf, sizeof(nowbuf), rfc1123fmt, gmtime( &now ) ); -- (void) strftime( modbuf, sizeof(modbuf), rfc1123fmt, gmtime( &mod ) ); -- (void) my_snprintf( -- fixed_type, sizeof(fixed_type), type, hc->hs->charset ); -- (void) my_snprintf( buf, sizeof(buf), -- "%.20s %d %s\r\nServer: %s\r\nContent-Type: %s\r\nDate: %s\r\nLast-Modified: %s\r\nAccept-Ranges: bytes\r\nConnection: close\r\n", -- hc->protocol, status, title, EXPOSED_SERVER_SOFTWARE, fixed_type, -- nowbuf, modbuf ); -- add_response( hc, buf ); -+ mod = httpd_time_now; -+ -+ if (last_modified == 0) { -+ (void) strftime( modbuf, sizeof(modbuf), rfc1123fmt, gmtime( &mod ) ); -+ last_modified = modbuf; -+ last_modified_len = strlen(modbuf); -+ } -+ -+ type_len = strlen(type); -+ -+ if (hc->response) { -+ s.c = hc->response; -+ s.len = 0; -+ s.a = hc->maxresponse; -+ hc->response = 0; -+ hc->maxresponse = 0; -+ } -+ -+ smart_str_appends(&s, "HTTP/1.1 "); -+ smart_str_append_long(&s, status); -+ smart_str_appends(&s, " HTTP\r\nServer: " EXPOSED_SERVER_SOFTWARE "\r\n" -+ "Content-Type: "); -+ -+ if (type[type_len-2] == '%' && type[type_len-1] == 's') { -+ smart_str_appendl(&s, type, type_len - 2); -+ smart_str_appends(&s, hc->hs->charset); -+ } else { -+ smart_str_appendl(&s, type, type_len); -+ } -+ -+ -+ smart_str_appends(&s, "\r\nDate: "); -+ smart_str_appends(&s, httpd_now_buf); -+ smart_str_appends(&s, "\r\nLast-Modified: "); -+ smart_str_appendl(&s, last_modified, last_modified_len); -+ smart_str_appends(&s, "\r\nAccept-Ranges: bytes\r\n"); -+ - if ( encodings[0] != '\0' ) - { -- (void) my_snprintf( buf, sizeof(buf), -- "Content-Encoding: %s\r\n", encodings ); -- add_response( hc, buf ); -+ smart_str_appends(&s, "Content-Encoding: "); -+ smart_str_appends(&s, encodings); -+ smart_str_appends(&s, "\r\n"); - } - if ( partial_content ) - { -- (void) my_snprintf( buf, sizeof(buf), -- "Content-Range: bytes %ld-%ld/%d\r\nContent-Length: %ld\r\n", -- (long) hc->init_byte_loc, (long) hc->end_byte_loc, length, -- (long) ( hc->end_byte_loc - hc->init_byte_loc + 1 ) ); -- add_response( hc, buf ); -+ -+ smart_str_appends(&s, "Content-Range: bytes "); -+ smart_str_append_long(&s, hc->init_byte_loc); -+ smart_str_appendc(&s, '-'); -+ smart_str_append_long(&s, hc->end_byte_loc); -+ smart_str_appendc(&s, '/'); -+ smart_str_append_long(&s, length); -+ smart_str_appends(&s, "\r\nContent-Length: "); -+ smart_str_append_long(&s, hc->end_byte_loc - hc->init_byte_loc + 1); -+ smart_str_appends(&s, "\r\n"); -+ - } - else if ( length >= 0 ) - { -- (void) my_snprintf( buf, sizeof(buf), -- "Content-Length: %d\r\n", length ); -- add_response( hc, buf ); -+ smart_str_appends(&s, "Content-Length: "); -+ smart_str_append_long(&s, length); -+ smart_str_appends(&s, "\r\n"); - } -+ else { -+ hc->do_keep_alive = 0; -+ } - if ( extraheads[0] != '\0' ) -- add_response( hc, extraheads ); -- add_response( hc, "\r\n" ); -+ smart_str_appends(&s, extraheads); -+ if (hc->do_keep_alive) { -+ smart_str_appends(&s, "Connection: keep-alive\r\n\r\n" ); -+ } else { -+ smart_str_appends(&s, "Connection: close\r\n\r\n" ); -+ } -+ smart_str_0(&s); -+ -+ if (hc->response) { -+ free(hc->response); -+ } -+ hc->response = s.c; -+ hc->maxresponse = s.a; -+ hc->responselen = s.len; -+ - } - } - -@@ -725,7 +805,7 @@ - { - char defanged_arg[1000], buf[2000]; - -- send_mime( hc, status, title, "", extraheads, "text/html", -1, 0 ); -+ send_mime( hc, status, title, "", extraheads, "text/html", -1, 0, 0, 0 ); - (void) my_snprintf( buf, sizeof(buf), - "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n<BODY BGCOLOR=\"#cc9999\"><H2>%d %s</H2>\n", - status, title, status, title ); -@@ -764,7 +844,7 @@ - char* cp2; - - for ( cp1 = str, cp2 = dfstr; -- *cp1 != '\0' && cp2 - dfstr < dfsize - 1; -+ *cp1 != '\0' && cp2 - dfstr < dfsize - 5; - ++cp1, ++cp2 ) - { - switch ( *cp1 ) -@@ -834,7 +914,7 @@ - fp = fopen( filename, "r" ); - if ( fp == (FILE*) 0 ) - return 0; -- send_mime( hc, status, title, "", extraheads, "text/html", -1, 0 ); -+ send_mime( hc, status, title, "", extraheads, "text/html", -1, 0, 0, 0 ); - for (;;) - { - r = fread( buf, 1, sizeof(buf) - 1, fp ); -@@ -1336,6 +1416,9 @@ - if ( hc->tildemapped ) - return 1; - -+ if ( hc->hostname[0] == '.' || strchr( hc->hostname, '/' ) != (char*) 0 ) -+ return 0; -+ - /* Figure out the host directory. */ - #ifdef VHOST_DIRLEVELS - httpd_realloc_str( -@@ -1436,7 +1519,7 @@ - restlen = strlen( path ); - httpd_realloc_str( &rest, &maxrest, restlen ); - (void) strcpy( rest, path ); -- if ( rest[restlen - 1] == '/' ) -+ if ( restlen > 0 && rest[restlen - 1] == '/' ) - rest[--restlen] = '\0'; /* trim trailing slash */ - if ( ! tildemapped ) - /* Remove any leading slashes. */ -@@ -1603,6 +1686,70 @@ - - - int -+httpd_request_reset(httpd_conn* hc, int preserve_read_buf ) -+{ -+ if (!preserve_read_buf) { -+ hc->read_idx = 0; -+ hc->checked_idx = 0; -+ } -+ -+ if (hc->read_buf_is_mmap) { -+ hc->read_buf_is_mmap = 0; -+ munmap(hc->read_buf, hc->read_size); -+ hc->read_buf = NULL; -+ hc->read_size = 0; -+ httpd_realloc_str( &hc->read_buf, &hc->read_size, 500 ); -+ } -+ hc->checked_state = CHST_FIRSTWORD; -+ hc->method = METHOD_UNKNOWN; -+ hc->status = 0; -+ hc->bytes_to_send = 0; -+ hc->bytes_sent = 0; -+ hc->encodedurl = ""; -+ hc->decodedurl[0] = '\0'; -+ hc->protocol = "UNKNOWN"; -+ hc->origfilename[0] = '\0'; -+ hc->expnfilename[0] = '\0'; -+ hc->encodings[0] = '\0'; -+ hc->pathinfo[0] = '\0'; -+ hc->query[0] = '\0'; -+ hc->referer = ""; -+ hc->useragent = ""; -+ hc->accept[0] = '\0'; -+ hc->accepte[0] = '\0'; -+ hc->acceptl = ""; -+ hc->cookie = ""; -+ hc->contenttype = ""; -+ hc->reqhost[0] = '\0'; -+ hc->hdrhost = ""; -+ hc->hostdir[0] = '\0'; -+ hc->authorization = ""; -+ hc->remoteuser[0] = '\0'; -+ hc->response[0] = '\0'; -+#ifdef TILDE_MAP_2 -+ hc->altdir[0] = '\0'; -+#endif /* TILDE_MAP_2 */ -+ hc->responselen = 0; -+ hc->if_modified_since = (time_t) -1; -+ hc->range_if = (time_t) -1; -+ hc->contentlength = -1; -+ hc->type = ""; -+ hc->hostname = (char*) 0; -+ hc->mime_flag = 1; -+ hc->one_one = 0; -+ hc->got_range = 0; -+ hc->tildemapped = 0; -+ hc->init_byte_loc = 0; -+ hc->end_byte_loc = -1; -+ hc->keep_alive = 0; -+ hc->do_keep_alive = 0; -+ hc->should_linger = 0; -+ hc->file_address = (char*) 0; -+ hc->read_body_into_mem = 0; -+ return GC_OK; -+} -+ -+int - httpd_get_conn( httpd_server* hs, int listen_fd, httpd_conn* hc ) - { - httpd_sockaddr sa; -@@ -1612,6 +1759,7 @@ - { - hc->read_size = 0; - httpd_realloc_str( &hc->read_buf, &hc->read_size, 500 ); -+ hc->read_buf_is_mmap = 0; - hc->maxdecodedurl = - hc->maxorigfilename = hc->maxexpnfilename = hc->maxencodings = - hc->maxpathinfo = hc->maxquery = hc->maxaccept = -@@ -1631,12 +1779,19 @@ - httpd_realloc_str( &hc->reqhost, &hc->maxreqhost, 0 ); - httpd_realloc_str( &hc->hostdir, &hc->maxhostdir, 0 ); - httpd_realloc_str( &hc->remoteuser, &hc->maxremoteuser, 0 ); -- httpd_realloc_str( &hc->response, &hc->maxresponse, 0 ); -+ httpd_realloc_str( &hc->response, &hc->maxresponse, 350 ); - #ifdef TILDE_MAP_2 - httpd_realloc_str( &hc->altdir, &hc->maxaltdir, 0 ); - #endif /* TILDE_MAP_2 */ - hc->initialized = 1; - } -+ if (hc->read_buf_is_mmap) { -+ hc->read_buf_is_mmap = 0; -+ munmap(hc->read_buf, hc->read_size); -+ hc->read_buf = NULL; -+ hc->read_size = 0; -+ httpd_realloc_str( &hc->read_buf, &hc->read_size, 500 ); -+ } - - /* Accept the new connection. */ - sz = sizeof(sa); -@@ -1657,53 +1812,12 @@ - hc->hs = hs; - memset( &hc->client_addr, 0, sizeof(hc->client_addr) ); - memcpy( &hc->client_addr, &sa, sockaddr_len( &sa ) ); -- hc->read_idx = 0; -- hc->checked_idx = 0; -- hc->checked_state = CHST_FIRSTWORD; -- hc->method = METHOD_UNKNOWN; -- hc->status = 0; -- hc->bytes_to_send = 0; -- hc->bytes_sent = 0; -- hc->encodedurl = ""; -- hc->decodedurl[0] = '\0'; -- hc->protocol = "UNKNOWN"; -- hc->origfilename[0] = '\0'; -- hc->expnfilename[0] = '\0'; -- hc->encodings[0] = '\0'; -- hc->pathinfo[0] = '\0'; -- hc->query[0] = '\0'; -- hc->referer = ""; -- hc->useragent = ""; -- hc->accept[0] = '\0'; -- hc->accepte[0] = '\0'; -- hc->acceptl = ""; -- hc->cookie = ""; -- hc->contenttype = ""; -- hc->reqhost[0] = '\0'; -- hc->hdrhost = ""; -- hc->hostdir[0] = '\0'; -- hc->authorization = ""; -- hc->remoteuser[0] = '\0'; -- hc->response[0] = '\0'; --#ifdef TILDE_MAP_2 -- hc->altdir[0] = '\0'; --#endif /* TILDE_MAP_2 */ -- hc->responselen = 0; -- hc->if_modified_since = (time_t) -1; -- hc->range_if = (time_t) -1; -- hc->contentlength = -1; -- hc->type = ""; -- hc->hostname = (char*) 0; -- hc->mime_flag = 1; -- hc->one_one = 0; -- hc->got_range = 0; -- hc->tildemapped = 0; -- hc->init_byte_loc = 0; -- hc->end_byte_loc = -1; -- hc->keep_alive = 0; -- hc->should_linger = 0; -- hc->file_address = (char*) 0; -- return GC_OK; -+ -+/* -+printf("doing httpd_get_con(%d)\n", hc->conn_fd); -+*/ -+ -+ return httpd_request_reset(hc, 0); - } - - -@@ -1720,6 +1834,9 @@ - { - char c; - -+/* -+printf("**REQUEST [%d]**\n%*.*s\n", hc->conn_fd, hc->read_idx, hc->read_idx, hc->read_buf); -+*/ - for ( ; hc->checked_idx < hc->read_idx; ++hc->checked_idx ) - { - c = hc->read_buf[hc->checked_idx]; -@@ -1912,8 +2029,11 @@ - eol = strpbrk( protocol, " \t\n\r" ); - if ( eol != (char*) 0 ) - *eol = '\0'; -- if ( strcasecmp( protocol, "HTTP/1.0" ) != 0 ) -+ if ( strcasecmp( protocol, "HTTP/1.0" ) != 0 ) { - hc->one_one = 1; -+ hc->keep_alive = 1; -+ hc->do_keep_alive = 1; -+ } - } - } - /* Check for HTTP/1.1 absolute URL. */ -@@ -2129,6 +2249,7 @@ - cp = &buf[11]; - cp += strspn( cp, " \t" ); - if ( strcasecmp( cp, "keep-alive" ) == 0 ) -+ hc->do_keep_alive = 1; - hc->keep_alive = 1; - } - #ifdef LOG_UNKNOWN_HEADERS -@@ -2168,6 +2289,9 @@ - } - } - -+/* -+printf("one_one = %d keep_alive = %d\n", hc->one_one, hc->keep_alive); -+*/ - if ( hc->one_one ) - { - /* Check that HTTP/1.1 requests specify a host, as required. */ -@@ -2177,14 +2301,14 @@ - return -1; - } - -- /* If the client wants to do keep-alives, it might also be doing -- ** pipelining. There's no way for us to tell. Since we don't -- ** implement keep-alives yet, if we close such a connection there -- ** might be unread pipelined requests waiting. So, we have to -- ** do a lingering close. -+ /* -+ ** Disable keep alive support for bad browsers, -+ ** list taken from Apache 1.3.19 - */ -- if ( hc->keep_alive ) -- hc->should_linger = 1; -+ if ( hc->do_keep_alive && -+ ( strstr(hc->useragent, "Mozilla/2") != NULL || -+ strstr(hc->useragent, "MSIE 4.0b2;") != NULL)) -+ hc->do_keep_alive = 0; - } - - /* Ok, the request has been parsed. Now we resolve stuff that -@@ -2349,15 +2473,24 @@ - - - void --httpd_close_conn( httpd_conn* hc, struct timeval* nowP ) -- { -- make_log_entry( hc, nowP ); -+httpd_complete_request( httpd_conn* hc, struct timeval* nowP) -+{ -+ if (hc->method != METHOD_UNKNOWN) -+ make_log_entry( hc, nowP ); - -- if ( hc->file_address != (char*) 0 ) -+ if ( hc->file_address == (char*) 1 ) -+ { -+ thttpd_closed_conn(hc->conn_fd); -+ } else if ( hc->file_address != (char*) 0 ) - { - mmc_unmap( hc->file_address, &(hc->sb), nowP ); - hc->file_address = (char*) 0; - } -+ } -+ -+void -+httpd_close_conn( httpd_conn* hc, struct timeval* nowP ) -+{ - if ( hc->conn_fd >= 0 ) - { - (void) close( hc->conn_fd ); -@@ -2370,7 +2503,12 @@ - { - if ( hc->initialized ) - { -- free( (void*) hc->read_buf ); -+ -+ if ( hc->read_buf_is_mmap ) { -+ munmap( hc->read_buf, hc->read_size ); -+ } else { -+ free( (void*) hc->read_buf ); -+ } - free( (void*) hc->decodedurl ); - free( (void*) hc->origfilename ); - free( (void*) hc->expnfilename ); -@@ -2556,7 +2694,7 @@ - return -1; - } - -- send_mime( hc, 200, ok200title, "", "", "text/html", -1, hc->sb.st_mtime ); -+ send_mime( hc, 200, ok200title, "", "", "text/html", -1, hc->sb.st_mtime, 0, 0 ); - if ( hc->method == METHOD_HEAD ) - closedir( dirp ); - else if ( hc->method == METHOD_GET ) -@@ -3026,11 +3164,9 @@ - post_post_garbage_hack( httpd_conn* hc ) - { - char buf[2]; -- int r; - -- r = recv( hc->conn_fd, buf, sizeof(buf), MSG_PEEK ); -- if ( r > 0 ) -- (void) read( hc->conn_fd, buf, r ); -+ fcntl(hc->conn_fd, F_SETFL, O_NONBLOCK); -+ (void) read( hc->conn_fd, buf, 2 ); - } - - -@@ -3313,6 +3449,11 @@ - int r; - ClientData client_data; - -+ /* -+ ** We are not going to leave the socket open after a CGI... too hard -+ */ -+ hc->do_keep_alive = 0; -+ - if ( hc->method == METHOD_GET || hc->method == METHOD_POST ) - { - httpd_clear_ndelay( hc->conn_fd ); -@@ -3369,6 +3510,7 @@ - int expnlen, indxlen; - char* cp; - char* pi; -+ int nocache = 0; - - expnlen = strlen( hc->expnfilename ); - -@@ -3561,6 +3703,16 @@ - match( hc->hs->cgi_pattern, hc->expnfilename ) ) - return cgi( hc ); - -+ if ( hc->hs->php_pattern != (char*) 0 && -+ match( hc->hs->php_pattern, hc->expnfilename)) { -+ return thttpd_php_request( hc, 0 ); -+ } -+ -+ if ( hc->hs->phps_pattern != (char*) 0 && -+ match( hc->hs->phps_pattern, hc->expnfilename)) { -+ return thttpd_php_request( hc, 1 ); -+ } -+ - /* It's not CGI. If it's executable or there's pathinfo, someone's - ** trying to either serve or run a non-CGI file as CGI. Either case - ** is prohibited. -@@ -3594,32 +3746,46 @@ - hc->end_byte_loc = hc->sb.st_size - 1; - - figure_mime( hc ); -+ if ( strncmp(hc->decodedurl, "/nocache/", sizeof("/nocache/") - 1 ) == 0 ) -+ nocache = 1; - - if ( hc->method == METHOD_HEAD ) - { - send_mime( - hc, 200, ok200title, hc->encodings, "", hc->type, hc->sb.st_size, -- hc->sb.st_mtime ); -+ hc->sb.st_mtime, 0, 0 ); - } -- else if ( hc->if_modified_since != (time_t) -1 && -+ else if ( !nocache && hc->if_modified_since != (time_t) -1 && - hc->if_modified_since >= hc->sb.st_mtime ) - { -- hc->method = METHOD_HEAD; - send_mime( -- hc, 304, err304title, hc->encodings, "", hc->type, hc->sb.st_size, -- hc->sb.st_mtime ); -+ hc, 304, err304title, hc->encodings, "", hc->type, -1, -+ hc->sb.st_mtime, 0, 0 ); - } - else - { -- hc->file_address = mmc_map( hc->expnfilename, &(hc->sb), nowP ); -+ char *extraheads = ""; -+ char *lm; -+ size_t lml; -+ -+ if ( nocache ) -+ { -+ extraheads = "Expires: Thu, 19 Nov 1981 08:52:00 GMT\r\n" -+ "Cache-Control: no-store, no-cache, must-revalidate, " -+ "post-check=0, pre-check=0\r\n" -+ "Pragma: no-cache\r\n"; -+ } -+ -+ hc->file_address = mmc_map( hc->expnfilename, &(hc->sb), nowP, nocache, &lm, &lml ); - if ( hc->file_address == (char*) 0 ) - { - httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl ); - return -1; - } -+ - send_mime( -- hc, 200, ok200title, hc->encodings, "", hc->type, hc->sb.st_size, -- hc->sb.st_mtime ); -+ hc, 200, ok200title, hc->encodings, extraheads, hc->type, hc->sb.st_size, -+ hc->sb.st_mtime, lm, lml ); - } - - return 0; -@@ -3638,6 +3804,9 @@ - return r; - } - -+#define smart_str_append_const(a,b) smart_str_appendl(a,b,sizeof(b)-1) -+ -+static smart_str bentries; - - static void - make_log_entry( httpd_conn* hc, struct timeval* nowP ) -@@ -3648,88 +3817,62 @@ - - if ( hc->hs->no_log ) - return; -- -- /* This is straight CERN Combined Log Format - the only tweak -- ** being that if we're using syslog() we leave out the date, because -- ** syslogd puts it in. The included syslogtocern script turns the -- ** results into true CERN format. -- */ -- - /* Format remote user. */ - if ( hc->remoteuser[0] != '\0' ) -- ru = hc->remoteuser; -+ ru = hc->remoteuser; - else -- ru = "-"; -+ ru = "-"; - /* If we're vhosting, prepend the hostname to the url. This is - ** a little weird, perhaps writing separate log files for - ** each vhost would make more sense. - */ -- if ( hc->hs->vhost && ! hc->tildemapped ) -- (void) my_snprintf( url, sizeof(url), -- "/%.100s%.200s", -- hc->hostname == (char*) 0 ? hc->hs->server_hostname : hc->hostname, -- hc->encodedurl ); -- else -- (void) my_snprintf( url, sizeof(url), -- "%.200s", hc->encodedurl ); -- /* Format the bytes. */ -- if ( (long) hc->bytes_sent >= 0 ) -- (void) my_snprintf( bytes, sizeof(bytes), -- "%ld", (long) hc->bytes_sent ); -- else -- (void) strcpy( bytes, "-" ); - - /* Logfile or syslog? */ - if ( hc->hs->logfp != (FILE*) 0 ) -- { -- time_t now; -- struct tm* t; -- const char* cernfmt_nozone = "%d/%b/%Y:%H:%M:%S"; -- char date_nozone[100]; -- int zone; -- char sign; -- char date[100]; -- -- /* Get the current time, if necessary. */ -- if ( nowP != (struct timeval*) 0 ) -- now = nowP->tv_sec; -- else -- now = time( (time_t*) 0 ); -- /* Format the time, forcing a numeric timezone (some log analyzers -- ** are stoooopid about this). -- */ -- t = localtime( &now ); -- (void) strftime( date_nozone, sizeof(date_nozone), cernfmt_nozone, t ); --#ifdef HAVE_TM_GMTOFF -- zone = t->tm_gmtoff / 60L; --#else -- zone = -timezone / 60L; -- /* Probably have to add something about daylight time here. */ --#endif -- if ( zone >= 0 ) -- sign = '+'; -- else -- { -- sign = '-'; -- zone = -zone; -- } -- zone = ( zone / 60 ) * 100 + zone % 60; -- (void) my_snprintf( date, sizeof(date), -- "%s %c%04d", date_nozone, sign, zone ); -- /* And write the log entry. */ -- (void) fprintf( hc->hs->logfp, -- "%.80s - %.80s [%s] \"%.80s %.300s %.80s\" %d %s \"%.200s\" \"%.80s\"\n", -- httpd_ntoa( &hc->client_addr ), ru, date, -- httpd_method_str( hc->method ), url, hc->protocol, -- hc->status, bytes, hc->referer, hc->useragent ); -- (void) fflush( hc->hs->logfp ); /* don't need to flush every time */ -- } -- else -- syslog( LOG_INFO, -- "%.80s - %.80s \"%.80s %.200s %.80s\" %d %s \"%.200s\" \"%.80s\"", -- httpd_ntoa( &hc->client_addr ), ru, -- httpd_method_str( hc->method ), url, hc->protocol, -- hc->status, bytes, hc->referer, hc->useragent ); -+ { -+ /* XXXXXXX */ -+ -+ smart_str_appends(&bentries, httpd_ntoa(&hc->client_addr)); -+ smart_str_append_const(&bentries, " - "); -+ smart_str_appends(&bentries, ru); -+ smart_str_append_const(&bentries, " ["); -+ smart_str_appendl(&bentries, hc->hs->log_date, hc->hs->log_date_len); -+ smart_str_append_const(&bentries, "] \""); -+ smart_str_appends(&bentries, httpd_method_str(hc->method)); -+ smart_str_appendc(&bentries, ' '); -+ -+ if (hc->hs->vhost && ! hc->tildemapped) { -+ smart_str_appendc(&bentries, '/'); -+ if (hc->hostname) -+ smart_str_appends(&bentries, hc->hostname); -+ else -+ smart_str_appends(&bentries, hc->hs->server_hostname); -+ } -+ smart_str_appends(&bentries, hc->encodedurl); -+ -+ smart_str_appendc(&bentries, ' '); -+ smart_str_appends(&bentries, hc->protocol); -+ smart_str_append_const(&bentries, "\" "); -+ smart_str_append_long(&bentries, hc->status); -+ if (hc->bytes_sent >= 0) { -+ smart_str_appendc(&bentries, ' '); -+ smart_str_append_long(&bentries, hc->bytes_sent); -+ smart_str_append_const(&bentries, " \""); -+ } else { -+ smart_str_append_const(&bentries, " - \""); -+ } -+ smart_str_appends(&bentries, hc->referer); -+ smart_str_append_const(&bentries, "\" \""); -+ smart_str_appends(&bentries, hc->useragent); -+ smart_str_append_const(&bentries, "\"\n"); -+ -+ if (bentries.len > 16384) { -+ int fd = fileno(hc->hs->logfp); -+ write(fd, bentries.c, bentries.len); -+ bentries.len = 0; -+ } -+ } -+ - } - - -@@ -3840,7 +3983,24 @@ - { - #ifdef HAVE_GETNAMEINFO - static char str[200]; -+ static smart_str httpd_ntoa_buf; -+ -+ if (saP->sa_in.sin_family == AF_INET) { -+ unsigned long n = ntohl(saP->sa_in.sin_addr.s_addr); - -+ httpd_ntoa_buf.len = 0; -+ smart_str_append_long(&httpd_ntoa_buf, (n >> 24)); -+ smart_str_appendc(&httpd_ntoa_buf, '.'); -+ smart_str_append_long(&httpd_ntoa_buf, (n >> 16) & 255); -+ smart_str_appendc(&httpd_ntoa_buf, '.'); -+ smart_str_append_long(&httpd_ntoa_buf, (n >> 8) & 255); -+ smart_str_appendc(&httpd_ntoa_buf, '.'); -+ smart_str_append_long(&httpd_ntoa_buf, (n >> 0) & 255); -+ smart_str_0(&httpd_ntoa_buf); -+ -+ return httpd_ntoa_buf.c; -+ } -+ - if ( getnameinfo( &saP->sa, sockaddr_len( saP ), str, sizeof(str), 0, 0, NI_NUMERICHOST ) != 0 ) - { - str[0] = '?'; -diff -ur thttpd-2.21b/libhttpd.h thttpd-2.21b-cool/libhttpd.h ---- thttpd-2.21b/libhttpd.h Tue Apr 24 00:36:50 2001 -+++ thttpd-2.21b-cool/libhttpd.h Sat Sep 20 14:43:20 2003 -@@ -69,6 +69,8 @@ - char* server_hostname; - int port; - char* cgi_pattern; -+ char* php_pattern; -+ char* phps_pattern; - char* charset; - char* cwd; - int listen4_fd, listen6_fd; -@@ -80,6 +82,8 @@ - char* url_pattern; - char* local_pattern; - int no_empty_referers; -+ size_t log_date_len; -+ char log_date[100]; - } httpd_server; - - /* A connection. */ -@@ -88,6 +92,7 @@ - httpd_server* hs; - httpd_sockaddr client_addr; - char* read_buf; -+ char read_buf_is_mmap; - int read_size, read_idx, checked_idx; - int checked_state; - int method; -@@ -132,11 +137,12 @@ - int got_range; - int tildemapped; /* this connection got tilde-mapped */ - off_t init_byte_loc, end_byte_loc; -- int keep_alive; -+ int keep_alive, do_keep_alive; - int should_linger; - struct stat sb; - int conn_fd; - char* file_address; -+ char read_body_into_mem; - } httpd_conn; - - /* Methods. */ -@@ -168,7 +174,8 @@ - char* hostname, httpd_sockaddr* sa4P, httpd_sockaddr* sa6P, int port, - char* cgi_pattern, char* charset, char* cwd, int no_log, FILE* logfp, - int no_symlink, int vhost, int global_passwd, char* url_pattern, -- char* local_pattern, int no_empty_referers ); -+ char* local_pattern, int no_empty_referers, char* php_pattern, -+ char* phps_pattern ); - - /* Change the log file. */ - extern void httpd_set_logfp( httpd_server* hs, FILE* logfp ); -@@ -229,6 +236,8 @@ - ** If you don't have a current timeval handy just pass in 0. - */ - extern void httpd_close_conn( httpd_conn* hc, struct timeval* nowP ); -+void httpd_complete_request( httpd_conn* hc, struct timeval* nowP); -+int httpd_request_reset(httpd_conn* hc,int ); - - /* Call this to de-initialize a connection struct and *really* free the - ** mallocced strings. -diff -ur thttpd-2.21b/mime_encodings.txt thttpd-2.21b-cool/mime_encodings.txt ---- thttpd-2.21b/mime_encodings.txt Wed May 10 03:22:28 2000 -+++ thttpd-2.21b-cool/mime_encodings.txt Sat Sep 20 14:43:20 2003 -@@ -3,6 +3,6 @@ - # A list of file extensions followed by the corresponding MIME encoding. - # Extensions not found in the table proceed to the mime_types table. - --Z x-compress --gz x-gzip -+Z compress -+gz gzip - uu x-uuencode -diff -ur thttpd-2.21b/mime_types.txt thttpd-2.21b-cool/mime_types.txt ---- thttpd-2.21b/mime_types.txt Sat Apr 14 04:53:30 2001 -+++ thttpd-2.21b-cool/mime_types.txt Sat Sep 20 14:43:20 2003 -@@ -1,135 +1,138 @@ --# mime_types.txt --# --# A list of file extensions followed by the corresponding MIME type. --# Extensions not found in the table are returned as text/plain. -- --html text/html; charset=%s --htm text/html; charset=%s --txt text/plain; charset=%s --rtx text/richtext --etx text/x-setext --tsv text/tab-separated-values --css text/css --xml text/xml --dtd text/xml -- --gif image/gif --jpg image/jpeg --jpeg image/jpeg --jpe image/jpeg --jfif image/jpeg --tif image/tiff --tiff image/tiff --pbm image/x-portable-bitmap --pgm image/x-portable-graymap --ppm image/x-portable-pixmap --pnm image/x-portable-anymap --xbm image/x-xbitmap --xpm image/x-xpixmap --xwd image/x-xwindowdump --ief image/ief --png image/png -- --au audio/basic --snd audio/basic --aif audio/x-aiff --aiff audio/x-aiff --aifc audio/x-aiff --ra audio/x-pn-realaudio --ram audio/x-pn-realaudio --rm audio/x-pn-realaudio --rpm audio/x-pn-realaudio-plugin --wav audio/wav --mid audio/midi --midi audio/midi --kar audio/midi --mpga audio/mpeg --mp2 audio/mpeg --mp3 audio/mpeg -- --mpeg video/mpeg --mpg video/mpeg --mpe video/mpeg --qt video/quicktime --mov video/quicktime --avi video/x-msvideo --movie video/x-sgi-movie --mv video/x-sgi-movie --vx video/x-rad-screenplay -- --a application/octet-stream -+ez application/andrew-inset -+hqx application/mac-binhex40 -+cpt application/mac-compactpro -+doc application/msword - bin application/octet-stream -+dms application/octet-stream -+lha application/octet-stream -+lzh application/octet-stream - exe application/octet-stream --dump application/octet-stream --o application/octet-stream --class application/java --js application/x-javascript -+class application/octet-stream -+so application/octet-stream -+dll application/octet-stream -+oda application/oda -+pdf application/pdf - ai application/postscript - eps application/postscript - ps application/postscript --dir application/x-director -+smi application/smil -+smil application/smil -+mif application/vnd.mif -+xls application/vnd.ms-excel -+ppt application/vnd.ms-powerpoint -+wbxml application/vnd.wap.wbxml -+wmlc application/vnd.wap.wmlc -+wmlsc application/vnd.wap.wmlscriptc -+bcpio application/x-bcpio -+vcd application/x-cdlink -+pgn application/x-chess-pgn -+cpio application/x-cpio -+csh application/x-csh - dcr application/x-director -+dir application/x-director - dxr application/x-director --fgd application/x-director --aam application/x-authorware-map --aas application/x-authorware-seg --aab application/x-authorware-bin --fh4 image/x-freehand --fh7 image/x-freehand --fh5 image/x-freehand --fhc image/x-freehand --fh image/x-freehand --spl application/futuresplash --swf application/x-shockwave-flash - dvi application/x-dvi -+spl application/x-futuresplash - gtar application/x-gtar - hdf application/x-hdf --hqx application/mac-binhex40 --iv application/x-inventor -+js application/x-javascript -+skp application/x-koan -+skd application/x-koan -+skt application/x-koan -+skm application/x-koan - latex application/x-latex --man application/x-troff-man --me application/x-troff-me --mif application/x-mif --ms application/x-troff-ms --oda application/oda --pdf application/pdf --rtf application/rtf --bcpio application/x-bcpio --cpio application/x-cpio --sv4cpio application/x-sv4cpio --sv4crc application/x-sv4crc --sh application/x-shar -+nc application/x-netcdf -+cdf application/x-netcdf -+sh application/x-sh - shar application/x-shar -+swf application/x-shockwave-flash - sit application/x-stuffit -+sv4cpio application/x-sv4cpio -+sv4crc application/x-sv4crc - tar application/x-tar -+tcl application/x-tcl - tex application/x-tex --texi application/x-texinfo - texinfo application/x-texinfo -+texi application/x-texinfo -+t application/x-troff - tr application/x-troff - roff application/x-troff - man application/x-troff-man - me application/x-troff-me - ms application/x-troff-ms --zip application/x-zip-compressed --tsp application/dsptype --wsrc application/x-wais-source - ustar application/x-ustar --cdf application/x-netcdf --nc application/x-netcdf --doc application/msword --ppt application/powerpoint -- --crt application/x-x509-ca-cert --crl application/x-pkcs7-crl -- -+src application/x-wais-source -+xhtml application/xhtml+xml -+xht application/xhtml+xml -+zip application/zip -+au audio/basic -+snd audio/basic -+mid audio/midi -+midi audio/midi -+kar audio/midi -+mpga audio/mpeg -+mp2 audio/mpeg -+mp3 audio/mpeg -+aif audio/x-aiff -+aiff audio/x-aiff -+aifc audio/x-aiff -+m3u audio/x-mpegurl -+ram audio/x-pn-realaudio -+rm audio/x-pn-realaudio -+rpm audio/x-pn-realaudio-plugin -+ra audio/x-realaudio -+wav audio/x-wav -+pdb chemical/x-pdb -+xyz chemical/x-xyz -+bmp image/bmp -+gif image/gif -+ief image/ief -+jpeg image/jpeg -+jpg image/jpeg -+jpe image/jpeg -+png image/png -+tiff image/tiff -+tif image/tiff -+djvu image/vnd.djvu -+djv image/vnd.djvu -+wbmp image/vnd.wap.wbmp -+ras image/x-cmu-raster -+pnm image/x-portable-anymap -+pbm image/x-portable-bitmap -+pgm image/x-portable-graymap -+ppm image/x-portable-pixmap -+rgb image/x-rgb -+xbm image/x-xbitmap -+xpm image/x-xpixmap -+xwd image/x-xwindowdump -+igs model/iges -+iges model/iges -+msh model/mesh -+mesh model/mesh -+silo model/mesh - wrl model/vrml - vrml model/vrml --mime message/rfc822 -- --pac application/x-ns-proxy-autoconfig -- -+css text/css -+html text/html; charset=%s -+htm text/html; charset=%s -+asc text/plain; charset=%s -+txt text/plain; charset=%s -+rtx text/richtext -+rtf text/rtf -+sgml text/sgml -+sgm text/sgml -+tsv text/tab-separated-values - wml text/vnd.wap.wml --wmlc application/vnd.wap.wmlc - wmls text/vnd.wap.wmlscript --wmlsc application/vnd.wap.wmlscriptc --wbmp image/vnd.wap.wbmp -+etx text/x-setext -+xml text/xml -+xsl text/xml -+mpeg video/mpeg -+mpg video/mpeg -+mpe video/mpeg -+qt video/quicktime -+mov video/quicktime -+mxu video/vnd.mpegurl -+avi video/x-msvideo -+movie video/x-sgi-movie -+ice x-conference/x-cooltalk -diff -ur thttpd-2.21b/mmc.c thttpd-2.21b-cool/mmc.c ---- thttpd-2.21b/mmc.c Fri Apr 13 23:02:15 2001 -+++ thttpd-2.21b-cool/mmc.c Sat Sep 20 14:43:20 2003 -@@ -70,6 +70,9 @@ - unsigned int hash; - int hash_idx; - struct MapStruct* next; -+ char nocache; -+ size_t last_modified_len; -+ char last_modified[100]; - } Map; - - -@@ -93,12 +96,13 @@ - - - void* --mmc_map( char* filename, struct stat* sbP, struct timeval* nowP ) -+mmc_map( char* filename, struct stat* sbP, struct timeval* nowP, int nocache, char **last_modified, size_t *last_modified_len ) - { - time_t now; - struct stat sb; - Map* m; - int fd; -+ const char* rfc1123fmt = "%a, %d %b %Y %H:%M:%S GMT"; - - /* Stat the file, if necessary. */ - if ( sbP != (struct stat*) 0 ) -@@ -130,7 +134,7 @@ - /* Yep. Just return the existing map */ - ++m->refcount; - m->reftime = now; -- return m->addr; -+ goto done; - } - - /* Open the file. */ -@@ -167,12 +171,13 @@ - m->ctime = sb.st_ctime; - m->refcount = 1; - m->reftime = now; -+ m->nocache = (char) nocache; - - /* Avoid doing anything for zero-length files; some systems don't like - ** to mmap them, other systems dislike mallocing zero bytes. - */ - if ( m->size == 0 ) -- m->addr = (void*) 1; /* arbitrary non-NULL address */ -+ m->addr = (void*) 5; /* arbitrary non-NULL address */ - else - { - #ifdef HAVE_MMAP -@@ -223,6 +228,13 @@ - maps = m; - ++map_count; - -+ strftime( m->last_modified, sizeof(m->last_modified), rfc1123fmt, gmtime( &sb.st_mtime ) ); -+ m->last_modified_len = strlen(m->last_modified); -+ -+done: -+ *last_modified = m->last_modified; -+ *last_modified_len = m->last_modified_len; -+ - /* And return the address. */ - return m->addr; - } -@@ -231,27 +243,32 @@ - void - mmc_unmap( void* addr, struct stat* sbP, struct timeval* nowP ) - { -- Map* m = (Map*) 0; -+ Map* m = (Map*) 0, **mm = &maps; - - /* Find the Map entry for this address. First try a hash. */ - if ( sbP != (struct stat*) 0 ) - { - m = find_hash( sbP->st_ino, sbP->st_dev, sbP->st_size, sbP->st_ctime ); -- if ( m != (Map*) 0 && m->addr != addr ) -+ if ( m != (Map*) 0 && ( m->addr != addr || m->nocache == 1 ) ) - m = (Map*) 0; - } - /* If that didn't work, try a full search. */ - if ( m == (Map*) 0 ) -- for ( m = maps; m != (Map*) 0; m = m->next ) -+ for ( m = maps; m != (Map*) 0; m = m->next ) { - if ( m->addr == addr ) - break; -+ mm = &m->next; -+ } - if ( m == (Map*) 0 ) - syslog( LOG_ERR, "mmc_unmap failed to find entry!" ); - else if ( m->refcount <= 0 ) - syslog( LOG_ERR, "mmc_unmap found zero or negative refcount!" ); - else - { -- --m->refcount; -+ if ( --m->refcount == 0 && m->nocache == 1 ) { -+ really_unmap( mm ); -+ return; -+ } - if ( nowP != (struct timeval*) 0 ) - m->reftime = nowP->tv_sec; - else -diff -ur thttpd-2.21b/mmc.h thttpd-2.21b-cool/mmc.h ---- thttpd-2.21b/mmc.h Fri Apr 13 07:36:54 2001 -+++ thttpd-2.21b-cool/mmc.h Sat Sep 20 14:43:20 2003 -@@ -31,8 +31,9 @@ - /* Returns an mmap()ed area for the given file, or (void*) 0 on errors. - ** If you have a stat buffer on the file, pass it in, otherwise pass 0. - ** Same for the current time. -+** Set nocache to 1, if this entry is supposed to be removed quickly. - */ --extern void* mmc_map( char* filename, struct stat* sbP, struct timeval* nowP ); -+extern void* mmc_map( char* filename, struct stat* sbP, struct timeval* nowP, int nocache, char **last_modified, size_t *last_modified_len ); - - /* Done with an mmap()ed area that was returned by mmc_map(). - ** If you have a stat buffer on the file, pass it in, otherwise pass 0. -diff -ur thttpd-2.21b/thttpd.c thttpd-2.21b-cool/thttpd.c ---- thttpd-2.21b/thttpd.c Tue Apr 24 00:41:57 2001 -+++ thttpd-2.21b-cool/thttpd.c Sat Sep 20 14:43:20 2003 -@@ -53,6 +53,10 @@ - #endif - #include <unistd.h> - -+#include <sys/mman.h> -+ -+#include <limits.h> -+ - #include "fdwatch.h" - #include "libhttpd.h" - #include "mmc.h" -@@ -66,6 +70,8 @@ - static char* dir; - static int do_chroot, no_log, no_symlink, do_vhost, do_global_passwd; - static char* cgi_pattern; -+static char* php_pattern; -+static char* phps_pattern; - static char* url_pattern; - static int no_empty_referers; - static char* local_pattern; -@@ -95,10 +101,10 @@ - httpd_conn* hc; - int tnums[MAXTHROTTLENUMS]; /* throttle indexes */ - int numtnums; -+ int keep_alive; - long limit; - time_t started_at; -- Timer* idle_read_timer; -- Timer* idle_send_timer; -+ time_t last_io; - Timer* wakeup_timer; - Timer* linger_timer; - long wouldblock_delay; -@@ -106,17 +112,22 @@ - off_t bytes_sent; - off_t bytes_to_send; - } connecttab; --static connecttab* connects; -+static connecttab* connects, **free_connects; -+static int next_free_connect; - static int numconnects, maxconnects; - static int httpd_conn_count; - - /* The connection states. */ --#define CNST_FREE 0 --#define CNST_READING 1 --#define CNST_SENDING 2 --#define CNST_PAUSING 3 --#define CNST_LINGERING 4 -- -+enum { -+ CNST_FREE = 0, -+ CNST_READING, -+ CNST_SENDING, -+ CNST_PAUSING, -+ CNST_LINGERING, -+ CNST_SENDING_RESP, -+ CNST_READING_BODY, -+ CNST_TOTAL_NR -+}; - - static httpd_server* hs = (httpd_server*) 0; - int terminate = 0; -@@ -140,23 +151,32 @@ - static int handle_newconnect( struct timeval* tvP, int listen_fd ); - static void handle_read( connecttab* c, struct timeval* tvP ); - static void handle_send( connecttab* c, struct timeval* tvP ); -+static void handle_send_resp( connecttab* c, struct timeval* tvP ); -+static void handle_read_body( connecttab* c, struct timeval* tvP ); - static void handle_linger( connecttab* c, struct timeval* tvP ); - static int check_throttles( connecttab* c ); -+static void timeout_conns( ClientData client_data, struct timeval* nowP ); - static void clear_throttles( connecttab* c, struct timeval* tvP ); - static void update_throttles( ClientData client_data, struct timeval* nowP ); --static void clear_connection( connecttab* c, struct timeval* tvP ); -+static void clear_connection( connecttab* c, struct timeval* tvP, int ); - static void really_clear_connection( connecttab* c, struct timeval* tvP ); --static void idle_read_connection( ClientData client_data, struct timeval* nowP ); --static void idle_send_connection( ClientData client_data, struct timeval* nowP ); - static void wakeup_connection( ClientData client_data, struct timeval* nowP ); - static void linger_clear_connection( ClientData client_data, struct timeval* nowP ); - static void occasional( ClientData client_data, struct timeval* nowP ); -+static void periodic_jobs( ClientData client_data, struct timeval* nowP ); - #ifdef STATS_TIME - static void show_stats( ClientData client_data, struct timeval* nowP ); - #endif /* STATS_TIME */ - static void logstats( struct timeval* nowP ); - static void thttpd_logstats( long secs ); -+static void boot_request(connecttab *c, struct timeval *tvP); -+ -+typedef void (*handler_func)(connecttab*, struct timeval *); -+ -+handler_func handler_array[CNST_TOTAL_NR] = -+{NULL, handle_read, handle_send, NULL, handle_linger, handle_send_resp, handle_read_body}; - -+#define RUN_HANDLER(type, c) if (handler_array[type]) handler_array[type](c, &tv) - - static void - handle_term( int sig ) -@@ -177,7 +197,7 @@ - return; - - /* Re-open the log file. */ -- if ( logfile != (char*) 0 ) -+ if ( logfile != (char*) 0 && strcmp(logfile, "-") != 0) - { - logfp = fopen( logfile, "a" ); - if ( logfp == (FILE*) 0 ) -@@ -198,6 +218,8 @@ - } - - -+time_t httpd_time_now; -+ - static void - handle_usr2( int sig ) - { -@@ -217,7 +239,6 @@ - int num_ready; - int cnum, ridx; - connecttab* c; -- httpd_conn* hc; - httpd_sockaddr sa4; - httpd_sockaddr sa6; - int gotv4, gotv6; -@@ -270,7 +291,9 @@ - no_log = 1; - logfp = (FILE*) 0; - } -- else -+ else if (strcmp(logfile, "-") == 0) { -+ logfp = stdout; -+ } else - { - logfp = fopen( logfile, "a" ); - if ( logfp == (FILE*) 0 ) -@@ -420,7 +443,8 @@ - hostname, - gotv4 ? &sa4 : (httpd_sockaddr*) 0, gotv6 ? &sa6 : (httpd_sockaddr*) 0, - port, cgi_pattern, charset, cwd, no_log, logfp, no_symlink, do_vhost, -- do_global_passwd, url_pattern, local_pattern, no_empty_referers ); -+ do_global_passwd, url_pattern, local_pattern, no_empty_referers, -+ php_pattern, phps_pattern); - if ( hs == (httpd_server*) 0 ) - exit( 1 ); - -@@ -430,6 +454,12 @@ - syslog( LOG_CRIT, "tmr_create(occasional) failed" ); - exit( 1 ); - } -+ -+ if (tmr_create(0, timeout_conns, JunkClientData, 30 * 1000, 1) == 0) { -+ syslog(LOG_CRIT, "tmr_create(timeout_conns) failed"); -+ exit(1); -+ } -+ - if ( numthrottles > 0 ) - { - /* Set up the throttles timer. */ -@@ -439,6 +469,12 @@ - exit( 1 ); - } - } -+ -+ if (tmr_create(0, periodic_jobs, JunkClientData, 2000, 1) == 0) { -+ syslog(LOG_CRIT, "tmr_create failed"); -+ exit(1); -+ } -+ - #ifdef STATS_TIME - /* Set up the stats timer. */ - if ( tmr_create( (struct timeval*) 0, show_stats, JunkClientData, STATS_TIME * 1000L, 1 ) == (Timer*) 0 ) -@@ -454,12 +490,14 @@ - /* If we're root, try to become someone else. */ - if ( getuid() == 0 ) - { -+#ifndef __CYGWIN__ - /* Set aux groups to null. */ - if ( setgroups( 0, (const gid_t*) 0 ) < 0 ) - { - syslog( LOG_CRIT, "setgroups - %m" ); - exit( 1 ); - } -+#endif - /* Set primary group. */ - if ( setgid( gid ) < 0 ) - { -@@ -495,13 +533,17 @@ - } - maxconnects -= SPARE_FDS; - connects = NEW( connecttab, maxconnects ); -+ free_connects = malloc(sizeof(connecttab *) * maxconnects); -+ next_free_connect = maxconnects; - if ( connects == (connecttab*) 0 ) - { - syslog( LOG_CRIT, "out of memory allocating a connecttab" ); - exit( 1 ); - } -+ - for ( cnum = 0; cnum < maxconnects; ++cnum ) - { -+ free_connects[cnum] = &connects[maxconnects - cnum - 1]; - connects[cnum].conn_state = CNST_FREE; - connects[cnum].hc = (httpd_conn*) 0; - } -@@ -518,6 +560,9 @@ - - /* Main loop. */ - (void) gettimeofday( &tv, (struct timezone*) 0 ); -+ httpd_time_now = tv.tv_sec; -+ periodic_jobs(JunkClientData, &tv); -+ - while ( ( ! terminate ) || numconnects > 0 ) - { - /* Do the fd watch. */ -@@ -530,6 +575,7 @@ - exit( 1 ); - } - (void) gettimeofday( &tv, (struct timezone*) 0 ); -+ httpd_time_now = tv.tv_sec; - if ( num_ready == 0 ) - { - /* No fd's are ready - run the timers. */ -@@ -565,16 +611,10 @@ - c = (connecttab*) fdwatch_get_client_data( ridx ); - if ( c == (connecttab*) 0 ) - continue; -- hc = c->hc; -- if ( c->conn_state == CNST_READING && -- fdwatch_check_fd( hc->conn_fd ) ) -- handle_read( c, &tv ); -- else if ( c->conn_state == CNST_SENDING && -- fdwatch_check_fd( hc->conn_fd ) ) -- handle_send( c, &tv ); -- else if ( c->conn_state == CNST_LINGERING && -- fdwatch_check_fd( hc->conn_fd ) ) -- handle_linger( c, &tv ); -+#if DO_UNNECESSARY_CHECK_FD -+ fdwatch_check_fd(c->hc->conn_fd); -+#endif -+ RUN_HANDLER(c->conn_state, c); - } - tmr_run( &tv ); - -@@ -627,6 +667,8 @@ - #else /* CGI_PATTERN */ - cgi_pattern = (char*) 0; - #endif /* CGI_PATTERN */ -+ php_pattern = "**.php"; -+ phps_pattern = "**.phps"; - url_pattern = (char*) 0; - no_empty_referers = 0; - local_pattern = (char*) 0; -@@ -833,6 +875,16 @@ - value_required( name, value ); - cgi_pattern = e_strdup( value ); - } -+ else if ( strcasecmp( name, "phppat" ) == 0 ) -+ { -+ value_required( name, value ); -+ php_pattern = e_strdup( value ); -+ } -+ else if ( strcasecmp( name, "phpspat" ) == 0 ) -+ { -+ value_required( name, value ); -+ phps_pattern = e_strdup( value ); -+ } - else if ( strcasecmp( name, "urlpat" ) == 0 ) - { - value_required( name, value ); -@@ -1196,8 +1248,10 @@ - logstats( &tv ); - for ( cnum = 0; cnum < maxconnects; ++cnum ) - { -- if ( connects[cnum].conn_state != CNST_FREE ) -+ if ( connects[cnum].conn_state != CNST_FREE ) { -+ httpd_complete_request( connects[cnum].hc, &tv ); - httpd_close_conn( connects[cnum].hc, &tv ); -+ } - if ( connects[cnum].hc != (httpd_conn*) 0 ) - { - httpd_destroy_conn( connects[cnum].hc ); -@@ -1214,6 +1268,7 @@ - } - mmc_destroy(); - tmr_destroy(); -+ free( (void*) free_connects ); - free( (void*) connects ); - if ( throttles != (throttletab*) 0 ) - free( (void*) throttles ); -@@ -1234,7 +1289,7 @@ - for (;;) - { - /* Is there room in the connection table? */ -- if ( numconnects >= maxconnects ) -+ if ( numconnects >= maxconnects || next_free_connect == 0 ) - { - /* Out of connection slots. Run the timers, then the - ** existing connections, and maybe we'll free up a slot -@@ -1245,10 +1300,10 @@ - return 0; - } - /* Find a free connection entry. */ -- for ( cnum = 0; cnum < maxconnects; ++cnum ) -- if ( connects[cnum].conn_state == CNST_FREE ) -- break; -- c = &connects[cnum]; -+ -+ c = free_connects[--next_free_connect]; -+ free_connects[next_free_connect] = NULL; -+ - /* Make the httpd_conn if necessary. */ - if ( c->hc == (httpd_conn*) 0 ) - { -@@ -1267,24 +1322,18 @@ - { - case GC_FAIL: - case GC_NO_MORE: -+ free_connects[next_free_connect++] = c; - return 1; - } - c->conn_state = CNST_READING; - ++numconnects; - client_data.p = c; -- c->idle_read_timer = tmr_create( -- tvP, idle_read_connection, client_data, IDLE_READ_TIMELIMIT * 1000L, -- 0 ); -- if ( c->idle_read_timer == (Timer*) 0 ) -- { -- syslog( LOG_CRIT, "tmr_create(idle_read_connection) failed" ); -- exit( 1 ); -- } -- c->idle_send_timer = (Timer*) 0; - c->wakeup_timer = (Timer*) 0; - c->linger_timer = (Timer*) 0; - c->bytes_sent = 0; - c->numtnums = 0; -+ c->keep_alive = 0; -+ c->last_io = httpd_time_now; - - /* Set the connection file descriptor to no-delay mode. */ - httpd_set_ndelay( c->hc->conn_fd ); -@@ -1298,11 +1347,100 @@ - } - - -+#define FIXUP(x) if (hc->x >= oldptr && hc->x < pe) hc->x += d -+ -+static void -+realign_hc(httpd_conn *hc, char *oldptr) -+{ -+ int d = hc->read_buf - oldptr; -+ char *pe = oldptr + hc->checked_idx; -+ -+ FIXUP(encodedurl); -+ FIXUP(protocol); -+ FIXUP(referer); -+ FIXUP(useragent); -+ FIXUP(acceptl); -+ FIXUP(cookie); -+ FIXUP(contenttype); -+ FIXUP(hdrhost); -+ FIXUP(authorization); -+} -+ -+#undef FIXUP -+ -+static void -+setup_read_body(connecttab *c, struct timeval *tvP) -+{ -+ httpd_conn *hc = c->hc; -+ int already, missing; -+ char *oldptr = hc->read_buf; -+ -+ c->conn_state = CNST_READING_BODY; -+ -+ hc->read_body_into_mem = 0; -+ -+ already = hc->read_idx - hc->checked_idx; -+ missing = hc->contentlength - already; -+ -+ if (missing > 16384) { -+ char filename[] = "/tmp/thttpd.upload.XXXXXX"; -+ int tmp = mkstemp(filename); -+ -+ if (tmp >= 0) { -+ void *p; -+ size_t sz = hc->contentlength + hc->checked_idx + 10; -+ -+ unlink(filename); -+ -+ ftruncate(tmp, sz); -+ p = mmap(NULL, sz, -+ PROT_READ|PROT_WRITE, MAP_PRIVATE, tmp, 0); -+ -+ if (p != MAP_FAILED) { -+ memcpy(p, hc->read_buf, hc->read_idx); -+ free(hc->read_buf); -+ hc->read_size = sz; -+ hc->read_buf = p; -+ hc->read_buf_is_mmap = 1; -+ } -+ close(tmp); -+ } -+ -+ if (!hc->read_buf_is_mmap) { -+ clear_connection( c, tvP, 0 ); -+ return; -+ } -+ } else if (missing > 0) { -+ httpd_realloc_str(&hc->read_buf, &hc->read_size, hc->checked_idx + hc->contentlength + 10); -+ } -+ if (oldptr != hc->read_buf) realign_hc(hc, oldptr); -+ -+ fdwatch_del_fd( hc->conn_fd ); -+ fdwatch_add_fd( hc->conn_fd, c, FDW_READ ); -+} -+ -+static void -+setup_sending(connecttab *c, int state, struct timeval *tvP) -+{ -+ httpd_conn *hc = c->hc; -+ ClientData client_data; -+ -+ c->conn_state = state; -+ c->started_at = tvP->tv_sec; -+ c->wouldblock_delay = 0; -+ client_data.p = c; -+ -+ fdwatch_del_fd( hc->conn_fd ); -+ fdwatch_add_fd( hc->conn_fd, c, FDW_WRITE ); -+} -+ -+static void handle_request( connecttab *c, struct timeval *tvP); -+ -+ - static void - handle_read( connecttab* c, struct timeval* tvP ) - { - int sz; -- ClientData client_data; - httpd_conn* hc = c->hc; - - /* Is there room in our buffer to read more bytes? */ -@@ -1311,7 +1449,7 @@ - if ( hc->read_size > 5000 ) - { - httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" ); -- clear_connection( c, tvP ); -+ clear_connection( c, tvP, 0 ); - return; - } - httpd_realloc_str( -@@ -1327,14 +1465,53 @@ - ** EWOULDBLOCK; however, this apparently can happen if a packet gets - ** garbled. - */ -- if ( sz == 0 || ( sz < 0 && ( errno != EWOULDBLOCK ) ) ) -- { -- httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" ); -- clear_connection( c, tvP ); -+ if ( sz == 0 ) { -+ if (! c->keep_alive) { -+ httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" ); -+ } -+ clear_connection( c, tvP, 0 ); -+ return; -+ } else if ( sz < 0 ) { -+ if (errno != EWOULDBLOCK) { -+ clear_connection( c, tvP, 0 ); -+ } - return; -+ } -+ -+ /* If this is a persistent PHP connection, we must not receive -+ ** any further requests on this connection. Some broken HTTP/1.1 -+ ** implementations (e.g. Mozilla 1.0.1) are known to do -+ ** pipelining on a connection, although a prior response included -+ ** Connection: close -+ */ -+ if (c->hc->file_address == (char *) 1) { -+ return; -+ } -+ -+ c->last_io = httpd_time_now; -+ if (sz > 0) hc->read_idx += sz; -+ -+ /* -+ ** if we start getting new data on this socket, "promote" it -+ ** to read timeout -+ */ -+ if ( hc->keep_alive ) { -+ ClientData client_data; -+ -+ -+ client_data.p = c; -+ -+ hc->keep_alive = 0; -+ } -+ handle_request(c, tvP); - } -- hc->read_idx += sz; - -+ -+static void -+handle_request( connecttab *c, struct timeval *tvP) -+{ -+ httpd_conn* hc = c->hc; -+ - /* Do we have a complete request yet? */ - switch ( httpd_got_request( hc ) ) - { -@@ -1342,14 +1519,14 @@ - return; - case GR_BAD_REQUEST: - httpd_send_err( hc, 400, httpd_err400title, "", httpd_err400form, "" ); -- clear_connection( c, tvP ); -+ clear_connection( c, tvP, 0 ); - return; - } - - /* Yes. Try parsing and resolving it. */ - if ( httpd_parse_request( hc ) < 0 ) - { -- clear_connection( c, tvP ); -+ clear_connection( c, tvP, 0 ); - return; - } - -@@ -1358,18 +1535,28 @@ - { - httpd_send_err( - hc, 503, httpd_err503title, "", httpd_err503form, hc->encodedurl ); -- clear_connection( c, tvP ); -+ clear_connection( c, tvP, 0 ); - return; - } -+ boot_request(c, tvP); -+} - -+static void boot_request(connecttab *c, struct timeval *tvP) -+{ -+ httpd_conn *hc = c->hc; - /* Start the connection going. */ - if ( httpd_start_request( hc, tvP ) < 0 ) - { - /* Something went wrong. Close down the connection. */ -- clear_connection( c, tvP ); -+ clear_connection( c, tvP, 0 ); - return; - } - -+ if ( hc->read_body_into_mem ) { -+ setup_read_body( c, tvP ); -+ return; -+ } -+ - /* Fill in bytes_to_send. */ - if ( hc->got_range ) - { -@@ -1384,37 +1571,25 @@ - { - /* No file address means someone else is handling it. */ - c->bytes_sent = hc->bytes_sent; -- clear_connection( c, tvP ); -+ clear_connection( c, tvP, 1 ); - return; - } -+ if (hc->file_address == (char *) 1) { -+ c->last_io = (time_t) LONG_MAX; -+ c->wouldblock_delay = 0; -+ return; -+ } - if ( c->bytes_sent >= c->bytes_to_send ) - { - /* There's nothing to send. */ -- clear_connection( c, tvP ); -+ clear_connection( c, tvP, 1 ); - return; - } - - /* Cool, we have a valid connection and a file to send to it. */ -- c->conn_state = CNST_SENDING; -- c->started_at = tvP->tv_sec; -- c->wouldblock_delay = 0; -- client_data.p = c; -- tmr_cancel( c->idle_read_timer ); -- c->idle_read_timer = (Timer*) 0; -- c->idle_send_timer = tmr_create( -- tvP, idle_send_connection, client_data, IDLE_SEND_TIMELIMIT * 1000L, -- 0 ); -- if ( c->idle_send_timer == (Timer*) 0 ) -- { -- syslog( LOG_CRIT, "tmr_create(idle_send_connection) failed" ); -- exit( 1 ); -- } -- -- fdwatch_del_fd( hc->conn_fd ); -- fdwatch_add_fd( hc->conn_fd, c, FDW_WRITE ); -+ setup_sending(c, CNST_SENDING, tvP); - } - -- - static void - handle_send( connecttab* c, struct timeval* tvP ) - { -@@ -1443,6 +1618,9 @@ - iv[1].iov_base = &(hc->file_address[c->bytes_sent]); - iv[1].iov_len = MIN( c->bytes_to_send - c->bytes_sent, c->limit ); - sz = writev( hc->conn_fd, iv, 2 ); -+/* -+printf("**RESPONSE2 [%d]** len = %d\n%*.*s\n", hc->conn_fd, hc->responselen, hc->responselen, hc->responselen, hc->response); -+*/ - } - - if ( sz == 0 || -@@ -1486,12 +1664,12 @@ - */ - if ( errno != EPIPE && errno != EINVAL && errno != ECONNRESET ) - syslog( LOG_ERR, "write - %m sending %.80s", hc->encodedurl ); -- clear_connection( c, tvP ); -+ clear_connection( c, tvP, 0 ); - return; - } - - /* Ok, we wrote something. */ -- tmr_reset( tvP, c->idle_send_timer ); -+ c->last_io = httpd_time_now; - /* Was this a headers + file writev()? */ - if ( hc->responselen > 0 ) - { -@@ -1500,7 +1678,7 @@ - { - /* Yes; move the unwritten part to the front of the buffer. */ - int newlen = hc->responselen - sz; -- (void) memcpy( hc->response, &(hc->response[sz]), newlen ); -+ (void) memmove( hc->response, &(hc->response[sz]), newlen ); - hc->responselen = newlen; - sz = 0; - } -@@ -1519,7 +1697,7 @@ - if ( c->bytes_sent >= c->bytes_to_send ) - { - /* This connection is finished! */ -- clear_connection( c, tvP ); -+ clear_connection( c, tvP, 1 ); - return; - } - -@@ -1560,6 +1738,9 @@ - char buf[1024]; - int r; - -+/* -+printf("*LINGER read\n"); -+*/ - /* In lingering-close mode we just read and ignore bytes. An error - ** or EOF ends things, otherwise we go until a timeout. - */ -@@ -1569,6 +1750,63 @@ - } - - -+static void -+handle_read_body(connecttab *c, struct timeval *tvP) -+{ -+ httpd_conn *hc = c->hc; -+ int n; -+ -+ n = read(hc->conn_fd, hc->read_buf + hc->read_idx, -+ hc->contentlength - (hc->read_idx - hc->checked_idx)); -+ -+ if (n <= 0) { -+ if (errno == EAGAIN) -+ return; -+ clear_connection(c, tvP, 0); -+ return; -+ } -+ -+ c->last_io = httpd_time_now; -+ -+ hc->read_idx += n; -+ -+ if (hc->contentlength == hc->read_idx - hc->checked_idx) { -+ boot_request(c, tvP); -+ return; -+ } -+} -+ -+static void -+handle_send_resp(connecttab *c, struct timeval *tvP) -+{ -+ httpd_conn* hc = c->hc; -+ int n = send(hc->conn_fd, hc->response, hc->responselen, 0); -+ int dokeep = 1; -+ -+ if (n < 0) { -+ if (errno == EAGAIN) -+ return; -+ -+ dokeep = 0; -+ goto clear; -+ } -+ -+ c->last_io = httpd_time_now; -+ -+ if (n == hc->responselen) { -+clear: -+ hc->response = realloc(hc->response, hc->maxresponse + 1); -+ hc->responselen = 0; -+ -+ clear_connection(c, tvP, dokeep); -+ return; -+ } -+ -+ hc->responselen -= n; -+ -+ memmove(hc->response, hc->response + n, hc->responselen); -+} -+ - static int - check_throttles( connecttab* c ) - { -@@ -1635,23 +1873,18 @@ - - - static void --clear_connection( connecttab* c, struct timeval* tvP ) -+clear_connection( connecttab* c, struct timeval* tvP, int doKeep ) - { - ClientData client_data; -+ int linger; - - /* If we haven't actually sent the buffered response yet, do so now. */ -- httpd_write_response( c->hc ); -+ if (c->hc->responselen && c->conn_state != CNST_SENDING_RESP) { -+ setup_sending(c, CNST_SENDING_RESP, tvP); - -- if ( c->idle_read_timer != (Timer*) 0 ) -- { -- tmr_cancel( c->idle_read_timer ); -- c->idle_read_timer = 0; -- } -- if ( c->idle_send_timer != (Timer*) 0 ) -- { -- tmr_cancel( c->idle_send_timer ); -- c->idle_send_timer = 0; -+ return; - } -+ - if ( c->wakeup_timer != (Timer*) 0 ) - { - tmr_cancel( c->wakeup_timer ); -@@ -1669,13 +1902,36 @@ - ** circumstances that make a lingering close necessary. If the flag - ** isn't set we do the real close now. - */ -- if ( c->hc->should_linger ) -+ -+ if ( c->hc->do_keep_alive && doKeep) - { -- c->conn_state = CNST_LINGERING; -+ httpd_conn *hc = c->hc; -+ c->conn_state = CNST_READING; -+ -+ client_data.p = c; -+ c->bytes_sent = 0; -+ c->numtnums = 0; -+ c->keep_alive = 1; -+ -+ httpd_complete_request( c->hc, tvP ); -+ - fdwatch_del_fd( c->hc->conn_fd ); - fdwatch_add_fd( c->hc->conn_fd, c, FDW_READ ); -+ -+ httpd_request_reset( c->hc, 1 ); -+ -+ hc->read_idx -= hc->checked_idx; -+ memmove(hc->read_buf, hc->read_buf + hc->checked_idx, hc->read_idx); -+ hc->checked_idx = 0; -+ - /* Make sure we are still in no-delay mode. */ - httpd_set_ndelay( c->hc->conn_fd ); -+ handle_request(c, tvP); -+ } -+ else if ( c->hc->should_linger ) -+ { -+ c->conn_state = CNST_LINGERING; -+ - client_data.p = c; - c->linger_timer = tmr_create( - tvP, linger_clear_connection, client_data, LINGER_TIME * 1000L, 0 ); -@@ -1684,9 +1940,19 @@ - syslog( LOG_CRIT, "tmr_create(linger_clear_connection) failed" ); - exit( 1 ); - } -+ -+ httpd_complete_request( c->hc, tvP ); -+ -+ fdwatch_del_fd( c->hc->conn_fd ); -+ fdwatch_add_fd( c->hc->conn_fd, c, FDW_READ ); -+ /* Make sure we are still in no-delay mode. */ -+ httpd_set_ndelay( c->hc->conn_fd ); - } -- else -+ else -+ { -+ httpd_complete_request( c->hc, tvP ); - really_clear_connection( c, tvP ); -+ } - } - - -@@ -1702,45 +1968,12 @@ - tmr_cancel( c->linger_timer ); - c->linger_timer = 0; - } -+ free_connects[next_free_connect++] = c; - c->conn_state = CNST_FREE; - --numconnects; - } - - --static void --idle_read_connection( ClientData client_data, struct timeval* nowP ) -- { -- connecttab* c; -- -- c = (connecttab*) client_data.p; -- c->idle_read_timer = (Timer*) 0; -- if ( c->conn_state != CNST_FREE ) -- { -- syslog( LOG_INFO, -- "%.80s connection timed out reading", -- httpd_ntoa( &c->hc->client_addr ) ); -- httpd_send_err( c->hc, 408, httpd_err408title, "", httpd_err408form, "" ); -- clear_connection( c, nowP ); -- } -- } -- -- --static void --idle_send_connection( ClientData client_data, struct timeval* nowP ) -- { -- connecttab* c; -- -- c = (connecttab*) client_data.p; -- c->idle_send_timer = (Timer*) 0; -- if ( c->conn_state != CNST_FREE ) -- { -- syslog( LOG_INFO, -- "%.80s connection timed out sending", -- httpd_ntoa( &c->hc->client_addr ) ); -- clear_connection( c, nowP ); -- } -- } -- - - static void - wakeup_connection( ClientData client_data, struct timeval* nowP ) -@@ -1783,6 +2016,43 @@ - } - #endif /* STATS_TIME */ - -+char httpd_now_buf[100]; -+ -+ -+ -+static void -+periodic_jobs( ClientData client_data, struct timeval* nowP ) -+{ -+ const char* rfc1123fmt = "%a, %d %b %Y %H:%M:%S GMT"; -+ struct tm *t; -+ char date_nozone[100]; -+ const char* cernfmt_nozone = "%d/%b/%Y:%H:%M:%S"; -+ char data[100]; -+ int zone; -+ char sign; -+ -+ strftime( httpd_now_buf, sizeof(httpd_now_buf), rfc1123fmt, gmtime( &nowP->tv_sec ) ); -+ -+ t = localtime(&nowP->tv_sec); -+ strftime( date_nozone, sizeof(date_nozone), cernfmt_nozone, t ); -+#ifdef HAVE_TM_GMTOFF -+ zone = t->tm_gmtoff / 60L; -+#else -+ zone = -timezone / 60L; -+ /* Probably have to add something about daylight time here. */ -+#endif -+ if ( zone >= 0 ) -+ sign = '+'; -+ else -+ { -+ sign = '-'; -+ zone = -zone; -+ } -+ zone = ( zone / 60 ) * 100 + zone % 60; -+ hs->log_date_len = sprintf( hs->log_date, "%s %c%04d", date_nozone, sign, -+ zone ); -+} -+ - - /* Generate debugging statistics syslog messages for all packages. */ - static void -@@ -1826,3 +2096,42 @@ - stats_connections = stats_bytes = 0L; - stats_simultaneous = 0; - } -+ -+static void -+timeout_conns(ClientData client_data, struct timeval *nowP) -+{ -+ connecttab *c = connects, *ce = c + maxconnects; -+ time_t now = nowP->tv_sec; -+ int r = 0, w = 0; -+ int checked = 0; -+ -+ while (c < ce) { -+ switch (c->conn_state) { -+ case CNST_SENDING: -+ case CNST_SENDING_RESP: -+ checked++; -+ if ((now - c->last_io) > IDLE_SEND_TIMELIMIT) { -+ clear_connection( c, nowP, 0 ); -+ w++; -+ } -+ break; -+ case CNST_READING: -+ case CNST_READING_BODY: -+ checked++; -+ if ((now - c->last_io) > IDLE_READ_TIMELIMIT) { -+ clear_connection( c, nowP, 0 ); -+ r++; -+ } -+ break; -+ case CNST_FREE: break; -+ default: checked++; break; -+ } -+ c++; -+ if (checked >= numconnects) break; -+ } -+ -+ if (r > 0 || w > 0) { -+ syslog(LOG_INFO, "Expired %d/%d connections in read/write state", r, w); -+ } -+} -+ -diff -ur thttpd-2.21b/version.h thttpd-2.21b-cool/version.h ---- thttpd-2.21b/version.h Tue Apr 24 04:05:23 2001 -+++ thttpd-2.21b-cool/version.h Sat Sep 20 14:43:20 2003 -@@ -3,7 +3,7 @@ - #ifndef _VERSION_H_ - #define _VERSION_H_ - --#define SERVER_SOFTWARE "thttpd/2.21b 23apr2001" -+#define SERVER_SOFTWARE "thttpd/2.21b PHP/20030920" - #define SERVER_ADDRESS "http://www.acme.com/software/thttpd/" - - #endif /* _VERSION_H_ */ diff --git a/sapi/tux/CREDITS b/sapi/tux/CREDITS deleted file mode 100644 index 3b7aa70c01..0000000000 --- a/sapi/tux/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -tux -Sascha Schumann diff --git a/sapi/tux/README b/sapi/tux/README deleted file mode 100644 index 92c021123f..0000000000 --- a/sapi/tux/README +++ /dev/null @@ -1,86 +0,0 @@ -README FOR THE TUX MODULE (by Sascha Schumann) -($Date$) - - This is a SAPI module for the TUX web-server by Ingo Molnar. - - The special thing about TUX is that it is integrated into the Linux - kernel and thus provides high-speed serving of static files. - - The web-server provides a user-space API which allows arbitrary - plug-ins to be made available. - - All requests to the PHP userspace module are currently serialized. - - This module is of alpha quality. Due to incomplete APIs, HTTP - authentication and handling of POST requests has not been - implemented yet. - - SECURITY NOTE: PHP will happily run everything under the - web-root through the parser; so be careful what you put - there. - - Note that requests are served in a chroot'ed environment. - The initialization of PHP does not take place in the chroot'ed - environment, so that e.g. /usr/local/lib/php.ini is treated - as usual. - -REQUIRED DOWNLOADS - - 1. TUX - - http://people.redhat.com/~mingo/TUX-patches/QuickStart-TUX.txt - - 2. PHP 4.0.x - - Download: - http://www.php.net/ - - Snapshots from CVS: - http://snaps.php.net/ - - -BUILD INSTRUCTIONS - - 1. Install TUX as outlined in the QuickStart text. - Create /tux-modules where modules will reside. - - 2. Prepare PHP - - $ cd php-* - $ ./configure \ - --with-tux=/tux-modules \ - <further PHP options> - # make install - - You can see the list of valid PHP options by executing - - $ ./configure --help - - 3. Touch a file in your web-root 'php5.tux'. This will - cause requests to '/php5.tux' to be redirected to the - userspace module php5.tux. - - 4. Start TUX with something like - - # tux -d -t 8 -r /www -m /tux-modules php5.tux - - (daemon mode, eight threads, web-root /www, modules in - /tux-modules, load php5.tux) - - BEFORE running this command, the kernel side of TUX has to - be properly setup. - - 5. Try to access - - http://yourserver/php5.tux?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000 - - It should display the PHP credits page. - - To access a script /foo/bar.php, use - - http://yourserver/php5.tux?/foo/bar.php - - Parameters can be appended: - - http://yourserver/php5.tux?/foo/bar.php&var=value - diff --git a/sapi/tux/config.m4 b/sapi/tux/config.m4 deleted file mode 100644 index 06788be757..0000000000 --- a/sapi/tux/config.m4 +++ /dev/null @@ -1,16 +0,0 @@ -dnl -dnl $Id$ -dnl - -PHP_ARG_WITH(tux,, -[ --with-tux=MODULEDIR Build PHP as a TUX module (Linux only)], no, no) - -AC_MSG_CHECKING([for TUX]) -if test "$PHP_TUX" != "no"; then - INSTALL_IT="\$(INSTALL) -m 0755 $SAPI_SHARED $PHP_TUX/php5.tux.so" - AC_CHECK_HEADERS(tuxmodule.h,[:],[AC_MSG_ERROR([Cannot find tuxmodule.h])]) - PHP_SELECT_SAPI(tux, shared, php_tux.c) - AC_MSG_RESULT([$PHP_TUX]) -else - AC_MSG_RESULT(no) -fi diff --git a/sapi/tux/php.sym b/sapi/tux/php.sym deleted file mode 100644 index b968c5f5a2..0000000000 --- a/sapi/tux/php.sym +++ /dev/null @@ -1,2 +0,0 @@ -TUXAPI_handle_events -TUXAPI_init diff --git a/sapi/tux/php_tux.c b/sapi/tux/php_tux.c deleted file mode 100644 index a10ea2ae37..0000000000 --- a/sapi/tux/php_tux.c +++ /dev/null @@ -1,457 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 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> | - +----------------------------------------------------------------------+ -*/ - -#include "php.h" -#include "SAPI.h" -#include "php_main.h" -#include "php_variables.h" - -#include "ext/standard/php_smart_str.h" - -#include "tuxmodule.h" - -#include <sys/uio.h> - -#if 0 -#include <pthread.h> -#endif - -void tux_closed_conn(int fd); - -enum { - PHP_TUX_BACKGROUND_CONN = 1 -}; - -typedef struct { - user_req_t *req; - void (*on_close)(int); - int tux_action; - struct iovec *header_vec; - int number_vec; -} php_tux_globals; - -static php_tux_globals tux_globals; - -#define TG(v) (tux_globals.v) - -static int sapi_tux_ub_write(const char *str, uint str_length TSRMLS_DC) -{ - int n; - int m; - const char *estr; - - /* combine headers and body */ - if (TG(number_vec)) { - struct iovec *vec = TG(header_vec); - - n = TG(number_vec); - vec[n].iov_base = (void *) str; - vec[n++].iov_len = str_length; - - /* XXX: this might need more complete error handling */ - if ((m = writev(TG(req)->sock, vec, n)) == -1 && errno == EPIPE) - php_handle_aborted_connection(); - - if (m > 0) - TG(req)->bytes_sent += str_length; - - TG(number_vec) = 0; - return str_length; - } - - estr = str + str_length; - - while (str < estr) { - n = send(TG(req)->sock, str, estr - str, 0); - - if (n == -1 && errno == EPIPE) - php_handle_aborted_connection(); - if (n == -1 && errno == EAGAIN) - continue; - if (n <= 0) - return n; - - str += n; - } - - n = str_length - (estr - str); - - TG(req)->bytes_sent += n; - - return n; -} - -static int sapi_tux_send_headers(sapi_headers_struct *sapi_headers) -{ - char buf[1024]; - struct iovec *vec; - int n; - int max_headers; - zend_llist_position pos; - sapi_header_struct *h; - size_t len; - char *status_line; - int locate_cl; - TSRMLS_FETCH(); - - max_headers = 30; - n = 1; - - vec = malloc(sizeof(struct iovec) * max_headers); - status_line = malloc(30); - - /* safe sprintf use */ - len = slprintf(status_line, 30, "HTTP/1.1 %d NA\r\n", SG(sapi_headers).http_response_code); - - vec[0].iov_base = status_line; - vec[0].iov_len = len; - - TG(req)->http_status = SG(sapi_headers).http_response_code; - - if (TG(tux_action) == TUX_ACTION_FINISH_CLOSE_REQ && TG(req)->http_version == HTTP_1_1) - locate_cl = 1; - else - locate_cl = 0; - - h = zend_llist_get_first_ex(&sapi_headers->headers, &pos); - while (h) { - if (locate_cl - && strncasecmp(h->header, "Content-length:", sizeof("Content-length:")-1) == 0) { - TG(tux_action) = TUX_ACTION_FINISH_REQ; - locate_cl = 0; - } - - vec[n].iov_base = h->header; - vec[n++].iov_len = h->header_len; - if (n >= max_headers - 3) { - max_headers *= 2; - vec = realloc(vec, sizeof(struct iovec) * max_headers); - } - vec[n].iov_base = "\r\n"; - vec[n++].iov_len = 2; - - h = zend_llist_get_next_ex(&sapi_headers->headers, &pos); - } - - vec[n].iov_base = "\r\n"; - vec[n++].iov_len = 2; - - TG(number_vec) = n; - TG(header_vec) = vec; - - - return SAPI_HEADER_SENT_SUCCESSFULLY; -} - -static int sapi_tux_read_post(char *buffer, uint count_bytes) -{ -#if 0 - int amount = 0; - TSRMLS_FETCH(); - - TG(req)->objectlen = count_bytes; - TG(req)->object_addr = buffer; - if (tux(TUX_ACTION_READ_POST_DATA, TG(req))) - return 0; - - TG(read_post_data) = 1; - - return TG(req)->objectlen; -#else - return 0; -#endif -} - -static char *sapi_tux_read_cookies(void) -{ - TSRMLS_FETCH(); - - return TG(req)->cookies; -} - -#define BUF_SIZE 512 -#define ADD_STRING(name) \ - php_register_variable(name, buf, track_vars_array TSRMLS_CC) - -static void sapi_tux_register_variables(zval *track_vars_array TSRMLS_DC) -{ - char buf[BUF_SIZE + 1]; - char *p; - sapi_header_line ctr = {0}; - - ctr.line = buf; - ctr.line_len = slprintf(buf, sizeof(buf), "Server: %s", TUXAPI_version); - sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC); - - php_register_variable("PHP_SELF", SG(request_info).request_uri, track_vars_array TSRMLS_CC); - php_register_variable("SERVER_SOFTWARE", TUXAPI_version, track_vars_array TSRMLS_CC); - php_register_variable("GATEWAY_INTERFACE", "CGI/1.1", track_vars_array TSRMLS_CC); - php_register_variable("REQUEST_METHOD", (char *) SG(request_info).request_method, track_vars_array TSRMLS_CC); - php_register_variable("DOCUMENT_ROOT", TUXAPI_docroot, track_vars_array TSRMLS_CC); - php_register_variable("SERVER_NAME", TUXAPI_servername, track_vars_array TSRMLS_CC); - php_register_variable("REQUEST_URI", SG(request_info).request_uri, track_vars_array TSRMLS_CC); - php_register_variable("PATH_TRANSLATED", SG(request_info).path_translated, track_vars_array TSRMLS_CC); - - p = inet_ntoa(TG(req)->client_host); - /* string representation of IPs are never larger than 512 bytes */ - if (p) { - memcpy(buf, p, strlen(p) + 1); - ADD_STRING("REMOTE_ADDR"); - ADD_STRING("REMOTE_HOST"); - } - - snprintf(buf, sizeof(buf), "%d", CGI_SERVER_PORT(TG(req))); - ADD_STRING("SERVER_PORT"); - -#if 0 - snprintf(buf, BUF_SIZE, "/%s", TG(hc)->pathinfo); - ADD_STRING("PATH_INFO"); - - snprintf(buf, BUF_SIZE, "/%s", TG(hc)->origfilename); - ADD_STRING("SCRIPT_NAME"); -#endif - -#define CONDADD(name, field) \ - if (TG(req)->field[0]) { \ - php_register_variable(#name, TG(req)->field, track_vars_array TSRMLS_CC); \ - } - - CONDADD(HTTP_REFERER, referer); - CONDADD(HTTP_USER_AGENT, user_agent); - CONDADD(HTTP_ACCEPT, accept); - CONDADD(HTTP_ACCEPT_ENCODING, accept_encoding); - CONDADD(HTTP_ACCEPT_LANGUAGE, accept_language); - CONDADD(HTTP_COOKIE, cookies); - CONDADD(CONTENT_TYPE, content_type); - -#if 0 - if (TG(hc)->contentlength != -1) { - snprintf(buf, sizeof(buf), "%ld", (long) TG(hc)->contentlength); - ADD_STRING("CONTENT_LENGTH"); - } -#endif - -#if 0 - if (TG(hc)->authorization[0]) - php_register_variable("AUTH_TYPE", "Basic", track_vars_array TSRMLS_CC); -#endif -} - - -static int php_tux_startup(sapi_module_struct *sapi_module) -{ - if (php_module_startup(sapi_module, NULL, 0)==FAILURE) { - return FAILURE; - } else { - return SUCCESS; - } -} - -static sapi_module_struct tux_sapi_module = { - "tux", - "tux", - - php_tux_startup, - php_module_shutdown_wrapper, - - NULL, /* activate */ - NULL, /* deactivate */ - - sapi_tux_ub_write, - NULL, - NULL, /* get uid */ - NULL, /* getenv */ - - php_error, - - NULL, - sapi_tux_send_headers, - NULL, - sapi_tux_read_post, - sapi_tux_read_cookies, - - sapi_tux_register_variables, - NULL, /* Log message */ - NULL, /* Get request time */ - NULL, /* Child terminate */ - - STANDARD_SAPI_MODULE_PROPERTIES -}; - -static void tux_module_main(TSRMLS_D) -{ - zend_file_handle file_handle; - - file_handle.type = ZEND_HANDLE_FILENAME; - file_handle.filename = SG(request_info).path_translated; - file_handle.free_filename = 0; - file_handle.opened_path = NULL; - - if (php_request_startup(TSRMLS_C) == FAILURE) { - return; - } - - php_execute_script(&file_handle TSRMLS_CC); - php_request_shutdown(NULL); -} - -static void tux_request_ctor(TSRMLS_D) -{ - char buf[1024]; - int offset; - size_t filename_len; - size_t cwd_len; - smart_str s = {0}; - char *p; - - TG(number_vec) = 0; - TG(header_vec) = NULL; - SG(request_info).query_string = strdup(TG(req)->query); - - smart_str_appends_ex(&s, "/", 1); - smart_str_appends_ex(&s, TG(req)->query, 1); - smart_str_0(&s); - p = strchr(s.c, '&'); - if (p) - *p = '\0'; - SG(request_info).path_translated = s.c; - - s.c = NULL; - smart_str_appendc_ex(&s, '/', 1); - smart_str_appends_ex(&s, TG(req)->objectname, 1); - smart_str_0(&s); - SG(request_info).request_uri = s.c; - SG(request_info).request_method = CGI_REQUEST_METHOD(TG(req)); - if(TG(req)->http_version == HTTP_1_1) SG(request_info).proto_num = 1001; - else SG(request_info).proto_num = 1000; - SG(sapi_headers).http_response_code = 200; - SG(request_info).content_type = TG(req)->content_type; - SG(request_info).content_length = 0; /* TG(req)->contentlength; */ - -#if 0 - php_handle_auth_data(TG(hc)->authorization TSRMLS_CC); -#endif -} - -static void tux_request_dtor(TSRMLS_D) -{ - if (TG(header_vec)) { - /* free status_line */ - free(TG(header_vec)[0].iov_base); - free(TG(header_vec)); - } - if (SG(request_info).query_string) - free(SG(request_info).query_string); - free(SG(request_info).request_uri); - free(SG(request_info).path_translated); -} - -#if 0 -static void *separate_thread(void *bla) -{ - int fd; - int i = 0; - - fd = (int) bla; - - while (i++ < 5) { - send(fd, "test<br />\n", 9, 0); - sleep(1); - } - - tux(TUX_ACTION_CONTINUE_REQ, (user_req_t *) fd); - /* We HAVE to trigger some event on the fd. Otherwise - fast_thread won't wake up, so that the eventloop - won't be entered -> TUX hangs */ - shutdown(fd, 2); - pthread_exit(NULL); -} -#endif - -int TUXAPI_handle_events(user_req_t *req) -{ - TSRMLS_FETCH(); - - if (req->event == PHP_TUX_BACKGROUND_CONN) { - tux_closed_conn(req->sock); - return tux(TUX_ACTION_FINISH_CLOSE_REQ, req); - } - - TG(req) = req; - TG(tux_action) = TUX_ACTION_FINISH_CLOSE_REQ; - - tux_request_ctor(TSRMLS_C); - - tux_module_main(TSRMLS_C); - - tux_request_dtor(TSRMLS_C); - - return tux(TG(tux_action), req); -} - -void tux_register_on_close(void (*arg)(int)) -{ - TG(on_close) = arg; -} - -void tux_closed_conn(int fd) -{ - TSRMLS_FETCH(); - - if (TG(on_close)) TG(on_close)(fd); -} - -int tux_get_fd(void) -{ - TSRMLS_FETCH(); - - return TG(req)->sock; -} - -void tux_set_dont_close(void) -{ - TSRMLS_FETCH(); - - TG(req)->event = PHP_TUX_BACKGROUND_CONN; - tux(TUX_ACTION_POSTPONE_REQ, TG(req)); - TG(tux_action) = TUX_ACTION_EVENTLOOP; -} - -void TUXAPI_init(void) -{ - sapi_startup(&tux_sapi_module); - tux_sapi_module.startup(&tux_sapi_module); - SG(server_context) = (void *) 1; -} - -void doesnotmatter_fini(void) -{ - if (SG(server_context) != NULL) { - tux_sapi_module.shutdown(&tux_sapi_module); - sapi_shutdown(); - } -} - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/sapi/webjames/CREDITS b/sapi/webjames/CREDITS deleted file mode 100644 index 73a7983e92..0000000000 --- a/sapi/webjames/CREDITS +++ /dev/null @@ -1,2 +0,0 @@ -WebJames -Alex Waugh diff --git a/sapi/webjames/README b/sapi/webjames/README deleted file mode 100644 index 746a7762fb..0000000000 --- a/sapi/webjames/README +++ /dev/null @@ -1,28 +0,0 @@ -README for WebJames SAPI module -by Alex Waugh <alex@alexwaugh.com> - -This is a SAPI module for the WebJames HTTP server, which runs on the -RISC OS operating system. - - -DOWNLOADS - -A recent (February 2002 or later) version of the GCCSDK cross compiler -http://www.hard-mofo.dsvr.net/ - -WebJames 0.35 or later -http://www.webjames.alexwaugh.com/ - - -BUILDING - -$ cd php5 -$ ./configure \ - --host=arm-riscos-aof \ - --with-webjames=../webjames/src \ - --with-config-file-path=/Choices: \ - other PHP options -$ make install -$ cd ../webjames -$ ./configure --enable-php -$ make diff --git a/sapi/webjames/config.m4 b/sapi/webjames/config.m4 deleted file mode 100644 index 78c8a1936d..0000000000 --- a/sapi/webjames/config.m4 +++ /dev/null @@ -1,21 +0,0 @@ -dnl -dnl $Id$ -dnl - -PHP_ARG_WITH(webjames,, -[ --with-webjames=SRCDIR Build PHP as a WebJames module (RISC OS only)], no, no) - -AC_MSG_CHECKING([for webjames]) - -if test "$PHP_WEBJAMES" != "no"; then - PHP_EXPAND_PATH($PHP_WEBJAMES, PHP_WEBJAMES) - INSTALL_IT="\ - echo 'PHP_LIBS = -l$abs_srcdir/$SAPI_STATIC \$(PHP_LIBS) \$(EXTRA_LIBS)' > $PHP_WEBJAMES/build/php; \ - echo 'PHP_LDFLAGS = \$(NATIVE_RPATHS) \$(PHP_LDFLAGS)' >> $PHP_WEBJAMES/build/php; \ - echo 'PHP_CFLAGS = -DPHP \$(COMMON_FLAGS) \$(EXTRA_CFLAGS) -I$abs_srcdir/sapi/webjames' >> $PHP_WEBJAMES/build/php;" - PHP_ADD_INCLUDE($PHP_WEBJAMES) - PHP_SELECT_SAPI(webjames, static, webjames.c) - AC_MSG_RESULT([yes, using $PHP_WEBJAMES]) -else - AC_MSG_RESULT(no) -fi diff --git a/sapi/webjames/webjames.c b/sapi/webjames/webjames.c deleted file mode 100644 index beabeee8c3..0000000000 --- a/sapi/webjames/webjames.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 5 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2016 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: Alex Waugh <alex@alexwaugh.com> | - +----------------------------------------------------------------------+ -*/ - - -#include "php.h" -#include "SAPI.h" -#include "php_main.h" -#include "php_variables.h" - -#define WEBJAMES_PHP_ONLY -#include "php_webjames.h" - -#include <unixlib/local.h> - -#define WEBJAMES_SAPI_VERSION "1.0.2" - -typedef struct { - struct connection *conn; /*structure holding all the details of the current request*/ - int bodyread; /*amount of POST body read*/ - closefn oldclose; /*function to call to close the connection*/ -} php_webjames_globals; - -static php_webjames_globals webjames_globals; - -#define WG(v) (webjames_globals.v) - -static int sapi_webjames_ub_write(const char *str, uint str_length TSRMLS_DC) -/*unbuffered write - send data straight out to socket*/ -{ - int totalbytes = 0; - - do { - int bytes; - bytes = webjames_writebuffer(WG(conn),str,str_length); - if (bytes<0) { - PG(connection_status) = PHP_CONNECTION_ABORTED; - if (!PG(ignore_user_abort)) { - zend_bailout(); - } - return bytes; - } - str += bytes; - str_length -= bytes; - totalbytes += bytes; - } while (str_length); - return totalbytes; -} - -static void sapi_webjames_send_header(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC) -/*send an HTTP header*/ -{ - char *header = sapi_header->header; - int len = sapi_header->header_len; - if (WG(conn)->flags.outputheaders) { - while (sapi_header && len > 0) { - int bytes; - bytes = webjames_writebuffer(WG(conn), header, len); - if (bytes<0) { - PG(connection_status) = PHP_CONNECTION_ABORTED; - if (!PG(ignore_user_abort)) { - zend_bailout(); - } - return; - } - header += bytes; - len -= bytes; - } - webjames_writestring(WG(conn), "\r\n"); - } -} - -static int sapi_webjames_read_post(char *buffer, uint count_bytes TSRMLS_DC) -/*read some of the post data*/ -{ - if (WG(conn)->body==NULL) return 0; - if (count_bytes+WG(bodyread)>WG(conn)->bodysize) count_bytes=WG(conn)->bodysize-WG(bodyread); - memcpy(buffer, WG(conn)->body+WG(bodyread), count_bytes); - WG(bodyread)+=count_bytes; - return count_bytes; -} - -static char *sapi_webjames_read_cookies(TSRMLS_D) -{ - return WG(conn)->cookie; -} - -#define BUF_SIZE 512 -#define ADD_STRING(name,string)\ - php_register_variable(name, string, track_vars_array TSRMLS_CC) - -#define ADD_NUM(name,field) {\ - snprintf(buf, BUF_SIZE, "%d", WG(conn)->field);\ - php_register_variable(name, buf, track_vars_array TSRMLS_CC);\ -} - -#define ADD_FIELD(name, field) \ - if (WG(conn)->field) { \ - php_register_variable(name, WG(conn)->field, track_vars_array TSRMLS_CC); \ - } - -static void sapi_webjames_register_variables(zval *track_vars_array TSRMLS_DC) -{ - char buf[BUF_SIZE + 1]; - char *docroot; - - buf[BUF_SIZE] = '\0'; - - ADD_STRING("SERVER_SOFTWARE", configuration.server); - ADD_STRING("SERVER_NAME", configuration.serverip); - ADD_FIELD("SERVER_PROTOCOL", protocol); - ADD_NUM("SERVER_PORT", port); - ADD_STRING("SERVER_ADMIN",configuration.webmaster); - ADD_STRING("GATEWAY_INTERFACE", "CGI/1.1"); - - docroot = __unixify(WG(conn)->homedir,0,NULL,1024,0); - if (docroot) ADD_STRING("DOCUMENT_ROOT", docroot); - - ADD_FIELD("REQUEST_METHOD", methodstr); - ADD_FIELD("REQUEST_URI", requesturi); - ADD_STRING("PATH_TRANSLATED", SG(request_info).path_translated); - ADD_FIELD("SCRIPT_NAME", uri); - ADD_FIELD("PHP_SELF", uri); - ADD_FIELD("QUERY_STRING", args); - - - snprintf(buf, BUF_SIZE, "%d.%d.%d.%d", WG(conn)->ipaddr[0], WG(conn)->ipaddr[1], WG(conn)->ipaddr[2], WG(conn)->ipaddr[3]); - ADD_STRING("REMOTE_ADDR", buf); - if (WG(conn)->dnsstatus == DNS_OK) ADD_FIELD("REMOTE_HOST", host); - - if ((WG(conn)->method == METHOD_POST) || (WG(conn)->method == METHOD_PUT)) { - ADD_NUM("CONTENT_LENGTH", bodysize); - ADD_FIELD("CONTENT_TYPE", type); - } - - if ((WG(conn)->method == METHOD_PUT) || (WG(conn)->method == METHOD_DELETE)) ADD_FIELD("ENTITY_PATH", requesturi); - - if (WG(conn)->pwd) { - ADD_STRING("AUTH_TYPE", "basic"); - ADD_FIELD("REMOTE_USER", authorization); - } - - ADD_FIELD("HTTP_COOKIE", cookie); - ADD_FIELD("HTTP_USER_AGENT", useragent); - ADD_FIELD("HTTP_REFERER", referer); - ADD_FIELD("HTTP_ACCEPT", accept); - ADD_FIELD("HTTP_ACCEPT_LANGUAGE", acceptlanguage); - ADD_FIELD("HTTP_ACCEPT_CHARSET", acceptcharset); - ADD_FIELD("HTTP_ACCEPT_ENCODING", acceptencoding); -} - -static void webjames_module_main(TSRMLS_D) -{ - zend_file_handle file_handle; - FILE *fp=NULL; - char *path; - - /* Convert filename to Unix format*/ - __riscosify_control|=__RISCOSIFY_STRICT_UNIX_SPECS; - path = __unixify(WG(conn)->filename,0,NULL,1024,0); - if (path) SG(request_info).path_translated = estrdup(path); - - SG(request_info).query_string = WG(conn)->args; - SG(request_info).request_uri = WG(conn)->requesturi; - SG(request_info).request_method = WG(conn)->methodstr; - if (WG(conn)->method==METHOD_HEAD) { - SG(request_info).headers_only = 1; - } else { - SG(request_info).headers_only = 0; - } - SG(sapi_headers).http_response_code = 200; - SG(request_info).content_type = WG(conn)->type; - SG(request_info).content_length = WG(conn)->bodysize; - - SG(request_info).auth_user = NULL; - SG(request_info).auth_password = NULL; - if (WG(conn)->authorization) { - char *colon=strchr(WG(conn)->authorization,':'); - if (colon) { - SG(request_info).auth_user = emalloc(colon-WG(conn)->authorization+1); - if (SG(request_info).auth_user) { - memcpy(SG(request_info).auth_user,WG(conn)->authorization,colon-WG(conn)->authorization); - SG(request_info).auth_user[colon-WG(conn)->authorization]='\0'; - SG(request_info).auth_password = estrdup(colon+1); - } - } - } - - /*ensure that syslog calls get logged separately from WebJames' main log */ - openlog("PHP",0,0); - - file_handle.type = ZEND_HANDLE_FILENAME; - file_handle.filename = SG(request_info).path_translated; - file_handle.free_filename = 0; - file_handle.opened_path = NULL; - - if (php_request_startup(TSRMLS_C) == FAILURE) { - return; - } - - php_execute_script(&file_handle TSRMLS_CC); - php_request_shutdown(NULL); -} - -static void webjames_php_close(struct connection *conn, int force) -/*called by webjames if it wants to close the connection*/ -{ - TSRMLS_FETCH(); - - php_request_shutdown(NULL); - WG(oldclose)(conn,force); -} - -void webjames_php_request(struct connection *conn) -/*called by WebJames to start handler*/ -{ - TSRMLS_FETCH(); - - WG(conn) = conn; - WG(bodyread) = 0; - WG(oldclose) = conn->close; - conn->close=webjames_php_close; - - webjames_module_main(TSRMLS_C); - - WG(oldclose)(WG(conn), 0); -} - -static void php_info_webjames(ZEND_MODULE_INFO_FUNC_ARGS) -{ - php_info_print_table_start(); - php_info_print_table_row(2, "SAPI module version", WEBJAMES_SAPI_VERSION); - php_info_print_table_row(2, "WebJames version", WEBJAMES_VERSION " (" WEBJAMES_DATE ")"); - php_info_print_table_end(); -} - -static zend_module_entry php_webjames_module = { -#if ZEND_MODULE_API_NO >= 20010901 - STANDARD_MODULE_HEADER, -#endif - "WebJames", - NULL, - NULL, - NULL, - NULL, - NULL, - php_info_webjames, -#if ZEND_MODULE_API_NO >= 20010901 - WEBJAMES_SAPI_VERSION, -#endif - STANDARD_MODULE_PROPERTIES -}; - - -static int php_webjames_startup(sapi_module_struct *sapi_module) -{ - if(php_module_startup(sapi_module, &php_webjames_module, 1) == FAILURE) { - return FAILURE; - } else { - return SUCCESS; - } -} - -static sapi_module_struct sapi_module = { - "webjames", /* name */ - "WebJames", /* pretty name */ - - php_webjames_startup, /* startup */ - php_module_shutdown_wrapper, /* shutdown */ - - NULL, /* activate */ - NULL, /* deactivate */ - - sapi_webjames_ub_write, /* unbuffered write */ - NULL, /* flush */ - NULL, /* get uid */ - NULL, /* getenv */ - - php_error, /* error handler */ - - NULL, /* header handler */ - NULL, /* send headers handler */ - sapi_webjames_send_header, /* send header handler */ - sapi_webjames_read_post, /* read POST data */ - sapi_webjames_read_cookies, /* read Cookies */ - - sapi_webjames_register_variables, /* register server variables */ - NULL, /* Log message */ - NULL, /* Get request time */ - NULL, /* Child terminate */ - - STANDARD_SAPI_MODULE_PROPERTIES -}; - -int webjames_php_init(void) -/*called when WebJames initialises*/ -{ - TSRMLS_FETCH(); - if (strcmp(configuration.webjames_h_revision,WEBJAMES_H_REVISION)!=0) { - /*This file was compiled against a different revision of - webjames.h than webjames was, which could be bad news*/ - webjames_writelog(0,"PHP module is compiled for WebJames (%s) and was linked with a different version (%s)",WEBJAMES_H_REVISION,configuration.webjames_h_revision); - return 0; /*failed to initialise*/ - } - sapi_startup(&sapi_module); - sapi_module.startup(&sapi_module); - SG(server_context) = (void *) 1; - return 1; /*initialised correctly*/ -} - -void webjames_php_shutdown(void) -/*called when WebJames is about to quit*/ -{ - sapi_module.shutdown(&sapi_module); - sapi_shutdown(); -} |