/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2015 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.txt | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Alex Waugh | +----------------------------------------------------------------------+ */ #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.2" typedef struct { struct connection *conn; /*structure holding all the details of the current request*/ int bodyread; /*amount of POST body read*/ closefn oldclose; /*function to call to close the connection*/ } php_webjames_globals; static php_webjames_globals webjames_globals; #define WG(v) (webjames_globals.v) static int sapi_webjames_ub_write(const char *str, uint str_length TSRMLS_DC) /*unbuffered write - send data straight out to socket*/ { int totalbytes = 0; do { int bytes; bytes = webjames_writebuffer(WG(conn),str,str_length); if (bytes<0) { PG(connection_status) = PHP_CONNECTION_ABORTED; if (!PG(ignore_user_abort)) { zend_bailout(); } return bytes; } str += bytes; str_length -= bytes; totalbytes += bytes; } while (str_length); return totalbytes; } static void sapi_webjames_send_header(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC) /*send an HTTP header*/ { char *header = sapi_header->header; int len = sapi_header->header_len; if (WG(conn)->flags.outputheaders) { while (sapi_header && len > 0) { int bytes; bytes = webjames_writebuffer(WG(conn), header, len); if (bytes<0) { PG(connection_status) = PHP_CONNECTION_ABORTED; if (!PG(ignore_user_abort)) { zend_bailout(); } return; } header += bytes; len -= bytes; } webjames_writestring(WG(conn), "\r\n"); } } static int sapi_webjames_read_post(char *buffer, uint count_bytes TSRMLS_DC) /*read some of the post data*/ { if (WG(conn)->body==NULL) return 0; if (count_bytes+WG(bodyread)>WG(conn)->bodysize) count_bytes=WG(conn)->bodysize-WG(bodyread); memcpy(buffer, WG(conn)->body+WG(bodyread), count_bytes); WG(bodyread)+=count_bytes; return count_bytes; } static char *sapi_webjames_read_cookies(TSRMLS_D) { return WG(conn)->cookie; } #define BUF_SIZE 512 #define ADD_STRING(name,string)\ php_register_variable(name, string, track_vars_array TSRMLS_CC) #define ADD_NUM(name,field) {\ snprintf(buf, BUF_SIZE, "%d", WG(conn)->field);\ php_register_variable(name, buf, track_vars_array TSRMLS_CC);\ } #define ADD_FIELD(name, field) \ if (WG(conn)->field) { \ php_register_variable(name, WG(conn)->field, track_vars_array TSRMLS_CC); \ } static void sapi_webjames_register_variables(zval *track_vars_array TSRMLS_DC) { char buf[BUF_SIZE + 1]; char *docroot; buf[BUF_SIZE] = '\0'; ADD_STRING("SERVER_SOFTWARE", configuration.server); ADD_STRING("SERVER_NAME", configuration.serverip); ADD_FIELD("SERVER_PROTOCOL", protocol); ADD_NUM("SERVER_PORT", port); ADD_STRING("SERVER_ADMIN",configuration.webmaster); ADD_STRING("GATEWAY_INTERFACE", "CGI/1.1"); docroot = __unixify(WG(conn)->homedir,0,NULL,1024,0); if (docroot) ADD_STRING("DOCUMENT_ROOT", docroot); ADD_FIELD("REQUEST_METHOD", methodstr); ADD_FIELD("REQUEST_URI", requesturi); ADD_STRING("PATH_TRANSLATED", SG(request_info).path_translated); ADD_FIELD("SCRIPT_NAME", uri); ADD_FIELD("PHP_SELF", uri); ADD_FIELD("QUERY_STRING", args); snprintf(buf, BUF_SIZE, "%d.%d.%d.%d", WG(conn)->ipaddr[0], WG(conn)->ipaddr[1], WG(conn)->ipaddr[2], WG(conn)->ipaddr[3]); ADD_STRING("REMOTE_ADDR", buf); if (WG(conn)->dnsstatus == DNS_OK) ADD_FIELD("REMOTE_HOST", host); if ((WG(conn)->method == METHOD_POST) || (WG(conn)->method == METHOD_PUT)) { ADD_NUM("CONTENT_LENGTH", bodysize); ADD_FIELD("CONTENT_TYPE", type); } if ((WG(conn)->method == METHOD_PUT) || (WG(conn)->method == METHOD_DELETE)) ADD_FIELD("ENTITY_PATH", requesturi); if (WG(conn)->pwd) { ADD_STRING("AUTH_TYPE", "basic"); ADD_FIELD("REMOTE_USER", authorization); } ADD_FIELD("HTTP_COOKIE", cookie); ADD_FIELD("HTTP_USER_AGENT", useragent); ADD_FIELD("HTTP_REFERER", referer); ADD_FIELD("HTTP_ACCEPT", accept); ADD_FIELD("HTTP_ACCEPT_LANGUAGE", acceptlanguage); ADD_FIELD("HTTP_ACCEPT_CHARSET", acceptcharset); ADD_FIELD("HTTP_ACCEPT_ENCODING", acceptencoding); } static void webjames_module_main(TSRMLS_D) { zend_file_handle file_handle; FILE *fp=NULL; char *path; /* Convert filename to Unix format*/ __riscosify_control|=__RISCOSIFY_STRICT_UNIX_SPECS; path = __unixify(WG(conn)->filename,0,NULL,1024,0); if (path) SG(request_info).path_translated = estrdup(path); SG(request_info).query_string = WG(conn)->args; SG(request_info).request_uri = WG(conn)->requesturi; SG(request_info).request_method = WG(conn)->methodstr; if (WG(conn)->method==METHOD_HEAD) { SG(request_info).headers_only = 1; } else { SG(request_info).headers_only = 0; } SG(sapi_headers).http_response_code = 200; SG(request_info).content_type = WG(conn)->type; SG(request_info).content_length = WG(conn)->bodysize; SG(request_info).auth_user = NULL; SG(request_info).auth_password = NULL; if (WG(conn)->authorization) { char *colon=strchr(WG(conn)->authorization,':'); if (colon) { SG(request_info).auth_user = emalloc(colon-WG(conn)->authorization+1); if (SG(request_info).auth_user) { memcpy(SG(request_info).auth_user,WG(conn)->authorization,colon-WG(conn)->authorization); SG(request_info).auth_user[colon-WG(conn)->authorization]='\0'; SG(request_info).auth_password = estrdup(colon+1); } } } /*ensure that syslog calls get logged separately from WebJames' main log */ openlog("PHP",0,0); file_handle.type = ZEND_HANDLE_FILENAME; file_handle.filename = SG(request_info).path_translated; file_handle.free_filename = 0; file_handle.opened_path = NULL; if (php_request_startup(TSRMLS_C) == FAILURE) { return; } php_execute_script(&file_handle TSRMLS_CC); php_request_shutdown(NULL); } static void webjames_php_close(struct connection *conn, int force) /*called by webjames if it wants to close the connection*/ { TSRMLS_FETCH(); php_request_shutdown(NULL); WG(oldclose)(conn,force); } void webjames_php_request(struct connection *conn) /*called by WebJames to start handler*/ { TSRMLS_FETCH(); WG(conn) = conn; WG(bodyread) = 0; WG(oldclose) = conn->close; conn->close=webjames_php_close; webjames_module_main(TSRMLS_C); WG(oldclose)(WG(conn), 0); } static void php_info_webjames(ZEND_MODULE_INFO_FUNC_ARGS) { php_info_print_table_start(); php_info_print_table_row(2, "SAPI module version", WEBJAMES_SAPI_VERSION); php_info_print_table_row(2, "WebJames version", WEBJAMES_VERSION " (" WEBJAMES_DATE ")"); php_info_print_table_end(); } static zend_module_entry php_webjames_module = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif "WebJames", NULL, NULL, NULL, NULL, NULL, php_info_webjames, #if ZEND_MODULE_API_NO >= 20010901 WEBJAMES_SAPI_VERSION, #endif STANDARD_MODULE_PROPERTIES }; static int php_webjames_startup(sapi_module_struct *sapi_module) { if(php_module_startup(sapi_module, &php_webjames_module, 1) == FAILURE) { return FAILURE; } else { return SUCCESS; } } static sapi_module_struct sapi_module = { "webjames", /* name */ "WebJames", /* pretty name */ php_webjames_startup, /* startup */ php_module_shutdown_wrapper, /* shutdown */ NULL, /* activate */ NULL, /* deactivate */ sapi_webjames_ub_write, /* unbuffered write */ NULL, /* flush */ NULL, /* get uid */ NULL, /* getenv */ php_error, /* error handler */ NULL, /* header handler */ NULL, /* send headers handler */ sapi_webjames_send_header, /* send header handler */ sapi_webjames_read_post, /* read POST data */ sapi_webjames_read_cookies, /* read Cookies */ sapi_webjames_register_variables, /* register server variables */ NULL, /* Log message */ NULL, /* Get request time */ NULL, /* Child terminate */ STANDARD_SAPI_MODULE_PROPERTIES }; int webjames_php_init(void) /*called when WebJames initialises*/ { TSRMLS_FETCH(); if (strcmp(configuration.webjames_h_revision,WEBJAMES_H_REVISION)!=0) { /*This file was compiled against a different revision of webjames.h than webjames was, which could be bad news*/ webjames_writelog(0,"PHP module is compiled for WebJames (%s) and was linked with a different version (%s)",WEBJAMES_H_REVISION,configuration.webjames_h_revision); return 0; /*failed to initialise*/ } sapi_startup(&sapi_module); sapi_module.startup(&sapi_module); SG(server_context) = (void *) 1; return 1; /*initialised correctly*/ } void webjames_php_shutdown(void) /*called when WebJames is about to quit*/ { sapi_module.shutdown(&sapi_module); sapi_shutdown(); }