caudium.c 23 KB

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