Back to index

php5  5.3.10
webjames.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Author: Alex Waugh <alex@alexwaugh.com>                              |
00016    +----------------------------------------------------------------------+
00017 */
00018 
00019 
00020 #include "php.h"
00021 #include "SAPI.h"
00022 #include "php_main.h"
00023 #include "php_variables.h"
00024 
00025 #define WEBJAMES_PHP_ONLY
00026 #include "php_webjames.h"
00027 
00028 #include <unixlib/local.h>
00029 
00030 #define WEBJAMES_SAPI_VERSION "1.0.2"
00031 
00032 typedef struct {
00033        struct connection *conn; /*structure holding all the details of the current request*/
00034        int bodyread; /*amount of POST body read*/
00035        closefn oldclose; /*function to call to close the connection*/
00036 } php_webjames_globals;
00037 
00038 static php_webjames_globals webjames_globals;
00039 
00040 #define WG(v) (webjames_globals.v)
00041 
00042 static int sapi_webjames_ub_write(const char *str, uint str_length TSRMLS_DC)
00043 /*unbuffered write - send data straight out to socket*/
00044 {
00045        int totalbytes = 0;
00046 
00047        do {
00048               int bytes;
00049               bytes = webjames_writebuffer(WG(conn),str,str_length);
00050               if (bytes<0) {
00051                      PG(connection_status) = PHP_CONNECTION_ABORTED;
00052                      if (!PG(ignore_user_abort)) {
00053                             zend_bailout();
00054                      }
00055                      return bytes;
00056               }
00057               str += bytes;
00058               str_length -= bytes;
00059               totalbytes += bytes;
00060        } while (str_length);
00061        return totalbytes;
00062 }
00063 
00064 static void sapi_webjames_send_header(sapi_header_struct *sapi_header, void *server_context TSRMLS_DC)
00065 /*send an HTTP header*/
00066 {
00067        char *header = sapi_header->header;
00068        int len = sapi_header->header_len;
00069        if (WG(conn)->flags.outputheaders) {
00070               while (sapi_header && len > 0) {
00071                      int bytes;
00072                      bytes = webjames_writebuffer(WG(conn), header, len);
00073                      if (bytes<0) {
00074                             PG(connection_status) = PHP_CONNECTION_ABORTED;
00075                             if (!PG(ignore_user_abort)) {
00076                                    zend_bailout();
00077                             }
00078                             return;
00079                      }
00080                      header += bytes;
00081                      len -= bytes;
00082               }
00083               webjames_writestring(WG(conn), "\r\n");
00084        }
00085 }
00086 
00087 static int sapi_webjames_read_post(char *buffer, uint count_bytes TSRMLS_DC)
00088 /*read some of the post data*/
00089 {
00090        if (WG(conn)->body==NULL) return 0;
00091        if (count_bytes+WG(bodyread)>WG(conn)->bodysize) count_bytes=WG(conn)->bodysize-WG(bodyread);
00092        memcpy(buffer, WG(conn)->body+WG(bodyread), count_bytes);
00093        WG(bodyread)+=count_bytes;
00094        return count_bytes;
00095 }
00096 
00097 static char *sapi_webjames_read_cookies(TSRMLS_D)
00098 {
00099        return WG(conn)->cookie;
00100 }
00101 
00102 #define BUF_SIZE 512
00103 #define ADD_STRING(name,string)\
00104        php_register_variable(name, string, track_vars_array TSRMLS_CC)
00105 
00106 #define ADD_NUM(name,field) {\
00107        snprintf(buf, BUF_SIZE, "%d", WG(conn)->field);\
00108        php_register_variable(name, buf, track_vars_array TSRMLS_CC);\
00109 }
00110 
00111 #define ADD_FIELD(name, field) \
00112        if (WG(conn)->field) { \
00113               php_register_variable(name, WG(conn)->field, track_vars_array TSRMLS_CC); \
00114        }
00115 
00116 static void sapi_webjames_register_variables(zval *track_vars_array TSRMLS_DC)
00117 {
00118        char buf[BUF_SIZE + 1];
00119        char *docroot;
00120 
00121        buf[BUF_SIZE] = '\0';
00122 
00123        ADD_STRING("SERVER_SOFTWARE", configuration.server);
00124        ADD_STRING("SERVER_NAME", configuration.serverip);
00125        ADD_FIELD("SERVER_PROTOCOL", protocol);
00126        ADD_NUM("SERVER_PORT", port);
00127        ADD_STRING("SERVER_ADMIN",configuration.webmaster);
00128        ADD_STRING("GATEWAY_INTERFACE", "CGI/1.1");
00129 
00130        docroot = __unixify(WG(conn)->homedir,0,NULL,1024,0);
00131        if (docroot) ADD_STRING("DOCUMENT_ROOT", docroot);
00132 
00133        ADD_FIELD("REQUEST_METHOD", methodstr);
00134        ADD_FIELD("REQUEST_URI", requesturi);
00135        ADD_STRING("PATH_TRANSLATED", SG(request_info).path_translated);
00136        ADD_FIELD("SCRIPT_NAME", uri);
00137        ADD_FIELD("PHP_SELF", uri);
00138        ADD_FIELD("QUERY_STRING", args);
00139 
00140        
00141        snprintf(buf, BUF_SIZE, "%d.%d.%d.%d", WG(conn)->ipaddr[0], WG(conn)->ipaddr[1], WG(conn)->ipaddr[2], WG(conn)->ipaddr[3]);
00142        ADD_STRING("REMOTE_ADDR", buf);
00143        if (WG(conn)->dnsstatus == DNS_OK) ADD_FIELD("REMOTE_HOST", host);
00144 
00145        if ((WG(conn)->method == METHOD_POST) || (WG(conn)->method == METHOD_PUT)) {
00146               ADD_NUM("CONTENT_LENGTH", bodysize);
00147               ADD_FIELD("CONTENT_TYPE", type);
00148        }
00149 
00150        if ((WG(conn)->method == METHOD_PUT) || (WG(conn)->method == METHOD_DELETE)) ADD_FIELD("ENTITY_PATH", requesturi);
00151 
00152        if (WG(conn)->pwd) {
00153               ADD_STRING("AUTH_TYPE", "basic");
00154               ADD_FIELD("REMOTE_USER", authorization);
00155        }
00156 
00157        ADD_FIELD("HTTP_COOKIE", cookie);
00158        ADD_FIELD("HTTP_USER_AGENT", useragent);
00159        ADD_FIELD("HTTP_REFERER", referer);
00160        ADD_FIELD("HTTP_ACCEPT", accept);
00161        ADD_FIELD("HTTP_ACCEPT_LANGUAGE", acceptlanguage);
00162        ADD_FIELD("HTTP_ACCEPT_CHARSET", acceptcharset);
00163        ADD_FIELD("HTTP_ACCEPT_ENCODING", acceptencoding);
00164 }
00165 
00166 static void webjames_module_main(TSRMLS_D)
00167 {
00168        zend_file_handle file_handle;
00169        FILE *fp=NULL;
00170        char *path;
00171 
00172        /* Convert filename to Unix format*/
00173        __riscosify_control|=__RISCOSIFY_STRICT_UNIX_SPECS;
00174        path = __unixify(WG(conn)->filename,0,NULL,1024,0);
00175        if (path) SG(request_info).path_translated = estrdup(path);
00176 
00177        SG(request_info).query_string = WG(conn)->args;
00178        SG(request_info).request_uri = WG(conn)->requesturi;
00179        SG(request_info).request_method = WG(conn)->methodstr;
00180        if (WG(conn)->method==METHOD_HEAD) {
00181               SG(request_info).headers_only = 1;
00182        } else {
00183               SG(request_info).headers_only = 0;
00184        }
00185        SG(sapi_headers).http_response_code = 200;
00186        SG(request_info).content_type = WG(conn)->type;
00187        SG(request_info).content_length = WG(conn)->bodysize;
00188 
00189        SG(request_info).auth_user = NULL;
00190        SG(request_info).auth_password = NULL;
00191        if (WG(conn)->authorization) {
00192               char *colon=strchr(WG(conn)->authorization,':');
00193               if (colon) {
00194                      SG(request_info).auth_user = emalloc(colon-WG(conn)->authorization+1);
00195                      if (SG(request_info).auth_user) {
00196                             memcpy(SG(request_info).auth_user,WG(conn)->authorization,colon-WG(conn)->authorization);
00197                             SG(request_info).auth_user[colon-WG(conn)->authorization]='\0';
00198                             SG(request_info).auth_password = estrdup(colon+1);
00199                      }
00200               }
00201        }
00202 
00203        /*ensure that syslog calls get logged separately from WebJames' main log */
00204        openlog("PHP",0,0);
00205 
00206        file_handle.type = ZEND_HANDLE_FILENAME;
00207        file_handle.filename = SG(request_info).path_translated;
00208        file_handle.free_filename = 0;
00209        file_handle.opened_path = NULL;
00210 
00211        if (php_request_startup(TSRMLS_C) == FAILURE) {
00212               return;
00213        }
00214        
00215        php_execute_script(&file_handle TSRMLS_CC);
00216        php_request_shutdown(NULL);
00217 }
00218 
00219 static void webjames_php_close(struct connection *conn, int force)
00220 /*called by webjames if it wants to close the connection*/
00221 {
00222        TSRMLS_FETCH();
00223 
00224        php_request_shutdown(NULL);
00225        WG(oldclose)(conn,force);
00226 }
00227 
00228 void webjames_php_request(struct connection *conn)
00229 /*called by WebJames to start handler*/
00230 {
00231        TSRMLS_FETCH();
00232 
00233        WG(conn) = conn;
00234        WG(bodyread) = 0;
00235        WG(oldclose) = conn->close;
00236        conn->close=webjames_php_close;
00237 
00238        webjames_module_main(TSRMLS_C);
00239 
00240        WG(oldclose)(WG(conn), 0);
00241 }
00242 
00243 static void php_info_webjames(ZEND_MODULE_INFO_FUNC_ARGS)
00244 {
00245        php_info_print_table_start();
00246        php_info_print_table_row(2, "SAPI module version", WEBJAMES_SAPI_VERSION);
00247        php_info_print_table_row(2, "WebJames version", WEBJAMES_VERSION " (" WEBJAMES_DATE ")");
00248        php_info_print_table_end();
00249 }
00250 
00251 static zend_module_entry php_webjames_module = {
00252 #if ZEND_MODULE_API_NO >= 20010901
00253     STANDARD_MODULE_HEADER,
00254 #endif
00255   "WebJames",
00256   NULL,
00257   NULL,
00258   NULL,
00259   NULL,
00260   NULL,
00261   php_info_webjames,
00262 #if ZEND_MODULE_API_NO >= 20010901
00263   WEBJAMES_SAPI_VERSION,          
00264 #endif
00265   STANDARD_MODULE_PROPERTIES
00266 };
00267 
00268 
00269 static int php_webjames_startup(sapi_module_struct *sapi_module)
00270 {
00271   if(php_module_startup(sapi_module, &php_webjames_module, 1) == FAILURE) {
00272     return FAILURE;
00273   } else {
00274     return SUCCESS;
00275   }
00276 }
00277 
00278 static sapi_module_struct sapi_module = {
00279        "webjames",                             /* name */
00280        "WebJames",                             /* pretty name */
00281 
00282        php_webjames_startup,                   /* startup */
00283        php_module_shutdown_wrapper,            /* shutdown */
00284 
00285        NULL,                                                          /* activate */
00286        NULL,                                                          /* deactivate */
00287 
00288        sapi_webjames_ub_write,                 /* unbuffered write */
00289        NULL,                                   /* flush */
00290        NULL,                                                          /* get uid */
00291        NULL,                                                          /* getenv */
00292 
00293        php_error,                              /* error handler */
00294 
00295        NULL,                                   /* header handler */
00296        NULL,                                                   /* send headers handler */
00297        sapi_webjames_send_header,              /* send header handler */
00298        sapi_webjames_read_post,                /* read POST data */
00299        sapi_webjames_read_cookies,             /* read Cookies */
00300 
00301        sapi_webjames_register_variables,       /* register server variables */
00302        NULL,                                                          /* Log message */
00303        NULL,                                                          /* Get request time */
00304        NULL,                                                          /* Child terminate */
00305 
00306        STANDARD_SAPI_MODULE_PROPERTIES
00307 };
00308 
00309 int webjames_php_init(void)
00310 /*called when WebJames initialises*/
00311 {
00312        TSRMLS_FETCH();
00313        if (strcmp(configuration.webjames_h_revision,WEBJAMES_H_REVISION)!=0) {
00314               /*This file was compiled against a different revision of
00315                 webjames.h than webjames was, which could be bad news*/
00316               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);
00317               return 0; /*failed to initialise*/
00318        }
00319        sapi_startup(&sapi_module);
00320        sapi_module.startup(&sapi_module);
00321        SG(server_context) = (void *) 1;
00322        return 1; /*initialised correctly*/
00323 }
00324 
00325 void webjames_php_shutdown(void)
00326 /*called when WebJames is about to quit*/
00327 {
00328        sapi_module.shutdown(&sapi_module);
00329        sapi_shutdown();
00330 }