From e06c1d7c7ea8ef8608fc28ad92624f6081dea0e9 Mon Sep 17 00:00:00 2001 From: Alex Waugh Date: Mon, 5 Nov 2001 12:07:49 +0000 Subject: [PATCH] New SAPI module for the WebJames server on RISC OS @- New SAPI module for the WebJames server on RISC OS (Alex Waugh) --- EXTENSIONS | 5 + sapi/webjames/CREDITS | 2 + sapi/webjames/Makefile.in | 5 + sapi/webjames/README | 32 ++++ sapi/webjames/config.m4 | 20 +++ sapi/webjames/php_webjames.h | 28 +++ sapi/webjames/webjames.c | 339 +++++++++++++++++++++++++++++++++++ 7 files changed, 431 insertions(+) create mode 100644 sapi/webjames/CREDITS create mode 100644 sapi/webjames/Makefile.in create mode 100644 sapi/webjames/README create mode 100644 sapi/webjames/config.m4 create mode 100644 sapi/webjames/php_webjames.h create mode 100644 sapi/webjames/webjames.c diff --git a/EXTENSIONS b/EXTENSIONS index a88a87bf3a561..8cdd44b18528d 100644 --- a/EXTENSIONS +++ b/EXTENSIONS @@ -73,6 +73,11 @@ EXTENSION: thttpd MAINTENANCE: Unknown STATUS: Unknown ------------------------------------------------------------------------------- +EXTENSION: webjames +PRIMARY MAINTAINER: Alex Waugh +MAINTENANCE: Maintained +STATUS: Experimental +------------------------------------------------------------------------------- == Database extensions == diff --git a/sapi/webjames/CREDITS b/sapi/webjames/CREDITS new file mode 100644 index 0000000000000..73a7983e9250a --- /dev/null +++ b/sapi/webjames/CREDITS @@ -0,0 +1,2 @@ +WebJames +Alex Waugh diff --git a/sapi/webjames/Makefile.in b/sapi/webjames/Makefile.in new file mode 100644 index 0000000000000..b0dc7f1162dcd --- /dev/null +++ b/sapi/webjames/Makefile.in @@ -0,0 +1,5 @@ + +LTLIBRARY_NAME = libsapi.la +LTLIBRARY_SOURCES = webjames.c + +include $(top_srcdir)/build/ltlib.mk diff --git a/sapi/webjames/README b/sapi/webjames/README new file mode 100644 index 0000000000000..10625a179e7cb --- /dev/null +++ b/sapi/webjames/README @@ -0,0 +1,32 @@ +README for WebJames SAPI module +by Alex Waugh + +This is a SAPI module for the WebJames HTTP server, which runs on the +RISC OS operating system. + + +DOWNLOADS + +A recent (September 2001 or later) version of the GCCSDK cross compiler +http://www.hard-mofo.dsvr.net/ + +WebJames 0.31 or later +http://www.webjames.alexwaugh.com/ + + +BUILDING + +$ cd webjames + +Edit Makefile if nessacery + +$ make setup +$ cd ../php4 +$ ./configure \ + --host=arm-riscos-aof \ + --with-webjames=../webjames \ + --with-config-file-path=/Choices: \ + other PHP options +$ make install +$ cd ../webjames +$ make diff --git a/sapi/webjames/config.m4 b/sapi/webjames/config.m4 new file mode 100644 index 0000000000000..1c8750ad0fda3 --- /dev/null +++ b/sapi/webjames/config.m4 @@ -0,0 +1,20 @@ +AC_ARG_WITH(webjames, +[ --with-webjames=SRCDIR Build PHP as a WebJames module (RISC OS only)],[ + PHP_EXPAND_PATH($withval, WEBJAMES) + INSTALL_IT="\ + echo '\\#Created by PHP configure' > $WEBJAMES/build/php; \ + echo 'PHP_LIBS = -l$abs_srcdir/$SAPI_STATIC \$(PHP_LIBS) \$(EXTRA_LIBS)' >> $WEBJAMES/build/php; \ + echo 'PHP_LDFLAGS = \$(NATIVE_RPATHS) \$(PHP_LDFLAGS)' >> $WEBJAMES/build/php; \ + echo 'PHP_CFLAGS = -DPHP \$(COMMON_FLAGS) \$(CFLAGS) \$(EXTRA_CFLAGS) -I$abs_srcdir/sapi/webjames' >> $WEBJAMES/build/php; \ + echo 'WIMPSLOT = \$\$(WIMPSLOT_PHP)' >> $WEBJAMES/build/php; \ + echo 'REMOVE_ATTRIBUTE=Action php-script.*' >> $WEBJAMES/build/php;" + PHP_WEBJAMES="yes, using $WEBJAMES" + PHP_ADD_INCLUDE($WEBJAMES) + PHP_BUILD_STATIC + PHP_SAPI=webjames +],[ + PHP_WEBJAMES="no" +]) + +AC_MSG_CHECKING(for webjames) +AC_MSG_RESULT($PHP_WEBJAMES) diff --git a/sapi/webjames/php_webjames.h b/sapi/webjames/php_webjames.h new file mode 100644 index 0000000000000..c8bef429772dc --- /dev/null +++ b/sapi/webjames/php_webjames.h @@ -0,0 +1,28 @@ +/* + +----------------------------------------------------------------------+ + | PHP version 4.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Alex Waugh | + +----------------------------------------------------------------------+ +*/ + +#ifndef PHP_WEBJAMES_H +#define PHP_WEBJAMES_H + +#include "webjames.h" + +void webjames_php_shutdown(void); +int webjames_php_init(void); +void webjames_php_request(struct connection *conn); + +#endif diff --git a/sapi/webjames/webjames.c b/sapi/webjames/webjames.c new file mode 100644 index 0000000000000..41a5c824b6679 --- /dev/null +++ b/sapi/webjames/webjames.c @@ -0,0 +1,339 @@ +/* + +----------------------------------------------------------------------+ + | PHP version 4.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Alex Waugh | + +----------------------------------------------------------------------+ +*/ + + +#include "php.h" +#include "SAPI.h" +#include "php_main.h" +#include "php_variables.h" + +#define WEBJAMES_PHP_ONLY +#include "php_webjames.h" + +#include + +#define WEBJAMES_SAPI_VERSION "1.0.0" + +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 WLS_D +#define WLS_DC +#define WLS_C +#define WLS_CC +#define WG(v) (webjames_globals.v) +#define WLS_FETCH() + +static int sapi_webjames_ub_write(const char *str, uint str_length) +/*unbuffered write - send data straight out to socket*/ +{ + int bytes; + WLS_FETCH(); + + 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; +} + +static int sapi_webjames_send_headers(sapi_headers_struct *sapi_headers SLS_DC) +/*send the HTTP response line*/ +{ + char buf[256]; + WLS_FETCH(); + + if (WG(conn)->flags.outputheaders) { + if (!SG(sapi_headers).http_status_line) { + int code=SG(sapi_headers).http_response_code; + snprintf(buf, 255, "HTTP/1.0 %d %s\r\n", code, code==200 ? "OK" : code==302 ? "Moved temporarily" : "Something"); + webjames_writestring(WG(conn), buf); + } + } + + return SAPI_HEADER_DO_SEND; +} + +static void sapi_webjames_send_header(sapi_header_struct *sapi_header, void *server_context) +/*send an HTTP header*/ +{ + WLS_FETCH(); + + if (WG(conn)->flags.outputheaders) { + if (sapi_header) + webjames_writebuffer(WG(conn), sapi_header->header, sapi_header->header_len); + webjames_writestring(WG(conn), "\r\n"); + } +} + +static int sapi_webjames_read_post(char *buffer, uint count_bytes SLS_DC) +/*read some of the post data*/ +{ + WLS_FETCH(); + + 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(SLS_D) +{ + WLS_FETCH(); + + return WG(conn)->cookie; +} + +#define BUF_SIZE 512 +#define ADD_STRING(name,string)\ + php_register_variable(name, string, track_vars_array ELS_CC PLS_CC) + +#define ADD_NUM(name,field) {\ + snprintf(buf, BUF_SIZE, "%d", WG(conn)->field);\ + php_register_variable(name, buf, track_vars_array ELS_CC PLS_CC);\ +} + +#define ADD_FIELD(name, field) \ + if (WG(conn)->field) { \ + php_register_variable(name, WG(conn)->field, track_vars_array ELS_CC PLS_C); \ + } + +static void sapi_webjames_register_variables(zval *track_vars_array ELS_DC SLS_DC PLS_DC) +{ + char buf[BUF_SIZE + 1]; + WLS_FETCH(); + + 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"); + ADD_STRING("DOCUMENT_ROOT", configuration.site); + + 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(WLS_D SLS_DC) +{ + zend_file_handle file_handle; + FILE *fp=NULL; + char *path; + CLS_FETCH(); + ELS_FETCH(); + PLS_FETCH(); + + /* Convert filename to Unix format*/ + __riscosify_control|=__RISCOSIFY_DONT_CHECK_DIR; + 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 separatly 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(CLS_C ELS_CC PLS_CC SLS_CC) == FAILURE) { + return; + } + + php_execute_script(&file_handle CLS_CC ELS_CC PLS_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*/ +{ + php_request_shutdown(NULL); + WG(oldclose)(conn,force); +} + +void webjames_php_request(struct connection *conn) +/*called by WebJames to start handler*/ +{ + SLS_FETCH(); + WLS_FETCH(); + + WG(conn) = conn; + WG(bodyread) = 0; + WG(oldclose) = conn->close; + conn->close=webjames_php_close; + + webjames_module_main(WLS_C SLS_CC); + + 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) == FAILURE + || zend_startup_module(&php_webjames_module) == 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 */ + sapi_webjames_send_headers, /* 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, /* Block interruptions */ + NULL, /* Unblock interruptions */ + + STANDARD_SAPI_MODULE_PROPERTIES +}; + +int webjames_php_init(void) +/*called when WebJames initialises*/ +{ + 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(); +}