5 changed files with 1343 additions and 0 deletions
-
314sapi/roxen/Makefile
-
9sapi/roxen/README
-
26sapi/roxen/config.m4
-
356sapi/roxen/phpmod.pike
-
638sapi/roxen/roxen.c
@ -0,0 +1,314 @@ |
|||
# Generated automatically from Makefile.in by configure.
|
|||
# Makefile.in generated automatically by automake 1.4a from Makefile.am
|
|||
|
|||
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
|
|||
# This Makefile.in is free software; the Free Software Foundation
|
|||
# gives unlimited permission to copy and/or distribute it,
|
|||
# with or without modifications, as long as this notice is preserved.
|
|||
|
|||
# This program is distributed in the hope that it will be useful,
|
|||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
|||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|||
# PARTICULAR PURPOSE.
|
|||
|
|||
SHELL = /bin/sh |
|||
|
|||
srcdir = . |
|||
top_srcdir = ../.. |
|||
prefix = /usr/local |
|||
exec_prefix = ${prefix} |
|||
|
|||
bindir = ${exec_prefix}/bin |
|||
sbindir = ${exec_prefix}/sbin |
|||
libexecdir = ${exec_prefix}/libexec |
|||
datadir = ${prefix}/share |
|||
sysconfdir = ${prefix}/etc |
|||
sharedstatedir = ${prefix}/com |
|||
localstatedir = ${prefix}/var |
|||
libdir = ${exec_prefix}/lib |
|||
infodir = ${prefix}/info |
|||
mandir = ${prefix}/man |
|||
includedir = ${prefix}/include |
|||
oldincludedir = /usr/include |
|||
|
|||
DESTDIR = |
|||
|
|||
pkgdatadir = $(datadir)/php |
|||
pkglibdir = $(libdir)/php |
|||
pkgincludedir = $(includedir)/php |
|||
|
|||
top_builddir = ../.. |
|||
|
|||
ACLOCAL = aclocal |
|||
AUTOCONF = autoconf |
|||
AUTOMAKE = automake |
|||
AUTOHEADER = autoheader |
|||
|
|||
INSTALL = /usr/bin/install -c |
|||
INSTALL_PROGRAM = ${INSTALL} |
|||
INSTALL_DATA = ${INSTALL} -m 644 |
|||
INSTALL_SCRIPT = ${INSTALL} |
|||
INSTALL_STRIP_FLAG = |
|||
transform = s,x,x, |
|||
|
|||
NORMAL_INSTALL = : |
|||
PRE_INSTALL = : |
|||
POST_INSTALL = : |
|||
NORMAL_UNINSTALL = : |
|||
PRE_UNINSTALL = : |
|||
POST_UNINSTALL = : |
|||
host_alias = i686-pc-linux-gnu |
|||
host_triplet = i686-pc-linux-gnu |
|||
AMTAR = gtar |
|||
AMTARFLAGS = o |
|||
AS = @AS@ |
|||
CC = gcc |
|||
CFLAGS = -g -O2 -g -O2 |
|||
DEBUG_CFLAGS = -g |
|||
DLLTOOL = @DLLTOOL@ |
|||
EXTRA_LDFLAGS = -avoid-version |
|||
EXTRA_LIBS = -ldl -lgd -lm -lresolv -lnsl -lcrypt -lgdbm -lttf -L/usr/lib/mysql -lmysqlclient -lpam |
|||
EXT_LIBS = db/libphpext_db.a gd/libphpext_gd.a mysql/libphpext_mysql.a pcre/libphpext_pcre.a session/libphpext_session.a standard/libphpext_standard.a |
|||
EXT_LTLIBS = ext/db/libphpext_db.la ext/gd/libphpext_gd.la ext/mysql/libphpext_mysql.la ext/pcre/libphpext_pcre.la ext/session/libphpext_session.la ext/standard/libphpext_standard.la |
|||
EXT_SHARED = |
|||
EXT_STATIC = db gd mysql pcre session standard |
|||
EXT_SUBDIRS = db gd mysql pcre session standard |
|||
HSREGEX = |
|||
INCLUDES = -I$(top_builddir)/libzend -I$(top_srcdir) -I$(top_srcdir)/libzend -I/tmp/dmalloc-pike//pike/0.7.79/include/pike/ -I/usr/include/mysql |
|||
INSTALL_IT = $(SHELL) $(srcdir)/install-sh -m 0755 libs/libphp4.so /tmp/dmalloc-pike//pike/0.7.79/lib/modules/PHP4.so |
|||
LD = /usr/bin/ld |
|||
LEX = flex |
|||
LEX_CFLAGS = -DYY_USE_CONST |
|||
LIBTOOL = $(SHELL) $(top_builddir)/libtool --silent |
|||
LN_S = ln -s |
|||
MAINT = # |
|||
MAKEINFO = makeinfo |
|||
NATIVE_RPATHS = -Wl,-rpath,/usr/lib/mysql |
|||
NM = /usr/bin/nm -B |
|||
OBJDUMP = @OBJDUMP@ |
|||
PACKAGE = php |
|||
PERL_PATH = /usr/bin/perl |
|||
PHP_BUILD_DATE = 1999-11-23 |
|||
PHP_DEBUG = 1 |
|||
PHP_LIBS = |
|||
PHP_PROGRAM = |
|||
PHP_RPATHS = -R /usr/lib/mysql |
|||
PHP_SAPI = roxen |
|||
PHP_VERSION = 4.0b4-dev |
|||
PROG_SENDMAIL = /usr/sbin/sendmail |
|||
RANLIB = ranlib |
|||
REGEX_DIR = regex |
|||
REGEX_LIB = regex/libregex.la |
|||
TSRM_DIR = |
|||
TSRM_LIB = |
|||
VERSION = 4.0b4-dev |
|||
WARNING_LEVEL = |
|||
YACC = bison -y |
|||
abs_builddir = /home/neotron/src/php4 |
|||
abs_srcdir = /home/neotron/src/php4 |
|||
phplibdir = /home/neotron/src/php4/modules |
|||
phptempdir = /home/neotron/src/php4/libs |
|||
|
|||
|
|||
noinst_LTLIBRARIES = libphpsapi_roxen.la |
|||
libphpsapi_roxen_la_SOURCES = roxen.c |
|||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs |
|||
CONFIG_HEADER = ../../php_config.h |
|||
CONFIG_CLEAN_FILES = |
|||
LTLIBRARIES = $(noinst_LTLIBRARIES) |
|||
|
|||
|
|||
DEFS = -DHAVE_CONFIG_H -I. -I$(srcdir) -I../.. |
|||
CPPFLAGS = |
|||
LDFLAGS = |
|||
LIBS = |
|||
libphpsapi_roxen_la_LDFLAGS = |
|||
libphpsapi_roxen_la_LIBADD = |
|||
am_libphpsapi_roxen_la_OBJECTS = roxen.lo |
|||
libphpsapi_roxen_la_OBJECTS = $(am_libphpsapi_roxen_la_OBJECTS) |
|||
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) |
|||
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) |
|||
CCLD = $(CC) |
|||
LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ |
|||
DIST_SOURCES = $(libphpsapi_roxen_la_SOURCES) |
|||
DIST_COMMON = README Makefile.am Makefile.in |
|||
|
|||
|
|||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) |
|||
|
|||
GZIP_ENV = --best |
|||
SOURCES = $(libphpsapi_roxen_la_SOURCES) |
|||
OBJECTS = $(am_libphpsapi_roxen_la_OBJECTS) |
|||
|
|||
all: all-redirect |
|||
.SUFFIXES: |
|||
.SUFFIXES: .c .lo .o |
|||
$(srcdir)/Makefile.in: # Makefile.am $(top_srcdir)/$(altdir)configure.in $(ACLOCAL_M4)
|
|||
cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps sapi/roxen/Makefile |
|||
|
|||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status |
|||
cd $(top_builddir) \
|
|||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status |
|||
|
|||
|
|||
mostlyclean-noinstLTLIBRARIES: |
|||
|
|||
clean-noinstLTLIBRARIES: |
|||
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) |
|||
|
|||
distclean-noinstLTLIBRARIES: |
|||
|
|||
maintainer-clean-noinstLTLIBRARIES: |
|||
|
|||
.c.o: |
|||
$(COMPILE) -c $< |
|||
|
|||
mostlyclean-compile: |
|||
-rm -f *.o core *.core |
|||
|
|||
clean-compile: |
|||
|
|||
distclean-compile: |
|||
-rm -f *.tab.c |
|||
|
|||
maintainer-clean-compile: |
|||
|
|||
.c.lo: |
|||
$(LIBTOOL) --mode=compile $(COMPILE) -c -o $@ $< |
|||
|
|||
mostlyclean-libtool: |
|||
-rm -f *.lo |
|||
|
|||
clean-libtool: |
|||
-rm -rf .libs _libs |
|||
|
|||
distclean-libtool: |
|||
|
|||
maintainer-clean-libtool: |
|||
roxen.lo: |
|||
|
|||
libphpsapi_roxen.la: $(libphpsapi_roxen_la_OBJECTS) $(libphpsapi_roxen_la_DEPENDENCIES) |
|||
$(LINK) $(libphpsapi_roxen_la_LDFLAGS) $(libphpsapi_roxen_la_OBJECTS) $(libphpsapi_roxen_la_LIBADD) $(LIBS) |
|||
|
|||
tags: TAGS |
|||
|
|||
ID: $(HEADERS) $(SOURCES) $(LISP) |
|||
list='$(SOURCES) $(HEADERS)'; \
|
|||
unique=`for i in $$list; do echo $$i; done | \
|
|||
awk ' { files[$$0] = 1; } \
|
|||
END { for (i in files) print i; }'`; \
|
|||
here=`pwd` && cd $(srcdir) \
|
|||
&& mkid -f$$here/ID $$unique $(LISP) |
|||
|
|||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) |
|||
tags=; \
|
|||
here=`pwd`; \
|
|||
list='$(SOURCES) $(HEADERS)'; \
|
|||
unique=`for i in $$list; do echo $$i; done | \
|
|||
awk ' { files[$$0] = 1; } \
|
|||
END { for (i in files) print i; }'`; \
|
|||
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|
|||
|| (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) |
|||
|
|||
mostlyclean-tags: |
|||
|
|||
clean-tags: |
|||
|
|||
distclean-tags: |
|||
-rm -f TAGS ID |
|||
|
|||
maintainer-clean-tags: |
|||
|
|||
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) |
|||
|
|||
subdir = sapi/roxen |
|||
|
|||
distdir: $(DISTFILES) |
|||
@for file in $(DISTFILES); do \
|
|||
d=$(srcdir); \
|
|||
if test -d $$d/$$file; then \
|
|||
cp -pr $$d/$$file $(distdir)/$$file; \
|
|||
else \
|
|||
test -f $(distdir)/$$file \
|
|||
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|
|||
|| cp -p $$d/$$file $(distdir)/$$file || :; \
|
|||
fi; \
|
|||
done |
|||
info-am: |
|||
info: info-am |
|||
dvi-am: |
|||
dvi: dvi-am |
|||
check-am: all-am |
|||
check: check-am |
|||
installcheck-am: |
|||
installcheck: installcheck-am |
|||
install-exec-am: |
|||
install-exec: install-exec-am |
|||
|
|||
install-data-am: |
|||
install-data: install-data-am |
|||
|
|||
install-am: all-am |
|||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am |
|||
install: install-am |
|||
uninstall-am: |
|||
uninstall: uninstall-am |
|||
all-am: Makefile $(LTLIBRARIES) |
|||
all-redirect: all-am |
|||
install-strip: |
|||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install |
|||
installdirs: |
|||
|
|||
|
|||
mostlyclean-generic: |
|||
|
|||
clean-generic: |
|||
|
|||
distclean-generic: |
|||
-rm -f Makefile $(CONFIG_CLEAN_FILES) |
|||
-rm -f config.cache config.log stamp-h stamp-h[0-9]* |
|||
|
|||
maintainer-clean-generic: |
|||
mostlyclean-am: mostlyclean-noinstLTLIBRARIES mostlyclean-compile \ |
|||
mostlyclean-libtool mostlyclean-tags \
|
|||
mostlyclean-generic |
|||
|
|||
mostlyclean: mostlyclean-am |
|||
|
|||
clean-am: clean-noinstLTLIBRARIES clean-compile clean-libtool \ |
|||
clean-tags clean-generic mostlyclean-am |
|||
|
|||
clean: clean-am |
|||
|
|||
distclean-am: distclean-noinstLTLIBRARIES distclean-compile \ |
|||
distclean-libtool distclean-tags distclean-generic \
|
|||
clean-am |
|||
-rm -f libtool |
|||
|
|||
distclean: distclean-am |
|||
|
|||
maintainer-clean-am: maintainer-clean-noinstLTLIBRARIES \ |
|||
maintainer-clean-compile maintainer-clean-libtool \
|
|||
maintainer-clean-tags maintainer-clean-generic \
|
|||
distclean-am |
|||
@echo "This command is intended for maintainers to use;" |
|||
@echo "it deletes files that may require special tools to rebuild." |
|||
|
|||
maintainer-clean: maintainer-clean-am |
|||
|
|||
.PHONY: mostlyclean-noinstLTLIBRARIES distclean-noinstLTLIBRARIES \ |
|||
clean-noinstLTLIBRARIES maintainer-clean-noinstLTLIBRARIES \ |
|||
mostlyclean-compile distclean-compile clean-compile \ |
|||
maintainer-clean-compile mostlyclean-libtool distclean-libtool \ |
|||
clean-libtool maintainer-clean-libtool tags mostlyclean-tags \ |
|||
distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ |
|||
dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ |
|||
install-exec install-data-am install-data install-am install \ |
|||
uninstall-am uninstall all-redirect all-am all install-strip \ |
|||
installdirs mostlyclean-generic distclean-generic clean-generic \ |
|||
maintainer-clean-generic clean mostlyclean distclean maintainer-clean |
|||
|
|||
|
|||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
|||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
|||
.NOEXPORT: |
|||
@ -0,0 +1,9 @@ |
|||
Roxen PHP support. Very early version. Don't expect to be able to get |
|||
it to work. Requires a very late Pike 0.7 and Roxen 1.4. Anything else will be |
|||
futile, and even that might be. Beware! It is not thread safe yet. As |
|||
a matter of fact it doesn't work when threads are enabled when |
|||
compiling PHP |
|||
|
|||
- The Author, David Hedbor <neotron@php.net> |
|||
|
|||
|
|||
@ -0,0 +1,26 @@ |
|||
dnl ## $Id$ -*- sh -*- |
|||
|
|||
RESULT=no |
|||
AC_MSG_CHECKING(for Roxen/Pike support) |
|||
AC_ARG_WITH(roxen, |
|||
[ --with-roxen=DIR], |
|||
[ |
|||
if test ! -d $withval ; then |
|||
AC_MSG_ERROR(You did not specify a directory) |
|||
fi |
|||
/* enable_thread_safety=yes*/ |
|||
/* passthru="$passthru --enable-thread-safety"*/ |
|||
ROXEN_DIR=$withval |
|||
AC_ADD_INCLUDE($ROXEN_DIR/pike/0.7.79/include/pike/) |
|||
AC_DEFINE(HAVE_ROXEN) |
|||
PHP_SAPI=roxen |
|||
PHP_BUILD_SHARED |
|||
INSTALL_IT="\$(SHELL) \$(srcdir)/install-sh -m 0755 $SAPI_SHARED $ROXEN_DIR/pike/0.7.79/lib/modules/PHP4.so" |
|||
RESULT=yes |
|||
]) |
|||
AC_MSG_RESULT($RESULT) |
|||
|
|||
dnl ## Local Variables: |
|||
dnl ## tab-width: 4 |
|||
dnl ## End: |
|||
|
|||
@ -0,0 +1,356 @@ |
|||
/* Roxen PHP module based of the Roxen PHP 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(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, |
|||
]); |
|||
thread_create(interpretor->run, command, options, this_object(), done); |
|||
mid->my_fd->set_close_callback(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 <cgi> tag", TYPE_FLAG, |
|||
"If set, the <cgi> 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><"+tag+" script=path [cache=seconds] [default-argument=value] " |
|||
"[argument=value]>:</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, |
|||
]); |
|||
} |
|||
@ -0,0 +1,638 @@ |
|||
/* |
|||
+----------------------------------------------------------------------+ |
|||
| 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" |
|||
|
|||
/* 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 |
|||
|
|||
#ifdef ZTS |
|||
#error Roxen PHP module isnt thread safe at the moment. |
|||
#endif |
|||
|
|||
#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> |
|||
|
|||
#ifdef _REENTRANT |
|||
static PIKE_MUTEX_T roxen_php_execution_lock; |
|||
#define PHP_INIT_LOCK() mt_init(&roxen_php_execution_lock) |
|||
#define PHP_LOCK() fprintf(stderr, "*** php lock.\n");THREADS_ALLOW();mt_lock(&roxen_php_execution_lock);fprintf(stderr, "*** php locked.\n");THREADS_DISALLOW() |
|||
#define PHP_UNLOCK() mt_unlock(&roxen_php_execution_lock);fprintf(stderr, "*** php unlocked.\n"); |
|||
#define PHP_DESTROY() mt_destroy(&roxen_php_execution_lock) |
|||
#else /* !_REENTRANT */ |
|||
#define PHP_INIT_LOCK() |
|||
#define PHP_LOCK() |
|||
#define PHP_UNLOCK() |
|||
#define PHP_DESTROY() |
|||
#endif /* _REENTRANT */ |
|||
|
|||
extern int fd_from_object(struct object *o); |
|||
static unsigned char roxen_php_initialized; |
|||
|
|||
#define REALTHIS ((php_roxen_request *)fp->current_storage) |
|||
#define GET_THIS() current_request = REALTHIS |
|||
#define THIS current_request |
|||
#define MY_FD ((struct object *)(THIS->my_fd)) |
|||
#define REQUEST_DATA ((struct mapping *)(THIS->request_data)) |
|||
|
|||
#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;\ |
|||
} 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) |
|||
|
|||
#ifndef MUCH_DEBUG |
|||
void no_fprintf(){} |
|||
#define fprintf no_fprintf |
|||
#endif |
|||
|
|||
/* php_roxen_context is per-server (thus only once at all) */ |
|||
|
|||
struct program *php_program; |
|||
|
|||
/* roxen_globals_struct is per-request */ |
|||
|
|||
typedef struct { |
|||
struct mapping *request_data; |
|||
struct object *my_fd; |
|||
char *filename; |
|||
} php_roxen_request; |
|||
|
|||
static php_roxen_request *current_request = NULL; |
|||
static int current_thread = -1; |
|||
|
|||
INLINE struct svalue *lookup_header(char *headername) |
|||
{ |
|||
struct svalue *headers, *value; |
|||
struct pike_string *sind; |
|||
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 char *lookup_string_header(char *headername, char *default_value) |
|||
{ |
|||
struct svalue *head; |
|||
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 int lookup_integer_header(char *headername, int default_value) |
|||
{ |
|||
struct svalue *head; |
|||
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. |
|||
*/ |
|||
|
|||
static int |
|||
php_roxen_low_ub_write(const char *str, uint str_length) { |
|||
int sent_bytes = 0; |
|||
struct pike_string *to_write; |
|||
to_write = make_shared_binary_string(str, str_length); |
|||
push_string(to_write); |
|||
safe_apply(MY_FD, "write", 1); |
|||
if(sp[-1].type == PIKE_T_INT) |
|||
sent_bytes = sp[-1].u.integer; |
|||
//free_string(to_write); |
|||
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"); |
|||
} |
|||
|
|||
/* |
|||
* 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; |
|||
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. |
|||
Set Header |
|||
*/ |
|||
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; |
|||
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; |
|||
char *p; |
|||
struct pike_string *hind; |
|||
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; |
|||
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); |
|||
fprintf(stderr, "Send Headers 1 (%d)...\n", SG(sapi_headers).http_response_code); |
|||
safe_apply(MY_FD, "send_headers", 2); |
|||
fprintf(stderr, "Send Headers 1 (%d)...\n", SG(sapi_headers).http_response_code); |
|||
pop_stack(); |
|||
fprintf(stderr, "Send Headers 2 (%d)...\n", SG(sapi_headers).http_response_code); |
|||
|
|||
/* |
|||
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; |
|||
} |
|||
|
|||
static int |
|||
php_roxen_sapi_send_headers(sapi_headers_struct *sapi_headers SLS_DC) |
|||
{ |
|||
THREAD_SAFE_RUN(php_roxen_low_send_headers(sapi_headers SLS_CC), "send headers"); |
|||
return SAPI_HEADER_SENT_SUCCESSFULLY; |
|||
} |
|||
|
|||
/* |
|||
* 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 max_read; |
|||
uint total_read = 0; |
|||
fprintf(stderr, "read post (%d bytes max)\n", count_bytes); |
|||
|
|||
push_int(count_bytes); |
|||
safe_apply(MY_FD, "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; |
|||
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) |
|||
{ |
|||
int i; |
|||
char *cookies; |
|||
cookies = lookup_string_header("HTTP_COOKIE", NULL); |
|||
return cookies; |
|||
} |
|||
|
|||
static void php_info_roxen(ZEND_MODULE_INFO_FUNC_ARGS) |
|||
{ |
|||
char buf[512]; |
|||
// int uptime = Ns_InfoUptime(); |
|||
|
|||
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>"); |
|||
} |
|||
|
|||
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; |
|||
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) { |
|||
char *p; |
|||
char c; |
|||
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 |
|||
*/ |
|||
|
|||
int php_roxen_module_main(SLS_D) |
|||
{ |
|||
zend_file_handle file_handle; |
|||
file_handle.type = ZEND_HANDLE_FILENAME; |
|||
file_handle.filename = THIS->filename; |
|||
if(php_request_startup(CLS_C ELS_CC PLS_CC SLS_CC) == FAILURE) { |
|||
return 0; |
|||
} |
|||
php_roxen_hash_environment(CLS_C ELS_CC PLS_CC SLS_CC); |
|||
THREADS_ALLOW(); |
|||
php_execute_script(&file_handle CLS_CC ELS_CC PLS_CC); |
|||
php_request_shutdown(NULL); |
|||
THREADS_DISALLOW(); |
|||
return 1; |
|||
} |
|||
|
|||
/* |
|||
* php_roxen_request_ctor() initializes the per-request data structure |
|||
* and fills it with data provided by the web server |
|||
*/ |
|||
|
|||
static void |
|||
php_roxen_request_ctor(SLS_D) |
|||
{ |
|||
char *server; |
|||
char *root; |
|||
int index; |
|||
char *tmp; |
|||
|
|||
SG(request_info).auth_user = NULL; |
|||
SG(request_info).auth_password = NULL; |
|||
/* |
|||
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_roxen_request_dtor() destroys all data associated with |
|||
* the per-request structure |
|||
*/ |
|||
|
|||
static void |
|||
php_roxen_request_dtor(SLS_D) |
|||
{ |
|||
// free(SG(request_info).path_translated); |
|||
} |
|||
|
|||
/* |
|||
* 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; |
|||
struct mapping *request_data; |
|||
struct svalue *done_callback; |
|||
struct pike_string *script; |
|||
int opened_fd = 1, status = 1; |
|||
int f = 0; |
|||
|
|||
if(current_thread == th_self()) |
|||
error("PHP4.Interpetor->run: Tried to run a PHP-script from a PHP " |
|||
"callback!"); |
|||
SLS_FETCH(); |
|||
get_all_args("PHP4.Interpretor->run", args, "%S%m%O%*", &script, |
|||
&request_data, &my_fd, &done_callback); |
|||
REALTHIS->request_data = request_data; |
|||
REALTHIS->my_fd = my_fd; |
|||
REALTHIS->filename = script->str; |
|||
if(done_callback->type != PIKE_T_FUNCTION) |
|||
error("PHP4.Interpretor->run: Bad argument 4, expected function.\n"); |
|||
PHP_LOCK(); |
|||
current_thread = th_self(); |
|||
GET_THIS(); |
|||
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; |
|||
status = php_roxen_module_main(SLS_C); |
|||
|
|||
php_roxen_request_dtor(SLS_C); |
|||
current_thread = -1; |
|||
PHP_UNLOCK(); |
|||
|
|||
apply_svalue(done_callback, 0); |
|||
pop_stack(); |
|||
pop_n_elems(args); |
|||
push_int(status); |
|||
|
|||
} |
|||
|
|||
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) { |
|||
sapi_startup(&sapi_module); |
|||
sapi_module.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); |
|||
|
|||
/* TSRM is used to allocate a per-thread structure */ |
|||
/* read the configuration */ |
|||
//php_roxen_config(ctx); |
|||
|
|||
} |
|||
|
|||
/* |
|||
* 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); |
|||
PHP_DESTROY(); |
|||
} |
|||
#endif |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue