Annotation of embedaddon/php/sapi/roxen/roxen.c, revision 1.1.1.4

1.1       misho       1: /* 
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
1.1.1.4 ! misho       5:    | Copyright (c) 1997-2014 The PHP Group                                |
1.1       misho       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: 
1.1.1.2   misho      20: /* $Id$ */
1.1       misho      21: 
                     22: #include "php.h"
                     23: #ifdef HAVE_ROXEN
                     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: #ifndef ZTS
                     34: /* Only valid if thread safety is enabled. */
                     35: #undef ROXEN_USE_ZTS
                     36: #endif
                     37: 
                     38: 
                     39: /* Pike Include Files 
                     40:  *
                     41:  * conflicts with pike avoided by only using long names. Requires a new
                     42:  * Pike 0.7 since it was implemented for this interface only.
                     43:  *
                     44:  */
                     45: #define NO_PIKE_SHORTHAND
                     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 <error.h>
                     53: #include <array.h>
                     54: #include <backend.h>
                     55: #include <stralloc.h>
                     56: #include <mapping.h>
                     57: #include <object.h>
                     58: #include <threads.h>
                     59: #include <builtin_functions.h>
                     60: #include <operators.h>
                     61: 
                     62: #undef HIDE_GLOBAL_VARIABLES
                     63: #undef REVEAL_GLOBAL_VARIABLES
                     64: #define HIDE_GLOBAL_VARIABLES()
                     65: #define REVEAL_GLOBAL_VARIABLES()
                     66: 
                     67: /* php_roxen_request is per-request object storage */
                     68: 
                     69: typedef struct
                     70: {
                     71:   struct mapping *request_data;
                     72:   struct object *my_fd_obj;
                     73:   int my_fd;
                     74:   char *filename;
                     75: } php_roxen_request;
                     76: 
                     77: 
                     78: /* Defines to get to the data supplied when the script is started. */
                     79: 
                     80: #ifdef ROXEN_USE_ZTS
                     81: 
                     82: /* ZTS does work now, but it seems like it's faster using the "serialization"
                     83:  * method I previously used. Thus it's not used unless ROXEN_USE_ZTS is defined.
                     84:  */
                     85: 
                     86: /* Per thread storage area id... */
                     87: static int roxen_globals_id;
                     88: 
                     89: # define GET_THIS() php_roxen_request *_request = ts_resource(roxen_globals_id)
                     90: # define THIS _request
                     91: #else
                     92: static php_roxen_request *current_request = NULL;
                     93: 
                     94: # define GET_THIS() current_request = ((php_roxen_request *)Pike_fp->current_storage)
                     95: # define THIS current_request
                     96: #endif
                     97: 
                     98: /* File descriptor integer. Used to write directly to the FD without 
                     99:  * passing Pike
                    100:  */
                    101: #define MY_FD    (THIS->my_fd)
                    102: 
                    103: /* FD object. Really a PHPScript object from Pike which implements a couple
                    104:  * of functions to handle headers, writing and buffering.
                    105:  */
                    106: #define MY_FD_OBJ        ((struct object *)(THIS->my_fd_obj))
                    107: 
                    108: /* Mapping with data supplied from the calling Roxen module. Contains
                    109:  * a mapping with headers, an FD object etc.
                    110:  */
                    111: #define REQUEST_DATA ((struct mapping *)(THIS->request_data))
                    112: 
                    113: 
                    114: #if defined(_REENTRANT) && !defined(ROXEN_USE_ZTS)
                    115: /* Lock used to serialize the PHP execution. If ROXEN_USE_ZTS is defined, we
                    116:  * are using the PHP thread safe mechanism instead.
                    117:  */
                    118: static PIKE_MUTEX_T roxen_php_execution_lock;
                    119: # define PHP_INIT_LOCK()       mt_init(&roxen_php_execution_lock)
                    120: # define PHP_LOCK(X)    THREADS_ALLOW();mt_lock(&roxen_php_execution_lock);THREADS_DISALLOW()
                    121: # define PHP_UNLOCK(X) mt_unlock(&roxen_php_execution_lock);
                    122: # define PHP_DESTROY() mt_destroy(&roxen_php_execution_lock)
                    123: #else /* !_REENTRANT */
                    124: # define PHP_INIT_LOCK()       
                    125: # define PHP_LOCK(X)
                    126: # define PHP_UNLOCK(X)
                    127: # define PHP_DESTROY() 
                    128: #endif /* _REENTRANT */
                    129: 
                    130: extern int fd_from_object(struct object *o);
                    131: static unsigned char roxen_php_initialized;
                    132: 
                    133: /* This allows calling of pike functions from the PHP callbacks,
                    134:  * which requires the Pike interpreter to be locked.
                    135:  */
                    136: #define THREAD_SAFE_RUN(COMMAND, what)  do {\
                    137:   struct thread_state *state;\
                    138:  if((state = thread_state_for_id(th_self()))!=NULL) {\
                    139:     if(!state->swapped) {\
                    140:       COMMAND;\
                    141:     } else {\
                    142:       mt_lock(&interpreter_lock);\
                    143:       SWAP_IN_THREAD(state);\
                    144:       COMMAND;\
                    145:       SWAP_OUT_THREAD(state);\
                    146:       mt_unlock(&interpreter_lock);\
                    147:     }\
                    148:   }\
                    149: } while(0)
                    150: 
                    151: struct program *php_program;
                    152: 
                    153: 
                    154: /* To avoid executing a PHP script from a PHP callback, which would
                    155:  * create a deadlock, a global thread id is used. If the thread calling the
                    156:  * php-script is the same as the current thread, it fails. 
                    157:  */
                    158: static int current_thread = -1;
                    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: static INLINE struct svalue *lookup_header(char *headername)
                    166: {
                    167:   struct svalue *headers, *value;
                    168:   struct pike_string *sind;
                    169: #ifdef ROXEN_USE_ZTS
                    170:   GET_THIS();
                    171: #endif
                    172:   sind = make_shared_string("env");
                    173:   headers = low_mapping_string_lookup(REQUEST_DATA, sind);
                    174:   free_string(sind);
                    175:   if(!headers || headers->type != PIKE_T_MAPPING) return NULL;
                    176:   sind = make_shared_string(headername);
                    177:   value = low_mapping_string_lookup(headers->u.mapping, sind);
                    178:   free_string(sind);
                    179:   if(!value) return NULL;
                    180:   return value;
                    181: }
                    182: 
                    183: /* Lookup a header in the mapping and return the value as a string, or
                    184:  * return the default if it's missing
                    185:  */
                    186: INLINE static char *lookup_string_header(char *headername, char *default_value)
                    187: {
                    188:   struct svalue *head = NULL;
                    189:   THREAD_SAFE_RUN(head = lookup_header(headername), "header lookup");
                    190:   if(!head || head->type != PIKE_T_STRING)
                    191:     return default_value;
                    192:   return head->u.string->str;
                    193: }
                    194: 
                    195: /* Lookup a header in the mapping and return the value as if it's an integer
                    196:  * and otherwise return the default.
                    197:  */
                    198: INLINE static int lookup_integer_header(char *headername, int default_value)
                    199: {
                    200:   struct svalue *head = NULL;
                    201:   THREAD_SAFE_RUN(head = lookup_header(headername), "header lookup");
                    202:   if(!head || head->type != PIKE_T_INT)
                    203:     return default_value;
                    204:   return head->u.integer;
                    205: }
                    206: 
                    207: /*
                    208:  * php_roxen_low_ub_write() writes data to the client connection. Might be
                    209:  * rewritten to do more direct IO to save CPU and the need to lock the *
                    210:  * interpreter for better threading.
                    211:  */
                    212: 
                    213: static int
                    214: php_roxen_low_ub_write(const char *str, uint str_length TSRMLS_DC) {
                    215:   int sent_bytes = 0;
                    216:   struct pike_string *to_write = NULL;
                    217: #ifdef ROXEN_USE_ZTS
                    218:   GET_THIS();
                    219: #endif
                    220: 
                    221:   if(!MY_FD_OBJ->prog) {
                    222:     PG(connection_status) = PHP_CONNECTION_ABORTED;
                    223:     zend_bailout();
                    224:     return -1;
                    225:   }
                    226:   to_write = make_shared_binary_string(str, str_length);
                    227:   push_string(to_write);
                    228:   safe_apply(MY_FD_OBJ, "write", 1);
                    229:   if(Pike_sp[-1].type == PIKE_T_INT)
                    230:     sent_bytes = Pike_sp[-1].u.integer;
                    231:   pop_stack();
                    232:   if(sent_bytes != str_length) {
                    233:     /* This means the connection is closed. Dead. Gone. *sniff*  */
                    234:     php_handle_aborted_connection();
                    235:   }
                    236:   return sent_bytes;
                    237: }
                    238: 
                    239: /*
                    240:  * php_roxen_sapi_ub_write() calls php_roxen_low_ub_write in a Pike thread
                    241:  * safe manner.
                    242:  */
                    243: 
                    244: static int
                    245: php_roxen_sapi_ub_write(const char *str, uint str_length TSRMLS_DC)
                    246: {
                    247: #ifdef ROXEN_USE_ZTS
                    248:   GET_THIS();
                    249: #endif
                    250: 
                    251:   int sent_bytes = 0, fd = MY_FD;
                    252:   if(fd)
                    253:   {
                    254:     for(sent_bytes=0;sent_bytes < str_length;)
                    255:     {
                    256:       int written;
                    257:       written = fd_write(fd, str + sent_bytes, str_length - sent_bytes);
                    258:       if(written < 0)
                    259:       {
                    260:        switch(errno)
                    261:        {
                    262:         default:
                    263:          /* This means the connection is closed. Dead. Gone. *sniff*  */
                    264:          PG(connection_status) = PHP_CONNECTION_ABORTED;
                    265:          zend_bailout();
                    266:          return sent_bytes;
                    267:         case EINTR: 
                    268:         case EWOULDBLOCK:
                    269:          continue;
                    270:        }
                    271: 
                    272:       } else {
                    273:        sent_bytes += written;
                    274:       }
                    275:     }
                    276:   } else {
                    277:     THREAD_SAFE_RUN(sent_bytes = php_roxen_low_ub_write(str, str_length TSRMLS_CC),
                    278:                    "write");
                    279:   }
                    280:   return sent_bytes;
                    281: }
                    282: 
                    283: /* php_roxen_set_header() sets a header in the header mapping. Called in a
                    284:  * thread safe manner from php_roxen_sapi_header_handler.
                    285:  */
                    286: static void php_roxen_set_header(char *header_name, char *value, char *p)
                    287: {
                    288:   struct svalue hsval;
                    289:   struct pike_string *hval, *ind, *hind;
                    290:   struct mapping *headermap;
                    291:   struct svalue *s_headermap;
                    292: #ifdef ROXEN_USE_ZTS
                    293:   GET_THIS();
                    294: #endif
                    295:   hval = make_shared_string(value);
                    296:   ind = make_shared_string(" _headers");
                    297:   hind = make_shared_binary_string(header_name,
                    298:                                   (int)(p - header_name));
                    299: 
                    300:   s_headermap = low_mapping_string_lookup(REQUEST_DATA, ind);
                    301:   if(!s_headermap)
                    302:   {
                    303:     struct svalue mappie;                                           
                    304:     mappie.type = PIKE_T_MAPPING;
                    305:     headermap = allocate_mapping(1);
                    306:     mappie.u.mapping = headermap;
                    307:     mapping_string_insert(REQUEST_DATA, ind, &mappie);
                    308:     free_mapping(headermap);
                    309:   } else
                    310:     headermap = s_headermap->u.mapping;
                    311: 
                    312:   hsval.type = PIKE_T_STRING;
                    313:   hsval.u.string = hval;
                    314:   mapping_string_insert(headermap, hind, &hsval);
                    315: 
                    316:   free_string(hval);
                    317:   free_string(ind);
                    318:   free_string(hind);
                    319: }
                    320: 
                    321: /*
                    322:  * php_roxen_sapi_header_handler() sets a HTTP reply header to be 
                    323:  * sent to the client.
                    324:  */
                    325: static int
                    326: php_roxen_sapi_header_handler(sapi_header_struct *sapi_header,
                    327:                              sapi_headers_struct *sapi_headers TSRMLS_DC)
                    328: {
                    329:   char *header_name, *header_content, *p;
                    330:   header_name = sapi_header->header;
                    331:   header_content = p = strchr(header_name, ':');
                    332:   
                    333:   if(p) {
                    334:   do {
                    335:     header_content++;
                    336:   } while(*header_content == ' ');
                    337:     THREAD_SAFE_RUN(php_roxen_set_header(header_name, header_content, p), "header handler");
                    338:   }
                    339:   sapi_free_header(sapi_header);
                    340:   return 0;
                    341: }
                    342: 
                    343: /*
                    344:  * php_roxen_sapi_send_headers() flushes the headers to the client.
                    345:  * Called before real content is sent by PHP.
                    346:  */
                    347: 
                    348: static int
                    349: php_roxen_low_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
                    350: {
                    351:   struct pike_string *ind;
                    352:   struct svalue *s_headermap;
                    353: #ifdef ROXEN_USE_ZTS
                    354:   GET_THIS();
                    355: #endif
                    356: 
                    357:   if(!MY_FD_OBJ->prog) {
                    358:     PG(connection_status) = PHP_CONNECTION_ABORTED;
                    359:     zend_bailout();
                    360:     return SAPI_HEADER_SEND_FAILED;
                    361:   }
                    362:   ind = make_shared_string(" _headers");  
                    363:   s_headermap = low_mapping_string_lookup(REQUEST_DATA, ind);
                    364:   free_string(ind);
                    365:   
                    366:   push_int(SG(sapi_headers).http_response_code);
                    367:   if(s_headermap && s_headermap->type == PIKE_T_MAPPING)
                    368:     ref_push_mapping(s_headermap->u.mapping);
                    369:   else
                    370:     push_int(0);
                    371:   safe_apply(MY_FD_OBJ, "send_headers", 2);
                    372:   pop_stack();
                    373:   
                    374:   return SAPI_HEADER_SENT_SUCCESSFULLY;
                    375: }
                    376: 
                    377: static int
                    378: php_roxen_sapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
                    379: {
                    380:   int res = 0;
                    381:   THREAD_SAFE_RUN(res = php_roxen_low_send_headers(sapi_headers TSRMLS_CC), "send headers");
                    382:   return res;
                    383: }
                    384: 
                    385: /*
                    386:  * php_roxen_sapi_read_post() reads a specified number of bytes from
                    387:  * the client. Used for POST/PUT requests.
                    388:  */
                    389: 
                    390: INLINE static int php_roxen_low_read_post(char *buf, uint count_bytes)
                    391: {
                    392:   uint total_read = 0;
                    393: #ifdef ROXEN_USE_ZTS
                    394:   GET_THIS();
                    395: #endif
                    396:   TSRMLS_FETCH();
                    397:   
                    398:   if(!MY_FD_OBJ->prog)
                    399:   {
                    400:     PG(connection_status) = PHP_CONNECTION_ABORTED;
                    401:     zend_bailout();
                    402:     return -1;
                    403:   }
                    404:   push_int(count_bytes);
                    405:   safe_apply(MY_FD_OBJ, "read_post", 1);
                    406:   if(Pike_sp[-1].type == PIKE_T_STRING) {
                    407:     MEMCPY(buf, Pike_sp[-1].u.string->str,
                    408:            (total_read = Pike_sp[-1].u.string->len));
                    409:     buf[total_read] = '\0';
                    410:   } else
                    411:     total_read = 0;
                    412:   pop_stack();
                    413:   return total_read;
                    414: }
                    415: 
                    416: static int
                    417: php_roxen_sapi_read_post(char *buf, uint count_bytes TSRMLS_DC)
                    418: {
                    419:   uint total_read = 0;
                    420:   THREAD_SAFE_RUN(total_read = php_roxen_low_read_post(buf, count_bytes), "read post");
                    421:   return total_read;
                    422: }
                    423: 
                    424: /* 
                    425:  * php_roxen_sapi_read_cookies() returns the Cookie header from
                    426:  * the HTTP request header
                    427:  */
                    428:        
                    429: static char *
                    430: php_roxen_sapi_read_cookies(TSRMLS_D)
                    431: {
                    432:   char *cookies;
                    433:   cookies = lookup_string_header("HTTP_COOKIE", NULL);
                    434:   return cookies;
                    435: }
                    436: 
                    437: static void php_info_roxen(ZEND_MODULE_INFO_FUNC_ARGS)
                    438: {
                    439:   /*  char buf[512]; */
                    440:   php_info_print_table_start();
1.1.1.2   misho     441:   php_info_print_table_row(2, "SAPI module version", "$Id$");
1.1       misho     442:   /*  php_info_print_table_row(2, "Build date", Ns_InfoBuildDate());
                    443:       php_info_print_table_row(2, "Config file path", Ns_InfoConfigFile());
                    444:       php_info_print_table_row(2, "Error Log path", Ns_InfoErrorLog());
                    445:       php_info_print_table_row(2, "Installation path", Ns_InfoHomePath());
                    446:       php_info_print_table_row(2, "Hostname of server", Ns_InfoHostname());
                    447:       php_info_print_table_row(2, "Source code label", Ns_InfoLabel());
                    448:       php_info_print_table_row(2, "Server platform", Ns_InfoPlatform());
                    449:       snprintf(buf, 511, "%s/%s", Ns_InfoServerName(), Ns_InfoServerVersion());
                    450:       php_info_print_table_row(2, "Server version", buf);
                    451:       snprintf(buf, 511, "%d day(s), %02d:%02d:%02d", 
                    452:       uptime / 86400,
                    453:       (uptime / 3600) % 24,
                    454:       (uptime / 60) % 60,
                    455:       uptime % 60);
                    456:       php_info_print_table_row(2, "Server uptime", buf);
                    457:   */
                    458:   php_info_print_table_end();
                    459: }
                    460: 
                    461: static zend_module_entry php_roxen_module = {
                    462:   STANDARD_MODULE_HEADER,
                    463:   "Roxen",
                    464:   NULL,
                    465:   NULL,
                    466:   NULL,
                    467:   NULL,
                    468:   NULL,
                    469:   php_info_roxen,
                    470:   NULL,
                    471:   STANDARD_MODULE_PROPERTIES
                    472: };
                    473: 
                    474: static int php_roxen_startup(sapi_module_struct *sapi_module)
                    475: {
                    476:   if(php_module_startup(sapi_module, &php_roxen_module, 1) == FAILURE) {
                    477:     return FAILURE;
                    478:   } else {
                    479:     return SUCCESS;
                    480:   }
                    481: }
                    482: 
                    483: /* this structure is static (as in "it does not change") */
                    484: 
                    485: static sapi_module_struct roxen_sapi_module = {
                    486:   "roxen",
                    487:   "Roxen",
                    488:   php_roxen_startup,                   /* startup */
                    489:   php_module_shutdown_wrapper,         /* shutdown */
                    490:   NULL,                                        /* activate */
                    491:   NULL,                                        /* deactivate */
                    492:   php_roxen_sapi_ub_write,             /* unbuffered write */
                    493:   NULL,                                        /* flush */
                    494:   NULL,                                        /* get uid */
                    495:   NULL,                                        /* getenv */
                    496:   php_error,                           /* error handler */
                    497:   php_roxen_sapi_header_handler,       /* header handler */
                    498:   php_roxen_sapi_send_headers,         /* send headers handler */
                    499:   NULL,                                        /* send header handler */
                    500:   php_roxen_sapi_read_post,            /* read POST data */
                    501:   php_roxen_sapi_read_cookies,         /* read Cookies */
                    502:   NULL,                                        /* register server variables */
                    503:   NULL,                                        /* Log message */
                    504:   NULL,                                        /* Get request time */
                    505:   NULL,                                        /* Child terminate */
                    506: 
                    507:   STANDARD_SAPI_MODULE_PROPERTIES
                    508: };
                    509: 
                    510: /*
                    511:  * php_roxen_hash_environment() populates the php script environment
                    512:  * with a number of variables. HTTP_* variables are created for
                    513:  * the HTTP header data, so that a script can access these.
                    514:  */
                    515: #define ADD_STRING(name)                                                                               \
                    516:        MAKE_STD_ZVAL(zvalue);                                                                          \
                    517:        zvalue->type = IS_STRING;                                                                               \
                    518:        zvalue->value.str.len = strlen(buf);                                                    \
                    519:        zvalue->value.str.val = estrndup(buf, zvalue->value.str.len);   \
                    520:        zend_hash_update(&EG(symbol_table), name, sizeof(name),         \
                    521:                        &zvalue, sizeof(zval *), NULL)
                    522: 
                    523: static void
                    524: php_roxen_hash_environment(TSRMLS_D)
                    525: {
                    526:   int i;
                    527:   char buf[512];
                    528:   zval *zvalue;
                    529:   struct svalue *headers;
                    530:   struct pike_string *sind;
                    531:   struct array *indices;
                    532:   struct svalue *ind, *val;
                    533: #ifdef ROXEN_USE_ZTS
                    534:   GET_THIS();
                    535: #endif
                    536:   sind = make_shared_string("env");
                    537:   headers = low_mapping_string_lookup(REQUEST_DATA, sind);
                    538:   free_string(sind);
                    539:   if(headers && headers->type == PIKE_T_MAPPING) {
                    540:     indices = mapping_indices(headers->u.mapping);
                    541:     for(i = 0; i < indices->size; i++) {
                    542:       ind = &indices->item[i];
                    543:       val = low_mapping_lookup(headers->u.mapping, ind);
                    544:       if(ind && ind->type == PIKE_T_STRING &&
                    545:         val && val->type == PIKE_T_STRING) {
                    546:        int buf_len;
                    547:        buf_len = MIN(511, ind->u.string->len);
                    548:        strncpy(buf, ind->u.string->str, buf_len);
                    549:        buf[buf_len] = '\0'; /* Terminate correctly */
                    550:        MAKE_STD_ZVAL(zvalue);
                    551:        zvalue->type = IS_STRING;
                    552:        zvalue->value.str.len = val->u.string->len;
                    553:        zvalue->value.str.val = estrndup(val->u.string->str, zvalue->value.str.len);
                    554:        
                    555:        zend_hash_update(&EG(symbol_table), buf, buf_len + 1, &zvalue, sizeof(zval *), NULL);
                    556:       }
                    557:     }
                    558:     free_array(indices);
                    559:   }
                    560:   
                    561:   /*
                    562:     MAKE_STD_ZVAL(zvalue);
                    563:     zvalue->type = IS_LONG;
                    564:     zvalue->value.lval = Ns_InfoBootTime();
                    565:     zend_hash_update(&EG(symbol_table), "SERVER_BOOTTIME", sizeof("SERVER_BOOTTIME"), &zvalue, sizeof(zval *), NULL);
                    566:   */
                    567: }
                    568: 
                    569: /*
                    570:  * php_roxen_module_main() is called by the per-request handler and
                    571:  * "executes" the script
                    572:  */
                    573: 
                    574: static int php_roxen_module_main(TSRMLS_D)
                    575: {
                    576:   int res, len;
                    577:   char *dir;
                    578:   zend_file_handle file_handle;
                    579: #ifdef ROXEN_USE_ZTS
                    580:   GET_THIS();
                    581: #endif
                    582: 
                    583:   file_handle.type = ZEND_HANDLE_FILENAME;
                    584:   file_handle.filename = THIS->filename;
                    585:   file_handle.free_filename = 0;
                    586:   file_handle.opened_path = NULL;
                    587: 
                    588:   THREADS_ALLOW();
                    589:   res = php_request_startup(TSRMLS_C);
                    590:   THREADS_DISALLOW();
                    591:   if(res == FAILURE) {
                    592:     return 0;
                    593:   }
                    594:   php_roxen_hash_environment(TSRMLS_C);
                    595:   THREADS_ALLOW();
                    596:   php_execute_script(&file_handle TSRMLS_CC);
                    597:   php_request_shutdown(NULL);
                    598:   THREADS_DISALLOW();
                    599:   return 1;
                    600: }
                    601: 
                    602: /*
                    603:  * The php_roxen_request_handler() is called per request and handles
                    604:  * everything for one request.
                    605:  */
                    606: 
                    607: void f_php_roxen_request_handler(INT32 args)
                    608: {
                    609:   struct object *my_fd_obj;
                    610:   struct mapping *request_data;
                    611:   struct svalue *done_callback, *raw_fd;
                    612:   struct pike_string *script, *ind;
                    613:   int status = 1;
                    614: #ifdef ROXEN_USE_ZTS
                    615:   GET_THIS();
                    616: #endif
                    617:   TSRMLS_FETCH();
                    618: 
                    619:   if(current_thread == th_self())
                    620:     php_error(E_WARNING, "PHP5.Interpreter->run: Tried to run a PHP-script from a PHP "
                    621:          "callback!");
                    622:   get_all_args("PHP5.Interpreter->run", args, "%S%m%O%*", &script,
                    623:               &request_data, &my_fd_obj, &done_callback);
                    624:   if(done_callback->type != PIKE_T_FUNCTION) 
                    625:     php_error(E_WARNING, "PHP5.Interpreter->run: Bad argument 4, expected function.\n");
                    626:   PHP_LOCK(THIS); /* Need to lock here or reusing the same object might cause
                    627:                       * problems in changing stuff in that object */
                    628: #ifndef ROXEN_USE_ZTS
                    629:   GET_THIS();
                    630: #endif
                    631:   THIS->request_data = request_data;
                    632:   THIS->my_fd_obj = my_fd_obj;
                    633:   THIS->filename = script->str;
                    634:   current_thread = th_self();
                    635:   SG(request_info).query_string = lookup_string_header("QUERY_STRING", 0);
                    636:   SG(server_context) = (void *)1; /* avoid server_context == NULL */
                    637: 
                    638:   /* path_translated is apparently the absolute path to the file, not
                    639:      the translated PATH_INFO
                    640:   */
                    641:   SG(request_info).path_translated =
                    642:     lookup_string_header("SCRIPT_FILENAME", NULL);
                    643:   SG(request_info).request_uri = lookup_string_header("DOCUMENT_URI", NULL);
                    644:   if(!SG(request_info).request_uri)
                    645:     SG(request_info).request_uri = lookup_string_header("SCRIPT_NAME", NULL);
                    646:   SG(request_info).request_method = lookup_string_header("REQUEST_METHOD", "GET");
                    647:   SG(request_info).content_length = lookup_integer_header("HTTP_CONTENT_LENGTH", 0);
                    648:   SG(request_info).content_type = lookup_string_header("HTTP_CONTENT_TYPE", NULL);
                    649:   SG(sapi_headers).http_response_code = 200;
                    650: 
                    651:   /* FIXME: Check for auth stuff needs to be fixed... */ 
                    652:   SG(request_info).auth_user = NULL; 
                    653:   SG(request_info).auth_password = NULL;
                    654:   
                    655:   ind = make_shared_binary_string("my_fd", 5);
                    656:   raw_fd = low_mapping_string_lookup(THIS->request_data, ind);
                    657:   if(raw_fd && raw_fd->type == PIKE_T_OBJECT)
                    658:   {
                    659:     int fd = fd_from_object(raw_fd->u.object);
                    660:     if(fd == -1)
                    661:       php_error(E_WARNING, "PHP5.Interpreter->run: my_fd object not open or not an FD.\n");
                    662:     THIS->my_fd = fd;
                    663:   } else
                    664:     THIS->my_fd = 0;
                    665:   
                    666:   status = php_roxen_module_main(TSRMLS_C);
                    667:   current_thread = -1;
                    668:   
                    669:   apply_svalue(done_callback, 0);
                    670:   pop_stack();
                    671:   pop_n_elems(args);
                    672:   push_int(status);
                    673:   PHP_UNLOCK(THIS);
                    674: }
                    675: 
                    676: 
                    677: /* Clear the object global struct */
                    678: static void clear_struct(struct object *o)
                    679: {
                    680:   MEMSET(Pike_fp->current_storage, 0, sizeof(php_roxen_request));
                    681: }
                    682: 
                    683: 
                    684: /*
                    685:  * pike_module_init() is called by Pike once at startup
                    686:  *
                    687:  * This functions allocates basic structures
                    688:  */
                    689: 
                    690: void pike_module_init( void )
                    691: {
                    692:   if (!roxen_php_initialized) {
                    693: #ifdef ZTS
                    694:     tsrm_startup(1, 1, 0, NULL);
                    695: #ifdef ROXEN_USE_ZTS
                    696:     ts_allocate_id(&roxen_globals_id, sizeof(php_roxen_request), NULL, NULL);
                    697: #endif  
                    698: #endif
                    699:     sapi_startup(&roxen_sapi_module);
                    700:     /*php_roxen_startup(&roxen_sapi_module); removed - should be called from SAPI activation*/
                    701:     roxen_php_initialized = 1;
                    702:     PHP_INIT_LOCK();
                    703:   }
                    704:   start_new_program(); /* Text */
                    705:   ADD_STORAGE(php_roxen_request);
                    706:   set_init_callback(clear_struct);
                    707:   pike_add_function("run", f_php_roxen_request_handler,
                    708:                    "function(string, mapping, object, function:int)", 0);
                    709:   add_program_constant("Interpreter", (php_program = end_program()), 0);
                    710: }
                    711: 
                    712: /*
                    713:  * pike_module_exit() performs the last steps before the
                    714:  * server exists. Shutdowns basic services and frees memory
                    715:  */
                    716: 
                    717: void pike_module_exit(void)
                    718: {
                    719:   roxen_php_initialized = 0;
                    720:   roxen_sapi_module.shutdown(&roxen_sapi_module);
                    721:   if(php_program)  free_program(php_program);
                    722: #ifdef ZTS
                    723:   tsrm_shutdown();
                    724: #endif
                    725:   PHP_DESTROY();
                    726: }
                    727: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>