root/sapi/caudium/caudium.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lookup_header
  2. lookup_string_header
  3. lookup_integer_header
  4. php_caudium_low_ub_write
  5. php_caudium_sapi_ub_write
  6. php_caudium_set_header
  7. php_caudium_sapi_header_handler
  8. php_caudium_low_send_headers
  9. php_caudium_sapi_send_headers
  10. php_caudium_low_read_post
  11. php_caudium_sapi_read_post
  12. php_caudium_sapi_read_cookies
  13. php_info_caudium
  14. low_sapi_caudium_register_variables
  15. sapi_caudium_register_variables
  16. php_caudium_startup
  17. php_caudium_module_main
  18. f_php_caudium_request_handler
  19. free_struct
  20. pike_module_init
  21. pike_module_exit

   1 /* 
   2    +----------------------------------------------------------------------+
   3    | PHP Version 5                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Author: David Hedbor <neotron@php.net>                               |
  16    | Based on aolserver SAPI by Sascha Schumann <sascha@schumann.cx>      |
  17    +----------------------------------------------------------------------+
  18  */
  19 
  20 /* $Id$ */
  21 
  22 #include "php.h"
  23 #ifdef HAVE_CAUDIUM
  24 
  25 #include "php_ini.h"
  26 #include "php_globals.h"
  27 #include "SAPI.h"
  28 #include "php_main.h" 
  29 #include "ext/standard/info.h"
  30 
  31 #include "php_version.h"
  32 
  33 /* Pike Include Files 
  34  *
  35  * conflicts with pike avoided by only using long names. Requires a new
  36  * Pike 0.7 since it was implemented for this interface only.
  37  *
  38  */
  39 #define NO_PIKE_SHORTHAND
  40 
  41 /* Ok, we are now using Pike level threads to handle PHP5 since
  42  * the nice th_farm threads aren't working on Linux with glibc 2.2
  43  * (why this is I don't know).
  44  */
  45 #define USE_PIKE_LEVEL_THREADS
  46 
  47 #include <fdlib.h>
  48 #include <program.h>
  49 #include <pike_types.h>
  50 #include <interpret.h>
  51 #include <module_support.h>
  52 #include <array.h>
  53 #include <backend.h>
  54 #include <stralloc.h>
  55 #include <mapping.h>
  56 #include <object.h>
  57 #include <threads.h>
  58 #include <builtin_functions.h>
  59 #include <operators.h>
  60 #include <version.h>
  61 
  62 #if (PIKE_MAJOR_VERSION == 7 && PIKE_MINOR_VERSION == 1 && PIKE_BUILD_VERSION >= 12) || PIKE_MAJOR_VERSION > 7 || (PIKE_MAJOR_VERSION == 7 && PIKE_MINOR_VERSION > 1)
  63 # include "pike_error.h"
  64 #else
  65 # include "error.h"
  66 # ifndef Pike_error
  67 #  define Pike_error error
  68 # endif
  69 #endif
  70 
  71 /* Pike 7.x and newer */
  72 #define MY_MAPPING_LOOP(md, COUNT, KEY) \
  73   for(COUNT=0;COUNT < md->data->hashsize; COUNT++ ) \
  74         for(KEY=md->data->hash[COUNT];KEY;KEY=KEY->next)
  75 
  76 #ifndef ZTS
  77 /* Need thread safety */
  78 #error You need to compile PHP with threads.
  79 #endif
  80 
  81 #ifndef PIKE_THREADS
  82 #error The PHP5 module requires that your Pike has thread support.
  83 #endif
  84 
  85 #undef HIDE_GLOBAL_VARIABLES
  86 #undef REVEAL_GLOBAL_VARIABLES
  87 #define HIDE_GLOBAL_VARIABLES()
  88 #define REVEAL_GLOBAL_VARIABLES()
  89 
  90 /* php_caudium_request is per-request object storage */
  91 
  92 typedef struct
  93 {
  94   struct mapping *request_data;
  95   struct object *my_fd_obj;
  96   struct svalue done_cb;
  97   struct pike_string *filename;
  98   int my_fd;
  99   int written;
 100   TSRMLS_D;
 101 } php_caudium_request;
 102 
 103 
 104 void pike_module_init(void);
 105 void pike_module_exit(void);
 106 static void free_struct(TSRMLS_D);
 107 void f_php_caudium_request_handler(INT32 args);
 108 
 109 /* Defines to get to the data supplied when the script is started. */
 110 
 111 /* Per thread storage area id... */
 112 static int caudium_globals_id;
 113 
 114 #define GET_THIS() php_caudium_request *_request = ts_resource(caudium_globals_id)
 115 #define THIS _request
 116 #define PTHIS ((php_caudium_request *)(Pike_fp->current_storage))
 117 /* File descriptor integer. Used to write directly to the FD without 
 118  * passing Pike
 119  */
 120 #define MY_FD    (THIS->my_fd)
 121 
 122 /* FD object. Really a PHPScript object from Pike which implements a couple
 123  * of functions to handle headers, writing and buffering.
 124  */
 125 #define MY_FD_OBJ        ((struct object *)(THIS->my_fd_obj))
 126 
 127 /* Mapping with data supplied from the calling Caudium module. Contains
 128  * a mapping with headers, an FD object etc.
 129  */
 130 #define REQUEST_DATA ((struct mapping *)(THIS->request_data))
 131 
 132 extern int fd_from_object(struct object *o);
 133 static unsigned char caudium_php_initialized;
 134 
 135 #ifndef mt_lock_interpreter
 136 #define mt_lock_interpreter()     mt_lock(&interpreter_lock);
 137 #define mt_unlock_interpreter()   mt_unlock(&interpreter_lock);
 138 #endif
 139 
 140 
 141 /* This allows calling of pike functions from the PHP callbacks,
 142  * which requires the Pike interpreter to be locked.
 143  */
 144 #define THREAD_SAFE_RUN(COMMAND, what)  do {\
 145   struct thread_state *state;\
 146   if((state = thread_state_for_id(th_self()))!=NULL) {\
 147     if(!state->swapped) {\
 148       COMMAND;\
 149     } else {\
 150       mt_lock_interpreter();\
 151       SWAP_IN_THREAD(state);\
 152       COMMAND;\
 153       SWAP_OUT_THREAD(state);\
 154       mt_unlock_interpreter();\
 155     }\
 156   }\
 157 } while(0)
 158 
 159 
 160 
 161 /* Low level header lookup. Basically looks for the named header in the mapping
 162  * headers in the supplied options mapping.
 163  */
 164  
 165 INLINE static struct svalue *lookup_header(char *headername)
 166 {
 167   struct svalue *headers, *value;
 168   struct pike_string *sind;
 169   GET_THIS();
 170   sind = make_shared_string("env");
 171   headers = low_mapping_string_lookup(REQUEST_DATA, sind);
 172   free_string(sind);
 173   if(!headers || headers->type != PIKE_T_MAPPING) return NULL;
 174   sind = make_shared_string(headername);
 175   value = low_mapping_string_lookup(headers->u.mapping, sind);
 176   free_string(sind);
 177   if(!value) return NULL;
 178   return value;
 179 }
 180 
 181 /* Lookup a header in the mapping and return the value as a string, or
 182  * return the default if it's missing
 183  */
 184 INLINE static char *lookup_string_header(char *headername, char *default_value)
 185 {
 186   struct svalue *head = NULL;
 187   THREAD_SAFE_RUN(head = lookup_header(headername), "header lookup");
 188   if(!head || head->type != PIKE_T_STRING)
 189     return default_value;
 190   return head->u.string->str;
 191 }
 192 
 193 /* Lookup a header in the mapping and return the value as if it's an integer
 194  * and otherwise return the default.
 195  */
 196 INLINE static int lookup_integer_header(char *headername, int default_value)
 197 {
 198   struct svalue *head = NULL;
 199   THREAD_SAFE_RUN(head = lookup_header(headername), "header lookup");
 200   if(!head || head->type != PIKE_T_INT)
 201     return default_value;
 202   return head->u.integer;
 203 }
 204 
 205 /*
 206  * php_caudium_low_ub_write() writes data to the client connection. Might be
 207  * rewritten to do more direct IO to save CPU and the need to lock the 
 208  * interpreter for better threading.
 209  */
 210 
 211 INLINE static int
 212 php_caudium_low_ub_write(const char *str, uint str_length TSRMLS_DC) {
 213   int sent_bytes = 0;
 214   struct pike_string *to_write = NULL;
 215   GET_THIS();
 216   if(!MY_FD_OBJ->prog) {
 217     PG(connection_status) = PHP_CONNECTION_ABORTED;
 218     zend_bailout();
 219     return -1;
 220   }
 221   to_write = make_shared_binary_string(str, str_length);
 222   push_string(to_write);
 223   safe_apply(MY_FD_OBJ, "write", 1);
 224   if(Pike_sp[-1].type == PIKE_T_INT)
 225     sent_bytes = Pike_sp[-1].u.integer;
 226   pop_stack();
 227   if(sent_bytes != str_length) {
 228     /* This means the connection is closed. Dead. Gone. *sniff*  */
 229     PG(connection_status) = PHP_CONNECTION_ABORTED;
 230     zend_bailout();
 231   }
 232   return sent_bytes;
 233 }
 234 
 235 /*
 236  * php_caudium_sapi_ub_write() calls php_caudium_low_ub_write in a Pike thread
 237  * safe manner or writes directly to the output FD if RXML post-parsing is
 238  * disabled. 
 239  */
 240 
 241 static int
 242 php_caudium_sapi_ub_write(const char *str, uint str_length TSRMLS_DC)
 243 {
 244   GET_THIS();
 245   int sent_bytes = 0, fd = MY_FD;
 246   if(fd)
 247   {
 248     for(sent_bytes=0;sent_bytes < str_length;)
 249     {
 250       int written;
 251       written = fd_write(fd, str + sent_bytes, str_length - sent_bytes);
 252       if(written < 0)
 253       {
 254         switch(errno)
 255         {
 256          default:
 257           /* This means the connection is closed. Dead. Gone. *sniff*  */
 258           PG(connection_status) = PHP_CONNECTION_ABORTED;
 259           zend_bailout();
 260           THIS->written += sent_bytes;
 261           return sent_bytes;
 262          case EINTR: 
 263          case EWOULDBLOCK:
 264           continue;
 265         }
 266       } else {
 267         sent_bytes += written;
 268       }
 269     }
 270     THIS->written += sent_bytes;
 271   } else {
 272     THREAD_SAFE_RUN(sent_bytes = php_caudium_low_ub_write(str, str_length TSRMLS_CC),
 273                     "write");
 274   }
 275   return sent_bytes;
 276 }
 277 
 278 /* php_caudium_set_header() sets a header in the header mapping. Called in a
 279  * thread safe manner from php_caudium_sapi_header_handler.
 280  */
 281 INLINE static void
 282 php_caudium_set_header(char *header_name, char *value, char *p)
 283 {
 284   struct svalue hsval;
 285   struct pike_string *hval, *ind, *hind;
 286   struct mapping *headermap;
 287   struct svalue *s_headermap, *soldval;
 288   int vallen;
 289   GET_THIS();
 290   /*  hval = make_shared_string(value); */
 291   ind = make_shared_string(" _headers");
 292   hind = make_shared_binary_string(header_name,
 293                                    (int)(p - header_name));
 294 
 295   s_headermap = low_mapping_string_lookup(REQUEST_DATA, ind);
 296   if(!s_headermap || s_headermap->type != PIKE_T_MAPPING)
 297   {
 298     struct svalue mappie;                                           
 299     mappie.type = PIKE_T_MAPPING;
 300     headermap = allocate_mapping(1);
 301     mappie.u.mapping = headermap;
 302     mapping_string_insert(REQUEST_DATA, ind, &mappie);
 303     free_mapping(headermap);
 304     hval = make_shared_string(value);
 305   } else {
 306     headermap = s_headermap->u.mapping;
 307     soldval = low_mapping_string_lookup(headermap, hind);
 308     vallen = strlen(value);
 309     if(soldval != NULL && 
 310        soldval->type == PIKE_T_STRING &&
 311        soldval->u.string->size_shift == 0) {
 312       /* Existing, valid header. Prepend.*/
 313       hval = begin_shared_string(soldval->u.string->len + 1 + vallen);
 314       MEMCPY(hval->str, soldval->u.string->str, soldval->u.string->len);
 315       STR0(hval)[soldval->u.string->len] = '\0';
 316       MEMCPY(hval->str+soldval->u.string->len+1, value, vallen);
 317       hval = end_shared_string(hval);
 318     } else { 
 319       hval = make_shared_string(value);
 320     }
 321   }
 322   hsval.type = PIKE_T_STRING;
 323   hsval.u.string = hval;
 324 
 325   mapping_string_insert(headermap, hind, &hsval);
 326 
 327   free_string(hval);
 328   free_string(ind);
 329   free_string(hind);
 330 }
 331 
 332 /*
 333  * php_caudium_sapi_header_handler() sets a HTTP reply header to be 
 334  * sent to the client.
 335  */
 336 static int
 337 php_caudium_sapi_header_handler(sapi_header_struct *sapi_header,
 338                               sapi_headers_struct *sapi_headers TSRMLS_DC)
 339 {
 340   char *header_name, *header_content, *p;
 341   header_name = sapi_header->header;
 342   header_content = p = strchr(header_name, ':');
 343   
 344   if(p) {
 345   do {
 346     header_content++;
 347   } while(*header_content == ' ');
 348     THREAD_SAFE_RUN(php_caudium_set_header(header_name, header_content, p), "header handler");
 349   }
 350   sapi_free_header(sapi_header);
 351   return 0;
 352 }
 353 
 354 /*
 355  * php_caudium_sapi_send_headers() flushes the headers to the client.
 356  * Called before real content is sent by PHP.
 357  */
 358 
 359 INLINE static int
 360 php_caudium_low_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
 361 {
 362   struct pike_string *ind;
 363   struct svalue *s_headermap;
 364   GET_THIS();
 365   if(!MY_FD_OBJ->prog) {
 366     PG(connection_status) = PHP_CONNECTION_ABORTED;
 367     zend_bailout();
 368     return SAPI_HEADER_SEND_FAILED;
 369   }
 370   ind = make_shared_string(" _headers");  
 371   s_headermap = low_mapping_string_lookup(REQUEST_DATA, ind);
 372   free_string(ind);
 373   
 374   push_int(SG(sapi_headers).http_response_code);
 375   if(s_headermap && s_headermap->type == PIKE_T_MAPPING)
 376     ref_push_mapping(s_headermap->u.mapping);
 377   else
 378     push_int(0);
 379   safe_apply(MY_FD_OBJ, "send_headers", 2);
 380   pop_stack();
 381   
 382   return SAPI_HEADER_SENT_SUCCESSFULLY;
 383 }
 384 
 385 static int
 386 php_caudium_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
 387 {
 388   int res = 0;
 389   THREAD_SAFE_RUN(res = php_caudium_low_send_headers(sapi_headers TSRMLS_CC), "send headers");
 390   return res;
 391 }
 392 
 393 /*
 394  * php_caudium_sapi_read_post() reads a specified number of bytes from
 395  * the client. Used for POST/PUT requests.
 396  */
 397 
 398 INLINE static int php_caudium_low_read_post(char *buf, uint count_bytes)
 399 {
 400   uint total_read = 0;
 401   GET_THIS();
 402   TSRMLS_FETCH();
 403   
 404   if(!MY_FD_OBJ->prog)
 405   {
 406     PG(connection_status) = PHP_CONNECTION_ABORTED;
 407     zend_bailout();
 408     return -1;
 409   }
 410   push_int(count_bytes);
 411   safe_apply(MY_FD_OBJ, "read_post", 1);
 412   if(Pike_sp[-1].type == PIKE_T_STRING) {
 413     MEMCPY(buf, Pike_sp[-1].u.string->str,
 414            (total_read = Pike_sp[-1].u.string->len));
 415     buf[total_read] = '\0';
 416   } else
 417     total_read = 0;
 418   pop_stack();
 419   return total_read;
 420 }
 421 
 422 static int
 423 php_caudium_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC)
 424 {
 425   uint total_read = 0;
 426   THREAD_SAFE_RUN(total_read = php_caudium_low_read_post(buf, count_bytes), "read post");
 427   return total_read;
 428 }
 429 
 430 /* 
 431  * php_caudium_sapi_read_cookies() returns the Cookie header from
 432  * the HTTP request header
 433  */
 434         
 435 static char *
 436 php_caudium_sapi_read_cookies(TSRMLS_D)
 437 {
 438   char *cookies;
 439   cookies = lookup_string_header("HTTP_COOKIE", NULL);
 440   return cookies;
 441 }
 442 
 443 static void php_info_caudium(ZEND_MODULE_INFO_FUNC_ARGS)
 444 {
 445   /*  char buf[512]; */
 446   php_info_print_table_start();
 447   php_info_print_table_row(2, "SAPI module version", "$Id$");
 448   /*  php_info_print_table_row(2, "Build date", Ns_InfoBuildDate());
 449       php_info_print_table_row(2, "Config file path", Ns_InfoConfigFile());
 450       php_info_print_table_row(2, "Error Log path", Ns_InfoErrorLog());
 451       php_info_print_table_row(2, "Installation path", Ns_InfoHomePath());
 452       php_info_print_table_row(2, "Hostname of server", Ns_InfoHostname());
 453       php_info_print_table_row(2, "Source code label", Ns_InfoLabel());
 454       php_info_print_table_row(2, "Server platform", Ns_InfoPlatform());
 455       snprintf(buf, 511, "%s/%s", Ns_InfoServerName(), Ns_InfoServerVersion());
 456       php_info_print_table_row(2, "Server version", buf);
 457       snprintf(buf, 511, "%d day(s), %02d:%02d:%02d", 
 458       uptime / 86400,
 459       (uptime / 3600) % 24,
 460       (uptime / 60) % 60,
 461       uptime % 60);
 462       php_info_print_table_row(2, "Server uptime", buf);
 463   */
 464   php_info_print_table_end();
 465 }
 466 
 467 static zend_module_entry php_caudium_module = {
 468   STANDARD_MODULE_HEADER,
 469   "Caudium",
 470   NULL,
 471   NULL,
 472   NULL,
 473   NULL,
 474   NULL,
 475   php_info_caudium,
 476   NULL,
 477   STANDARD_MODULE_PROPERTIES
 478 };
 479 
 480 
 481 INLINE static void low_sapi_caudium_register_variables(zval *track_vars_array TSRMLS_DC)   
 482 {
 483   int i;
 484   struct keypair *k;
 485   struct svalue *headers;
 486   struct pike_string *sind;
 487   struct svalue *ind;
 488   struct svalue *val;
 489   GET_THIS();
 490   php_register_variable("PHP_SELF", SG(request_info).request_uri,
 491                         track_vars_array TSRMLS_CC);
 492   php_register_variable("GATEWAY_INTERFACE", "CGI/1.1",
 493                         track_vars_array TSRMLS_CC);
 494   php_register_variable("REQUEST_METHOD",
 495                         (char *) SG(request_info).request_method,
 496                         track_vars_array TSRMLS_CC);
 497   php_register_variable("REQUEST_URI", SG(request_info).request_uri,
 498                         track_vars_array TSRMLS_CC);
 499   php_register_variable("PATH_TRANSLATED", SG(request_info).path_translated,
 500                         track_vars_array TSRMLS_CC);
 501 
 502   sind = make_shared_string("env");
 503   headers = low_mapping_string_lookup(REQUEST_DATA, sind);
 504   free_string(sind);
 505   if(headers && headers->type == PIKE_T_MAPPING) {
 506     MY_MAPPING_LOOP(headers->u.mapping, i, k) {
 507       ind = &k->ind;
 508       val = &k->val;
 509       if(ind && ind->type == PIKE_T_STRING &&
 510          val && val->type == PIKE_T_STRING) {
 511         php_register_variable(ind->u.string->str, val->u.string->str,
 512                               track_vars_array TSRMLS_CC );
 513       }
 514     }
 515   }
 516 }
 517 
 518 static void sapi_caudium_register_variables(zval *track_vars_array TSRMLS_DC)
 519 {
 520   THREAD_SAFE_RUN(low_sapi_caudium_register_variables(track_vars_array TSRMLS_CC), "register_variables");
 521 }
 522 
 523 
 524 static int php_caudium_startup(sapi_module_struct *sapi_module)
 525 {
 526         if (php_module_startup(sapi_module, &php_caudium_module, 1)==FAILURE) {
 527                 return FAILURE;
 528         }
 529         return SUCCESS;
 530 }
 531 
 532 
 533 /* this structure is static (as in "it does not change") */
 534 static sapi_module_struct caudium_sapi_module = {
 535   "caudium",
 536   "Caudium",
 537   php_caudium_startup,                  /* startup */
 538   php_module_shutdown_wrapper,          /* shutdown */
 539   NULL,                                 /* activate */
 540   NULL,                                 /* deactivate */
 541   php_caudium_sapi_ub_write,            /* unbuffered write */
 542   NULL,                                 /* flush */
 543   NULL,                                 /* get uid */
 544   NULL,                                 /* getenv */
 545   php_error,                            /* error handler */
 546   php_caudium_sapi_header_handler,      /* header handler */
 547   php_caudium_sapi_send_headers,        /* send headers handler */
 548   NULL,                                 /* send header handler */
 549   php_caudium_sapi_read_post,           /* read POST data */
 550   php_caudium_sapi_read_cookies,        /* read cookies */
 551   sapi_caudium_register_variables,      /* register server variables */
 552   NULL,                                 /* Log message */
 553   NULL,                                 /* Get request time */
 554   NULL,                                 /* Child terminate */
 555 
 556   STANDARD_SAPI_MODULE_PROPERTIES
 557 };
 558 
 559 /*
 560  * php_caudium_module_main() is called by the per-request handler and
 561  * "executes" the script
 562  */
 563 
 564 static void php_caudium_module_main(php_caudium_request *ureq)
 565 {
 566   int res;
 567   zend_file_handle file_handle;
 568 #ifndef USE_PIKE_LEVEL_THREADS
 569   struct thread_state *state;
 570   extern struct program *thread_id_prog;
 571 #endif
 572   TSRMLS_FETCH();
 573   GET_THIS();
 574   THIS->filename = ureq->filename;
 575   THIS->done_cb = ureq->done_cb;
 576   THIS->my_fd_obj = ureq->my_fd_obj;
 577   THIS->my_fd = ureq->my_fd;
 578   THIS->request_data = ureq->request_data;
 579   free(ureq);
 580 
 581 #ifndef USE_PIKE_LEVEL_THREADS
 582   mt_lock_interpreter();
 583   init_interpreter();
 584 #if PIKE_MAJOR_VERSION == 7 && PIKE_MINOR_VERSION < 1
 585   thread_id = low_clone(thread_id_prog);
 586   state = OBJ2THREAD(thread_id);
 587   Pike_stack_top=((char *)&state)+ (thread_stack_size-16384) * STACK_DIRECTION;
 588   recoveries = NULL;
 589   call_c_initializers(thread_id);
 590   OBJ2THREAD(thread_id)->id=th_self();
 591   num_threads++;
 592   thread_table_insert(thread_id);
 593   state->status=THREAD_RUNNING;
 594 #else
 595   Pike_interpreter.thread_id = low_clone(thread_id_prog);
 596   state = OBJ2THREAD(Pike_interpreter.thread_id);
 597   Pike_interpreter.stack_top=((char *)&state)+ (thread_stack_size-16384) * STACK_DIRECTION;
 598   Pike_interpreter.recoveries = NULL;
 599   call_c_initializers(Pike_interpreter.thread_id);
 600   state->id=th_self();
 601   /*  SWAP_OUT_THREAD(OBJ2THREAD(Pike_interpreter.thread_id)); */
 602   num_threads++;
 603   thread_table_insert(Pike_interpreter.thread_id);
 604   state->status=THREAD_RUNNING;
 605 #endif
 606   state->swapped = 0;
 607 #endif 
 608   SG(request_info).query_string = lookup_string_header("QUERY_STRING", 0);
 609   SG(server_context) = (void *)1; /* avoid server_context == NULL */
 610 
 611   /* path_translated is apparently the absolute path to the file, not
 612      the translated PATH_INFO
 613   */
 614   SG(request_info).path_translated =
 615     lookup_string_header("SCRIPT_FILENAME", NULL);
 616   SG(request_info).request_uri = lookup_string_header("DOCUMENT_URI", NULL);
 617   if(!SG(request_info).request_uri)
 618     SG(request_info).request_uri = lookup_string_header("SCRIPT_NAME", NULL);
 619   SG(request_info).request_method = lookup_string_header("REQUEST_METHOD", "GET");
 620   SG(request_info).content_length = lookup_integer_header("HTTP_CONTENT_LENGTH", 0);
 621   SG(request_info).content_type = lookup_string_header("HTTP_CONTENT_TYPE", NULL);
 622   SG(sapi_headers).http_response_code = 200;
 623   if (!strcmp(SG(request_info).request_method, "HEAD")) {
 624     SG(request_info).headers_only = 1;
 625   } else {
 626     SG(request_info).headers_only = 0;
 627   }
 628 
 629   /* Let PHP5 handle the deconding of the AUTH */
 630   php_handle_auth_data(lookup_string_header("HTTP_AUTHORIZATION", NULL), TSRMLS_C);
 631    /* Swap out this thread and release the interpreter lock to allow
 632    * Pike threads to run. We wait since the above would otherwise require
 633    * a lot of unlock/lock.
 634    */
 635 #ifndef USE_PIKE_LEVEL_THREADS
 636   SWAP_OUT_THREAD(state);
 637   mt_unlock_interpreter();
 638 #else
 639   THREADS_ALLOW();
 640 #endif
 641 
 642   file_handle.type = ZEND_HANDLE_FILENAME;
 643   file_handle.filename = THIS->filename->str;
 644   file_handle.opened_path = NULL;
 645   file_handle.free_filename = 0;
 646 
 647   THIS->written = 0;
 648   res = php_request_startup(TSRMLS_C);
 649 
 650   if(res == FAILURE) {
 651     THREAD_SAFE_RUN({
 652       apply_svalue(&THIS->done_cb, 0);
 653       pop_stack();
 654       free_struct(TSRMLS_C);
 655     }, "Negative run response");
 656   } else {
 657     php_execute_script(&file_handle TSRMLS_CC);
 658     php_request_shutdown(NULL);
 659     THREAD_SAFE_RUN({
 660       push_int(THIS->written);
 661       apply_svalue(&THIS->done_cb, 1);
 662       pop_stack();
 663       free_struct(TSRMLS_C);
 664     }, "positive run response");
 665   }
 666 
 667 #ifndef USE_PIKE_LEVEL_THREADS
 668   mt_lock_interpreter();
 669   SWAP_IN_THREAD(state);
 670 #if PIKE_MAJOR_VERSION == 7 && PIKE_MINOR_VERSION < 1
 671   state->status=THREAD_EXITED;
 672   co_signal(& state->status_change);
 673   thread_table_delete(thread_id);
 674   free_object(thread_id);
 675   thread_id=NULL;
 676 #else
 677   state->status=THREAD_EXITED;
 678   co_signal(& state->status_change);
 679   thread_table_delete(Pike_interpreter.thread_id);
 680   free_object(Pike_interpreter.thread_id);
 681   Pike_interpreter.thread_id=NULL;
 682 #endif
 683   cleanup_interpret();
 684   num_threads--;
 685   mt_unlock_interpreter();
 686 #else
 687   THREADS_DISALLOW();
 688 #endif
 689 }
 690 
 691 /*
 692  * The php_caudium_request_handler() is called per request and handles
 693  * everything for one request.
 694  */
 695 
 696 void f_php_caudium_request_handler(INT32 args)
 697 {
 698   struct object *my_fd_obj;
 699   struct mapping *request_data;
 700   struct svalue *done_callback;
 701   struct pike_string *script;
 702   struct svalue *raw_fd;
 703   struct pike_string *ind;
 704   php_caudium_request *_request;
 705   THIS = malloc(sizeof(php_caudium_request));
 706   if(THIS == NULL)
 707     Pike_error("Out of memory.");
 708 
 709   get_all_args("PHP5.Interpreter->run", args, "%S%m%O%*", &script,
 710                &request_data, &my_fd_obj, &done_callback);
 711   if(done_callback->type != PIKE_T_FUNCTION) 
 712     Pike_error("PHP5.Interpreter->run: Bad argument 4, expected function.\n");
 713   add_ref(request_data);
 714   add_ref(my_fd_obj);
 715   add_ref(script);
 716 
 717   THIS->request_data = request_data;
 718   THIS->my_fd_obj = my_fd_obj;
 719   THIS->filename = script;
 720   assign_svalue_no_free(&THIS->done_cb, done_callback);
 721 
 722   ind = make_shared_binary_string("my_fd", 5);
 723   raw_fd = low_mapping_string_lookup(THIS->request_data, ind);
 724   if(raw_fd && raw_fd->type == PIKE_T_OBJECT)
 725   {
 726     int fd = fd_from_object(raw_fd->u.object);
 727     if(fd == -1)
 728       THIS->my_fd = 0; /* Don't send directly to this FD... */
 729     else
 730       THIS->my_fd = fd;
 731   } else
 732     THIS->my_fd = 0;
 733 #ifdef USE_PIKE_LEVEL_THREADS
 734   php_caudium_module_main(THIS);
 735 #else
 736   th_farm((void (*)(void *))php_caudium_module_main, THIS);
 737 #endif
 738   pop_n_elems(args);
 739 }
 740 
 741 static void free_struct(TSRMLS_D)
 742 {
 743   GET_THIS();
 744   if(THIS->request_data) free_mapping(THIS->request_data);
 745   if(THIS->my_fd_obj)    free_object(THIS->my_fd_obj);
 746   free_svalue(&THIS->done_cb);
 747   if(THIS->filename)     free_string(THIS->filename);
 748   MEMSET(THIS, 0, sizeof(php_caudium_request));
 749 }
 750 
 751 
 752 /*
 753  * pike_module_init() is called by Pike once at startup
 754  *
 755  * This functions allocates basic structures
 756  */
 757 
 758 void pike_module_init( void )
 759 {
 760   if (!caudium_php_initialized) {
 761     caudium_php_initialized = 1;
 762     tsrm_startup(1, 1, 0, NULL);
 763     ts_allocate_id(&caudium_globals_id, sizeof(php_caudium_request), NULL, NULL);
 764     sapi_startup(&caudium_sapi_module);
 765     sapi_module.startup(&caudium_sapi_module);
 766   }
 767   start_new_program(); /* Text */
 768   pike_add_function("run", f_php_caudium_request_handler,
 769                     "function(string, mapping, object, function:void)", 0);
 770   end_class("Interpreter", 0);
 771 }
 772 
 773 /*
 774  * pike_module_exit() performs the last steps before the
 775  * server exists. Shutdowns basic services and frees memory
 776  */
 777 
 778 void pike_module_exit(void)
 779 {
 780   caudium_php_initialized = 0;
 781   sapi_module.shutdown(&caudium_sapi_module);
 782   tsrm_shutdown();
 783 }
 784 #endif

/* [<][>][^][v][top][bottom][index][help] */