roxen.c 20 KB

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