summaryrefslogtreecommitdiff
path: root/sapi/roxen
diff options
context:
space:
mode:
Diffstat (limited to 'sapi/roxen')
-rw-r--r--sapi/roxen/Makefile.am4
-rw-r--r--sapi/roxen/README17
-rw-r--r--sapi/roxen/config.h.stub12
-rw-r--r--sapi/roxen/config.m463
-rw-r--r--sapi/roxen/phpmod.pike363
-rw-r--r--sapi/roxen/roxen.c745
6 files changed, 0 insertions, 1204 deletions
diff --git a/sapi/roxen/Makefile.am b/sapi/roxen/Makefile.am
deleted file mode 100644
index 4c6d5de6b0..0000000000
--- a/sapi/roxen/Makefile.am
+++ /dev/null
@@ -1,4 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-noinst_LTLIBRARIES=libphpsapi_roxen.la
-libphpsapi_roxen_la_SOURCES=roxen.c
diff --git a/sapi/roxen/README b/sapi/roxen/README
deleted file mode 100644
index b12662f3e3..0000000000
--- a/sapi/roxen/README
+++ /dev/null
@@ -1,17 +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. For now this uses a global lock in the PHP interpreter
-so the end result is the same (only one concurrent script). In the
-future this might change though, but for now you are better off using
-the non-ZendThreadSafe version (which works fine with Roxen and
-threads).
-
-- The Author, David Hedbor <neotron@php.net>
-
-
diff --git a/sapi/roxen/config.h.stub b/sapi/roxen/config.h.stub
deleted file mode 100644
index 4128f3170f..0000000000
--- a/sapi/roxen/config.h.stub
+++ /dev/null
@@ -1,12 +0,0 @@
-
-/* Define this if you want to build the Roxen PHP module
- * It is currently VERY EXPERIMENTAL and not finished.
- */
-#undef HAVE_ROXEN
-
-
-/* Comment to use the Roxen "serializing" instead of PHP's ZTS.
- * It seems like the Roxen PHP-global mutex lock works better,
- * performance wise.
- */
-#undef ROXEN_USE_ZTS
diff --git a/sapi/roxen/config.m4 b/sapi/roxen/config.m4
deleted file mode 100644
index b2425b2156..0000000000
--- a/sapi/roxen/config.m4
+++ /dev/null
@@ -1,63 +0,0 @@
-dnl ## $Id$ -*- sh -*-
-
-RESULT=no
-AC_MSG_CHECKING(for Roxen/Pike support)
-AC_ARG_WITH(roxen,
-[ --with-roxen=DIR Build PHP as a Pike module. DIR is the base Roxen
- directory, normally /usr/local/roxen/server.],
-[
- if test ! -d $withval ; then
- AC_MSG_ERROR(You did not specify a directory)
- fi
- if test -f $withval/bin/roxen; then
- PIKE="$withval/bin/roxen"
- elif test -f $withval/bin/pike; then
- PIKE="$withval/bin/pike"
- else
- AC_MSG_ERROR(Couldn't find a pike in $withval/bin/)
- fi
- if $PIKE -e 'float v = __VERSION__ + (__BUILD__/10000.0); if(v < 0.7079) exit(1); exit(0);'; then
- PIKE_MODULE_DIR="`$PIKE --show-paths 2>&1| grep lib/modules | 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" -o -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
- AC_ADD_INCLUDE($PIKE_INCLUDE_DIR)
- AC_DEFINE(HAVE_ROXEN)
- PHP_SAPI=roxen
- PHP_BUILD_SHARED
- INSTALL_IT="\$(SHELL) \$(srcdir)/install-sh -m 0755 $SAPI_SHARED $PIKE_MODULE_DIR/PHP4.so"
- RESULT="yes
- Pike binary used: $PIKE
- Pike include dir: $PIKE_INCLUDE_DIR
- Pike module directory: $PIKE_MODULE_DIR"
-])
-AC_MSG_RESULT($RESULT)
-
-if test "$RESULT" != "no" ; then
- RESULT=no
- AC_MSG_CHECKING(if Roxen should use ZTS)
- AC_ARG_ENABLE(roxen-zts,
- [ --enable-roxen-zts Build the Roxen module using Zend Thread Safety.
- This is not required to run the module in a threaded
- Roxen and it doesn't improve performance. PHP calls
- are normally made in a serialized mode.],
- [
- PHP_BUILD_THREAD_SAFE
- AC_DEFINE(ROXEN_USE_ZTS)
- RESULT="yes
- *** You have choosen to compile with PHP thread safety
- *** enabled. This is not a requirement for the Roxen
- *** PHP module, even if Roxen runs in multi-threaded mode.
- *** It will as a matter of fact make performance worse."
-
- ])
- AC_MSG_RESULT($RESULT)
-fi
-dnl ## Local Variables:
-dnl ## tab-width: 4
-dnl ## End:
- \ No newline at end of file
diff --git a/sapi/roxen/phpmod.pike b/sapi/roxen/phpmod.pike
deleted file mode 100644
index 35db7b4076..0000000000
--- a/sapi/roxen/phpmod.pike
+++ /dev/null
@@ -1,363 +0,0 @@
-/* Roxen PHP module based of the Roxen CGI module for Roxen 1.4. */
-
-#include <roxen.h>
-#include <module.h>
-inherit "module";
-inherit "roxenlib";
-
-constant cvs_version = "$Id$";
-constant thread_safe = 1;
-
-string trim( string what )
-{
- sscanf(what, "%*[ \t]%s", what);
- what = reverse(what);
- sscanf(what, "%*[ \t]%s", what);
- what = reverse(what);
- return what;
-}
-
-//#define PHP_DEBUG
-#ifdef PHP_DEBUG
-#define DWERROR(X) report_debug("Thr("+getpid()+"): "+X)
-#else /* !PHP_DEBUG */
-#define DWERROR(X)
-#endif /* PHP_DEBUG */
-
-array register_module()
-{
- return
- ({
- MODULE_FILE_EXTENSION | MODULE_PARSER,
- "PHP Script Support",
- "This module allows Roxen users to run PHP scripts, optionally in "
- "combination with RXML. ",
- });
-}
-
-class PHPScript
-{
- object interpretor;
- string command;
- string buffer="";
- // stderr is handled by run().
- mapping (string:string) environment;
- int blocking, written, close_when_done;
- object mid;
- void done() {
- if(strlen(buffer)) {
- close_when_done = 1;
- if(QUERY(rxml)) {
- buffer = parse_rxml(buffer, mid);
- write_callback();
- }
- } else
- destruct();
- }
-
- void destroy() {
- mid->do_not_disconnect = 0;
- // destruct(interpretor);
- mid->file = ([ "len": written, "raw":1 ]);
- // mid->do_log();
- }
- void write_callback()
- {
- DWERROR("PHP:Wrapper::write_callback()\n");
- if(!strlen(buffer))
- return;
- // int nelems = tofd->write( buffer );
- int nelems;
- array err = catch { nelems = mid->my_fd->write(buffer); };
- DWERROR(sprintf("PHP:Wrapper::write_callback(): write(%O) => %d\n",
- buffer, nelems));
- if( err || nelems < 0 )
- // if nelems == 0, network buffer is full. We still want to continue.
- {
- buffer="";
- close_when_done = -1;
- } else {
- written += nelems;
- buffer = buffer[nelems..];
- DWERROR(sprintf("Done: %d %d...\n", strlen(buffer), close_when_done));
- if(close_when_done && !strlen(buffer)) {
- destruct();
- }
- }
- }
-
- int write( string what )
- {
- DWERROR(sprintf("PHP:Wrapper::write(%O)\n", what));
- if(close_when_done == -1) // Remote closed
- return -1;
- if(buffer == "" )
- {
- buffer = what;
- if(!QUERY(rxml)) write_callback();
- } else
- buffer += what;
- return strlen(what);
- }
-
- void send_headers(int code, mapping headers)
- {
- DWERROR(sprintf("PHP:PHPWrapper::send_headers(%d,%O)\n", code, headers));
- string result = "", post="";
- string code = mid->errors[code||200];
- int ct_received = 0, sv_received = 0;
- if(headers)
- foreach(indices(headers), string header)
- {
- string value = headers[header];
- if(!header || !value)
- {
- // Heavy DWIM. For persons who forget about headers altogether.
- continue;
- }
- header = trim(header);
- value = trim(value);
- switch(lower_case( header ))
- {
- case "status":
- code = value;
- break;
-
- case "content-type":
- ct_received=1;
- result += header+": "+value+"\r\n";
- break;
-
- case "server":
- sv_received=1;
- result += header+": "+value+"\r\n";
- break;
-
- case "location":
- code = "302 Redirection";
- result += header+": "+value+"\r\n";
- break;
-
- default:
- result += header+": "+value+"\r\n";
- break;
- }
- }
- if(!sv_received)
- result += "Server: "+roxen.version()+"/PHP\r\n";
- if(!ct_received)
- result += "Content-Type: text/html\r\n";
- write("HTTP/1.0 "+code+"\r\n"+result+"\r\n");
- }
-
- PHPScript run()
- {
- DWERROR("PHP:PHPScript::run()\n");
- // if( QUERY(rxml) )
- // stdout = (wrapper = RXMLWrapper( stdout, mid ))->get_fd();
- mapping options = ([
- "env":environment,
- ]);
-#if 1
- if(!QUERY(rxml)) {
- mid->my_fd->set_blocking();
- options->my_fd = mid->my_fd;
- }
-#endif
- mid->my_fd->set_close_callback(done);
- interpretor->run(command, options, this_object(), done);
- return this_object();
- }
-
-
- void create( object id )
- {
- DWERROR("PHP:PHPScript()\n");
- interpretor = PHP4.Interpretor();
- mid = id;
-
-#ifndef THREADS
- if(id->misc->orig) // An <insert file=...> operation, and we have no threads.
- blocking = 1;
-#else
- if(id->misc->orig && this_thread() == roxen.backend_thread)
- blocking = 1;
- // An <insert file=...> and we are
- // currently in the backend thread.
-#endif
- if(!id->realfile)
- {
- id->realfile = id->conf->real_file( id->not_query, id );
- if(!id->realfile)
- error("No real file associated with "+id->not_query+
- ", thus it's not possible to run it as a PHP script.\n");
- }
- command = id->realfile;
-
- environment =(QUERY(env)?getenv():([]));
- environment |= global_env;
- environment |= build_env_vars( id->realfile, id, id->misc->path_info );
- environment |= build_roxen_env_vars(id);
- if(id->misc->ssi_env) environment |= id->misc->ssi_env;
- if(id->misc->is_redirected) environment["REDIRECT_STATUS"] = "1";
- if(id->rawauth && QUERY(rawauth))
- environment["HTTP_AUTHORIZATION"] = (string)id->rawauth;
- else
- m_delete(environment, "HTTP_AUTHORIZATION");
- if(QUERY(clearpass) && id->auth && id->realauth ) {
- environment["REMOTE_USER"] = (id->realauth/":")[0];
- environment["REMOTE_PASSWORD"] = (id->realauth/":")[1];
- } else {
- m_delete(environment, "REMOTE_PASSWORD");
- }
- if (id->rawauth) {
- environment["AUTH_TYPE"] = (id->rawauth/" ")[0];
- }
- // DWERROR(sprintf("%O\n", environment));
- // ffd = id->my_fd;
- }
-}
-
-mapping(string:string) global_env = ([]);
-void start(int n, object conf)
-{
- DWERROR("PHP:start()\n");
-
- module_dependencies(conf, ({ "pathinfo" }));
- if(conf)
- {
- string tmp=conf->query("MyWorldLocation");
- sscanf(tmp, "%*s//%s", tmp);
- sscanf(tmp, "%s:", tmp);
- sscanf(tmp, "%s/", tmp);
- global_env["SERVER_NAME"]=tmp;
- global_env["SERVER_SOFTWARE"]=roxen.version();
- global_env["GATEWAY_INTERFACE"]="PHP/1.1";
- global_env["SERVER_PROTOCOL"]="HTTP/1.0";
- global_env["SERVER_URL"]=conf->query("MyWorldLocation");
-
- array us = ({0,0});
- foreach(query("extra_env")/"\n", tmp)
- if(sscanf(tmp, "%s=%s", us[0], us[1])==2)
- global_env[us[0]] = us[1];
- }
-}
-mapping handle_file_extension(object o, string e, object id)
-{
- DWERROR("PHP:handle_file_extension()\n");
- id->do_not_disconnect = 1;
- PHPScript( id )->run();
- return http_pipe_in_progress();
-}
-/*
-** Variables et. al.
-*/
-array (string) query_file_extensions()
-{
- return QUERY(ext);
-}
-
-
-void create(object conf)
-{
- defvar("env", 0, "Pass environment variables", TYPE_FLAG,
- "If this is set, all environment variables roxen has will be "
- "passed to PHP scripts, not only those defined in the PHP/1.1 standard. "
- "This includes PATH. (For a quick test, try this script with "
- "and without this variable set:"
- "<pre>"
- "#!/bin/sh\n\n"
- "echo Content-type: text/plain\n"
- "echo ''\n"
- "env\n"
- "</pre>)");
-
- defvar("rxml", 0, "Parse RXML in PHP-scripts", TYPE_FLAG,
- "If this is set, the output from PHP-scripts handled by this "
- "module will be RXMl parsed. NOTE: No data will be returned to the "
- "client until the PHP-script is fully parsed.");
-
- defvar("extra_env", "", "Extra environment variables", TYPE_TEXT_FIELD,
- "Extra variables to be sent to the script, format:<pre>"
- "NAME=value\n"
- "NAME=value\n"
- "</pre>Please note that the standard variables will have higher "
- "priority.");
-
- defvar("ext",
- ({"php", "php3", "php4"
- }), "PHP-script extensions", TYPE_STRING_LIST,
- "All files ending with these extensions, will be parsed as "+
- "PHP-scripts.");
-
- defvar("rawauth", 0, "Raw user info", TYPE_FLAG|VAR_MORE,
- "If set, the raw, unparsed, user info will be sent to the script, "
- " in the HTTP_AUTHORIZATION environment variable. This is not "
- "recommended, but some scripts need it. Please note that this "
- "will give the scripts access to the password used.");
-
- defvar("clearpass", 0, "Send decoded password", TYPE_FLAG|VAR_MORE,
- "If set, the variable REMOTE_PASSWORD will be set to the decoded "
- "password value.");
-
- defvar( "cgi_tag", 1, "Provide the &lt;cgi&gt; tag", TYPE_FLAG,
- "If set, the &lt;cgi&gt; tag will be available" );
-}
-
-int|string tag_cgi( string tag, mapping args, object id )
-{
- DWERROR("PHP:tag_cgi()\n");
-
- if(!query("cgi_tag"))
- return 0;
-
- if(args->help)
- return ("<b>&lt;"+tag+" script=path [cache=seconds] [default-argument=value] "
- "[argument=value]&gt;:</b>");
-
- if(!args->cache)
- NOCACHE();
- else
- CACHE( (int)args->cache || 60 );
-
-
- object fid = id->clone_me();
- string file = args->script;
- if(!file)
- return "No 'script' argument to the PHP tag";
- fid->not_query = fix_relative( file, id );
- foreach(indices(args), string arg )
- {
- if(arg == "script")
- continue;
- if(arg == "cache")
- continue;
- if(arg[..7] == "default-")
- {
- if(!id->variables[arg[8..]])
- fid->variables[arg[8..]] = args[arg];
- }
- else
- fid->variables[arg] = args[arg];
- }
- fid->realfile=0;
- fid->method = "GET";
- mixed e = catch
- {
- string data=handle_file_extension( 0, "cgi", fid )->file->read();
- if(!sscanf(data, "%*s\r\n\r\n%s", data))
- sscanf(data, "%*s\n\n%s", data);
- return data;
- };
- return ("Failed to run PHP script: <font color=red><pre>"+
- (html_encode_string(describe_backtrace(e))/"\n")[0]+
- "</pre></font>");
-}
-
-
-mapping query_tag_callers()
-{
- return ([
- "cgi":tag_cgi,
- ]);
-}
diff --git a/sapi/roxen/roxen.c b/sapi/roxen/roxen.c
deleted file mode 100644
index 1ec54f3138..0000000000
--- a/sapi/roxen/roxen.c
+++ /dev/null
@@ -1,745 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP version 4.0 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997, 1998, 1999 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 2.0 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available at through the world-wide-web at |
- | http://www.php.net/license/2_0.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 "main.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>
-
-/* 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 *)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) fprintf(stderr, "*** php lock (thr_id=%d, glob=%d).\n", th_self(), current_thread);THREADS_ALLOW();mt_lock(&roxen_php_execution_lock);fprintf(stderr, "*** php locked.\n");THREADS_DISALLOW()
-# define PHP_UNLOCK(X) mt_unlock(&roxen_php_execution_lock);fprintf(stderr, "*** php unlocked (thr_id=%d, glob=%d).\n", th_self(), current_thread);
-# define PHP_DESTROY() mt_destroy(&roxen_php_execution_lock)
-#else /* !_REENTRANT */
-# define PHP_INIT_LOCK()
-# define PHP_LOCK(X) fprintf(stderr, "*** php lock (thr_id=%d).\n", th_self());
-# define PHP_UNLOCK(X) fprintf(stderr, "*** php unlock (thr_id=%d).\n", th_self());
-# 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 interpretor to be locked.
- */
-#define THREAD_SAFE_RUN(COMMAND, what) do {\
- struct thread_state *state;\
- fprintf(stderr,"threads: %d disabled: %d id: %d\n",num_threads, threads_disabled, th_self());\
- if((state = thread_state_for_id(th_self()))!=NULL) {\
- if(!state->swapped) {\
- fprintf(stderr, "MT lock (%s).\n", what);\
- COMMAND;\
- fprintf(stderr, "MT locked done (%s).\n", what);\
- } else {\
- fprintf(stderr, "MT nonlock (%s).\n", what); \
- mt_lock(&interpreter_lock);\
- SWAP_IN_THREAD(state);\
- fprintf(stderr, "MT locked.\n", what); \
- COMMAND;\
- fprintf(stderr, "MT locked done.\n", what); \
- SWAP_OUT_THREAD(state);\
- mt_unlock(&interpreter_lock);\
- fprintf(stderr, "MT unlocked.\n", what); \
- }\
- }\
-} while(0)
-
-/* Toggle debug printouts, for now... */
-/*#define MUCH_DEBUG */
-#ifndef MUCH_DEBUG
-void no_fprintf(){}
-#define fprintf no_fprintf
-#endif
-
-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) {
- fprintf(stderr, "Header lookup for %s: default (%s)\n", headername,
- default_value);
- return default_value;
- }
- fprintf(stderr, "Header lookup for %s: %s(%d)\n", headername,
- head->u.string->str, head->u.string->len);
- 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) {
- fprintf(stderr, "Header lookup for %s: default (%d)\n", headername,
- default_value);
- return default_value;
- }
- fprintf(stderr, "Header lookup for %s: %d \n", headername,
- head->u.integer);
- 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 *
- * interpretor for better threading.
- */
-
-static int
-php_roxen_low_ub_write(const char *str, uint str_length) {
- int sent_bytes = 0;
- struct pike_string *to_write = NULL;
-#ifdef ZTS
- PLS_FETCH();
-#endif
-#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(sp[-1].type == PIKE_T_INT)
- sent_bytes = 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();
- }
- fprintf(stderr, "low_write done.\n");
- 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)
-{
- 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),
- "write");
- }
- fprintf(stderr, "write done.\n");
- 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);
-
- fprintf(stderr, "Setting header %s to %s\n", hind->str, value);
- 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 SLS_DC)
-{
- char *header_name, *header_content, *p;
- header_name = sapi_header->header;
- header_content = p = strchr(header_name, ':');
-
- if(!p) return 0;
- do {
- header_content++;
- } while(*header_content == ' ');
- THREAD_SAFE_RUN(php_roxen_set_header(header_name, header_content, p), "header handler");
- efree(sapi_header->header);
- return 1;
-}
-
-/*
- * 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 SLS_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);
- fprintf(stderr, "Send Headers (%d)...\n", SG(sapi_headers).http_response_code);
-
- 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 SLS_DC)
-{
- int res = 0;
- THREAD_SAFE_RUN(res = php_roxen_low_send_headers(sapi_headers SLS_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
- fprintf(stderr, "read post (%d bytes max)\n", count_bytes);
-
- 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(sp[-1].type == T_STRING) {
- MEMCPY(buf, sp[-1].u.string->str, total_read = sp[-1].u.string->len);
- buf[total_read] = '\0';
- } else
- total_read = -1;
- pop_stack();
- return total_read;
-}
-
-static int
-php_roxen_sapi_read_post(char *buf, uint count_bytes SLS_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(SLS_D)
-{
- char *cookies;
- cookies = lookup_string_header("HTTP_COOKIE", NULL);
- return cookies;
-}
-
-static void php_info_roxen(ZEND_MODULE_INFO_FUNC_ARGS)
-{
-#if 0
- char buf[512];
-
- PUTS("<table border=5 width=600>\n");
- 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);
- */
- PUTS("</table>");
-#endif
-}
-
-static zend_module_entry php_roxen_module = {
- "Roxen",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- php_info_roxen,
- STANDARD_MODULE_PROPERTIES
-};
-
-static int php_roxen_startup(sapi_module_struct *sapi_module)
-{
- if(php_module_startup(sapi_module) == FAILURE
- || zend_register_module(&php_roxen_module) == FAILURE) {
- return FAILURE;
- } else {
- return SUCCESS;
- }
-}
-
-/* this structure is static (as in "it does not change") */
-
-void pike_module_exit(void);
-
-static sapi_module_struct sapi_module = {
- "PHP Language",
-
- php_module_startup, /* startup */
- pike_module_exit, /* shutdown */
-
- php_roxen_sapi_ub_write, /* unbuffered write */
-
- 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 */
-
- 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(pval); \
- pval->type = IS_STRING; \
- pval->value.str.len = strlen(buf); \
- pval->value.str.val = estrndup(buf, pval->value.str.len); \
- zend_hash_update(&EG(symbol_table), name, sizeof(name), \
- &pval, sizeof(zval *), NULL)
-
-static void
-php_roxen_hash_environment(CLS_D ELS_DC PLS_DC SLS_DC)
-{
- int i;
- char buf[512];
- zval *pval;
- 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(pval);
- pval->type = IS_STRING;
- pval->value.str.len = val->u.string->len;
- pval->value.str.val = estrndup(val->u.string->str, pval->value.str.len);
- /* fprintf(stderr, "Header: %s(%d)=%s\n", buf, buf_len, val->u.string->str);*/
-
- zend_hash_update(&EG(symbol_table), buf, buf_len + 1, &pval, sizeof(zval *), NULL);
- }
- }
- free_array(indices);
- }
-
- /*
- MAKE_STD_ZVAL(pval);
- pval->type = IS_LONG;
- pval->value.lval = Ns_InfoBootTime();
- zend_hash_update(&EG(symbol_table), "SERVER_BOOTTIME", sizeof("SERVER_BOOTTIME"), &pval, sizeof(zval *), NULL);
-
- fprintf(stderr, "Set up header environment.\n");
- */
-}
-
-/*
- * php_roxen_module_main() is called by the per-request handler and
- * "executes" the script
- */
-
-static int php_roxen_module_main(SLS_D)
-{
- int res;
- zend_file_handle file_handle;
-#ifdef ZTS
- CLS_FETCH();
- PLS_FETCH();
- ELS_FETCH();
-#ifdef ROXEN_USE_ZTS
- GET_THIS();
-#endif
-#endif
- file_handle.type = ZEND_HANDLE_FILENAME;
- file_handle.filename = THIS->filename;
- file_handle.free_filename = 0;
- THREADS_ALLOW();
- fprintf(stderr, "Request Startup.\n");
- res = php_request_startup(CLS_C ELS_CC PLS_CC SLS_CC);
- THREADS_DISALLOW();
- if(res == FAILURE) {
- return 0;
- }
- php_roxen_hash_environment(CLS_C ELS_CC PLS_CC SLS_CC);
- THREADS_ALLOW();
- fprintf(stderr, "Script Execute.\n");
- php_execute_script(&file_handle CLS_CC ELS_CC PLS_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;
- SLS_FETCH();
-#ifdef ROXEN_USE_ZTS
- GET_THIS();
-#endif
-
- if(current_thread == th_self())
- error("PHP4.Interpetor->run: Tried to run a PHP-script from a PHP "
- "callback!");
- get_all_args("PHP4.Interpretor->run", args, "%S%m%O%*", &script,
- &request_data, &my_fd_obj, &done_callback);
- if(done_callback->type != PIKE_T_FUNCTION)
- error("PHP4.Interpretor->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 the absolute path to the file */
- SG(request_info).path_translated =
- lookup_string_header("PATH_TRANSLATED", 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("CONTENT_LENGTH", 0);
- SG(request_info).content_type = "text/html";
- 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)
- error("PHP4.Interpretor->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(SLS_C);
- current_thread = -1;
- PHP_UNLOCK(THIS);
-
- apply_svalue(done_callback, 0);
- pop_stack();
- pop_n_elems(args);
- push_int(status);
-
-}
-
-
-/* Clear the object global struct */
-static void clear_struct(struct object *o)
-{
- MEMSET(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()
-{
- if (!roxen_php_initialized) {
-#ifdef ZTS
- tsrm_startup(1, 1, 0);
-#ifdef ROXEN_USE_ZTS
- roxen_globals_id = ts_allocate_id(sizeof(php_roxen_request), NULL, NULL);
-#endif
-#endif
- sapi_startup(&sapi_module);
- php_roxen_startup(&sapi_module);
- 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("Interpretor", (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;
- sapi_module.shutdown(&sapi_module);
- if(php_program) free_program(php_program);
-#ifdef ZTS
- tsrm_shutdown();
-#endif
- PHP_DESTROY();
-}
-#endif