SAPI.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 7 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2018 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. | Original design: Shane Caraveo <shane@caraveo.com> |
  16. | Authors: Andi Gutmans <andi@php.net> |
  17. | Zeev Suraski <zeev@php.net> |
  18. +----------------------------------------------------------------------+
  19. */
  20. #include <ctype.h>
  21. #include <sys/stat.h>
  22. #include "php.h"
  23. #include "SAPI.h"
  24. #include "php_variables.h"
  25. #include "php_ini.h"
  26. #include "ext/standard/php_string.h"
  27. #include "ext/standard/pageinfo.h"
  28. #if (HAVE_PCRE || HAVE_BUNDLED_PCRE) && !defined(COMPILE_DL_PCRE)
  29. #include "ext/pcre/php_pcre.h"
  30. #endif
  31. #ifdef ZTS
  32. #include "TSRM.h"
  33. #endif
  34. #ifdef HAVE_SYS_TIME_H
  35. #include <sys/time.h>
  36. #elif defined(PHP_WIN32)
  37. #include "win32/time.h"
  38. #endif
  39. #include "rfc1867.h"
  40. #include "php_content_types.h"
  41. #ifdef ZTS
  42. SAPI_API int sapi_globals_id;
  43. #else
  44. sapi_globals_struct sapi_globals;
  45. #endif
  46. static void _type_dtor(zval *zv)
  47. {
  48. free(Z_PTR_P(zv));
  49. }
  50. static void sapi_globals_ctor(sapi_globals_struct *sapi_globals)
  51. {
  52. #ifdef ZTS
  53. ZEND_TSRMLS_CACHE_UPDATE();
  54. #endif
  55. memset(sapi_globals, 0, sizeof(*sapi_globals));
  56. zend_hash_init_ex(&sapi_globals->known_post_content_types, 8, NULL, _type_dtor, 1, 0);
  57. php_setup_sapi_content_types();
  58. }
  59. static void sapi_globals_dtor(sapi_globals_struct *sapi_globals)
  60. {
  61. zend_hash_destroy(&sapi_globals->known_post_content_types);
  62. }
  63. /* True globals (no need for thread safety) */
  64. SAPI_API sapi_module_struct sapi_module;
  65. SAPI_API void sapi_startup(sapi_module_struct *sf)
  66. {
  67. sf->ini_entries = NULL;
  68. sapi_module = *sf;
  69. #ifdef ZTS
  70. ts_allocate_id(&sapi_globals_id, sizeof(sapi_globals_struct), (ts_allocate_ctor) sapi_globals_ctor, (ts_allocate_dtor) sapi_globals_dtor);
  71. # ifdef PHP_WIN32
  72. _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
  73. # endif
  74. #else
  75. sapi_globals_ctor(&sapi_globals);
  76. #endif
  77. #ifdef PHP_WIN32
  78. tsrm_win32_startup();
  79. #endif
  80. reentrancy_startup();
  81. }
  82. SAPI_API void sapi_shutdown(void)
  83. {
  84. #ifdef ZTS
  85. ts_free_id(sapi_globals_id);
  86. #else
  87. sapi_globals_dtor(&sapi_globals);
  88. #endif
  89. reentrancy_shutdown();
  90. #ifdef PHP_WIN32
  91. tsrm_win32_shutdown();
  92. #endif
  93. }
  94. SAPI_API void sapi_free_header(sapi_header_struct *sapi_header)
  95. {
  96. efree(sapi_header->header);
  97. }
  98. /* {{{ proto bool header_register_callback(mixed callback)
  99. call a header function */
  100. PHP_FUNCTION(header_register_callback)
  101. {
  102. zval *callback_func;
  103. if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &callback_func) == FAILURE) {
  104. return;
  105. }
  106. if (!zend_is_callable(callback_func, 0, NULL)) {
  107. RETURN_FALSE;
  108. }
  109. if (Z_TYPE(SG(callback_func)) != IS_UNDEF) {
  110. zval_ptr_dtor(&SG(callback_func));
  111. SG(fci_cache) = empty_fcall_info_cache;
  112. }
  113. ZVAL_COPY(&SG(callback_func), callback_func);
  114. RETURN_TRUE;
  115. }
  116. /* }}} */
  117. static void sapi_run_header_callback(zval *callback)
  118. {
  119. int error;
  120. zend_fcall_info fci;
  121. char *callback_error = NULL;
  122. zval retval;
  123. if (zend_fcall_info_init(callback, 0, &fci, &SG(fci_cache), NULL, &callback_error) == SUCCESS) {
  124. fci.retval = &retval;
  125. error = zend_call_function(&fci, &SG(fci_cache));
  126. if (error == FAILURE) {
  127. goto callback_failed;
  128. } else {
  129. zval_ptr_dtor(&retval);
  130. }
  131. } else {
  132. callback_failed:
  133. php_error_docref(NULL, E_WARNING, "Could not call the sapi_header_callback");
  134. }
  135. if (callback_error) {
  136. efree(callback_error);
  137. }
  138. }
  139. SAPI_API void sapi_handle_post(void *arg)
  140. {
  141. if (SG(request_info).post_entry && SG(request_info).content_type_dup) {
  142. SG(request_info).post_entry->post_handler(SG(request_info).content_type_dup, arg);
  143. efree(SG(request_info).content_type_dup);
  144. SG(request_info).content_type_dup = NULL;
  145. }
  146. }
  147. static void sapi_read_post_data(void)
  148. {
  149. sapi_post_entry *post_entry;
  150. uint32_t content_type_length = (uint32_t)strlen(SG(request_info).content_type);
  151. char *content_type = estrndup(SG(request_info).content_type, content_type_length);
  152. char *p;
  153. char oldchar=0;
  154. void (*post_reader_func)(void) = NULL;
  155. /* dedicated implementation for increased performance:
  156. * - Make the content type lowercase
  157. * - Trim descriptive data, stay with the content-type only
  158. */
  159. for (p=content_type; p<content_type+content_type_length; p++) {
  160. switch (*p) {
  161. case ';':
  162. case ',':
  163. case ' ':
  164. content_type_length = p-content_type;
  165. oldchar = *p;
  166. *p = 0;
  167. break;
  168. default:
  169. *p = tolower(*p);
  170. break;
  171. }
  172. }
  173. /* now try to find an appropriate POST content handler */
  174. if ((post_entry = zend_hash_str_find_ptr(&SG(known_post_content_types), content_type,
  175. content_type_length)) != NULL) {
  176. /* found one, register it for use */
  177. SG(request_info).post_entry = post_entry;
  178. post_reader_func = post_entry->post_reader;
  179. } else {
  180. /* fallback */
  181. SG(request_info).post_entry = NULL;
  182. if (!sapi_module.default_post_reader) {
  183. /* no default reader ? */
  184. SG(request_info).content_type_dup = NULL;
  185. sapi_module.sapi_error(E_WARNING, "Unsupported content type: '%s'", content_type);
  186. return;
  187. }
  188. }
  189. if (oldchar) {
  190. *(p-1) = oldchar;
  191. }
  192. SG(request_info).content_type_dup = content_type;
  193. if(post_reader_func) {
  194. post_reader_func();
  195. }
  196. if(sapi_module.default_post_reader) {
  197. sapi_module.default_post_reader();
  198. }
  199. }
  200. SAPI_API size_t sapi_read_post_block(char *buffer, size_t buflen)
  201. {
  202. size_t read_bytes;
  203. if (!sapi_module.read_post) {
  204. return 0;
  205. }
  206. read_bytes = sapi_module.read_post(buffer, buflen);
  207. if (read_bytes > 0) {
  208. /* gogo */
  209. SG(read_post_bytes) += read_bytes;
  210. }
  211. if (read_bytes < buflen) {
  212. /* done */
  213. SG(post_read) = 1;
  214. }
  215. return read_bytes;
  216. }
  217. SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data)
  218. {
  219. if ((SG(post_max_size) > 0) && (SG(request_info).content_length > SG(post_max_size))) {
  220. php_error_docref(NULL, E_WARNING, "POST Content-Length of " ZEND_LONG_FMT " bytes exceeds the limit of " ZEND_LONG_FMT " bytes",
  221. SG(request_info).content_length, SG(post_max_size));
  222. return;
  223. }
  224. SG(request_info).request_body = php_stream_temp_create_ex(TEMP_STREAM_DEFAULT, SAPI_POST_BLOCK_SIZE, PG(upload_tmp_dir));
  225. if (sapi_module.read_post) {
  226. size_t read_bytes;
  227. for (;;) {
  228. char buffer[SAPI_POST_BLOCK_SIZE];
  229. read_bytes = sapi_read_post_block(buffer, SAPI_POST_BLOCK_SIZE);
  230. if (read_bytes > 0) {
  231. if (php_stream_write(SG(request_info).request_body, buffer, read_bytes) != read_bytes) {
  232. /* if parts of the stream can't be written, purge it completely */
  233. php_stream_truncate_set_size(SG(request_info).request_body, 0);
  234. php_error_docref(NULL, E_WARNING, "POST data can't be buffered; all data discarded");
  235. break;
  236. }
  237. }
  238. if ((SG(post_max_size) > 0) && (SG(read_post_bytes) > SG(post_max_size))) {
  239. php_error_docref(NULL, E_WARNING, "Actual POST length does not match Content-Length, and exceeds " ZEND_LONG_FMT " bytes", SG(post_max_size));
  240. break;
  241. }
  242. if (read_bytes < SAPI_POST_BLOCK_SIZE) {
  243. /* done */
  244. break;
  245. }
  246. }
  247. php_stream_rewind(SG(request_info).request_body);
  248. }
  249. }
  250. static inline char *get_default_content_type(uint32_t prefix_len, uint32_t *len)
  251. {
  252. char *mimetype, *charset, *content_type;
  253. uint32_t mimetype_len, charset_len;
  254. if (SG(default_mimetype)) {
  255. mimetype = SG(default_mimetype);
  256. mimetype_len = (uint32_t)strlen(SG(default_mimetype));
  257. } else {
  258. mimetype = SAPI_DEFAULT_MIMETYPE;
  259. mimetype_len = sizeof(SAPI_DEFAULT_MIMETYPE) - 1;
  260. }
  261. if (SG(default_charset)) {
  262. charset = SG(default_charset);
  263. charset_len = (uint32_t)strlen(SG(default_charset));
  264. } else {
  265. charset = SAPI_DEFAULT_CHARSET;
  266. charset_len = sizeof(SAPI_DEFAULT_CHARSET) - 1;
  267. }
  268. if (*charset && strncasecmp(mimetype, "text/", 5) == 0) {
  269. char *p;
  270. *len = prefix_len + mimetype_len + sizeof("; charset=") - 1 + charset_len;
  271. content_type = (char*)emalloc(*len + 1);
  272. p = content_type + prefix_len;
  273. memcpy(p, mimetype, mimetype_len);
  274. p += mimetype_len;
  275. memcpy(p, "; charset=", sizeof("; charset=") - 1);
  276. p += sizeof("; charset=") - 1;
  277. memcpy(p, charset, charset_len + 1);
  278. } else {
  279. *len = prefix_len + mimetype_len;
  280. content_type = (char*)emalloc(*len + 1);
  281. memcpy(content_type + prefix_len, mimetype, mimetype_len + 1);
  282. }
  283. return content_type;
  284. }
  285. SAPI_API char *sapi_get_default_content_type(void)
  286. {
  287. uint32_t len;
  288. return get_default_content_type(0, &len);
  289. }
  290. SAPI_API void sapi_get_default_content_type_header(sapi_header_struct *default_header)
  291. {
  292. uint32_t len;
  293. default_header->header = get_default_content_type(sizeof("Content-type: ")-1, &len);
  294. default_header->header_len = len;
  295. memcpy(default_header->header, "Content-type: ", sizeof("Content-type: ") - 1);
  296. }
  297. /*
  298. * Add charset on content-type header if the MIME type starts with
  299. * "text/", the default_charset directive is not empty and
  300. * there is not already a charset option in there.
  301. *
  302. * If "mimetype" is non-NULL, it should point to a pointer allocated
  303. * with emalloc(). If a charset is added, the string will be
  304. * re-allocated and the new length is returned. If mimetype is
  305. * unchanged, 0 is returned.
  306. *
  307. */
  308. SAPI_API size_t sapi_apply_default_charset(char **mimetype, size_t len)
  309. {
  310. char *charset, *newtype;
  311. size_t newlen;
  312. charset = SG(default_charset) ? SG(default_charset) : SAPI_DEFAULT_CHARSET;
  313. if (*mimetype != NULL) {
  314. if (*charset && strncmp(*mimetype, "text/", 5) == 0 && strstr(*mimetype, "charset=") == NULL) {
  315. newlen = len + (sizeof(";charset=")-1) + strlen(charset);
  316. newtype = emalloc(newlen + 1);
  317. PHP_STRLCPY(newtype, *mimetype, newlen + 1, len);
  318. strlcat(newtype, ";charset=", newlen + 1);
  319. strlcat(newtype, charset, newlen + 1);
  320. efree(*mimetype);
  321. *mimetype = newtype;
  322. return newlen;
  323. }
  324. }
  325. return 0;
  326. }
  327. SAPI_API void sapi_activate_headers_only(void)
  328. {
  329. if (SG(request_info).headers_read == 1)
  330. return;
  331. SG(request_info).headers_read = 1;
  332. zend_llist_init(&SG(sapi_headers).headers, sizeof(sapi_header_struct),
  333. (void (*)(void *)) sapi_free_header, 0);
  334. SG(sapi_headers).send_default_content_type = 1;
  335. /* SG(sapi_headers).http_response_code = 200; */
  336. SG(sapi_headers).http_status_line = NULL;
  337. SG(sapi_headers).mimetype = NULL;
  338. SG(read_post_bytes) = 0;
  339. SG(request_info).request_body = NULL;
  340. SG(request_info).current_user = NULL;
  341. SG(request_info).current_user_length = 0;
  342. SG(request_info).no_headers = 0;
  343. SG(request_info).post_entry = NULL;
  344. SG(global_request_time) = 0;
  345. /*
  346. * It's possible to override this general case in the activate() callback,
  347. * if necessary.
  348. */
  349. if (SG(request_info).request_method && !strcmp(SG(request_info).request_method, "HEAD")) {
  350. SG(request_info).headers_only = 1;
  351. } else {
  352. SG(request_info).headers_only = 0;
  353. }
  354. if (SG(server_context)) {
  355. SG(request_info).cookie_data = sapi_module.read_cookies();
  356. if (sapi_module.activate) {
  357. sapi_module.activate();
  358. }
  359. }
  360. if (sapi_module.input_filter_init ) {
  361. sapi_module.input_filter_init();
  362. }
  363. }
  364. /*
  365. * Called from php_request_startup() for every request.
  366. */
  367. SAPI_API void sapi_activate(void)
  368. {
  369. zend_llist_init(&SG(sapi_headers).headers, sizeof(sapi_header_struct), (void (*)(void *)) sapi_free_header, 0);
  370. SG(sapi_headers).send_default_content_type = 1;
  371. /*
  372. SG(sapi_headers).http_response_code = 200;
  373. */
  374. SG(sapi_headers).http_status_line = NULL;
  375. SG(sapi_headers).mimetype = NULL;
  376. SG(headers_sent) = 0;
  377. ZVAL_UNDEF(&SG(callback_func));
  378. SG(read_post_bytes) = 0;
  379. SG(request_info).request_body = NULL;
  380. SG(request_info).current_user = NULL;
  381. SG(request_info).current_user_length = 0;
  382. SG(request_info).no_headers = 0;
  383. SG(request_info).post_entry = NULL;
  384. SG(request_info).proto_num = 1000; /* Default to HTTP 1.0 */
  385. SG(global_request_time) = 0;
  386. SG(post_read) = 0;
  387. /* It's possible to override this general case in the activate() callback, if necessary. */
  388. if (SG(request_info).request_method && !strcmp(SG(request_info).request_method, "HEAD")) {
  389. SG(request_info).headers_only = 1;
  390. } else {
  391. SG(request_info).headers_only = 0;
  392. }
  393. SG(rfc1867_uploaded_files) = NULL;
  394. /* Handle request method */
  395. if (SG(server_context)) {
  396. if (PG(enable_post_data_reading)
  397. && SG(request_info).content_type
  398. && SG(request_info).request_method
  399. && !strcmp(SG(request_info).request_method, "POST")) {
  400. /* HTTP POST may contain form data to be processed into variables
  401. * depending on given content type */
  402. sapi_read_post_data();
  403. } else {
  404. SG(request_info).content_type_dup = NULL;
  405. }
  406. /* Cookies */
  407. SG(request_info).cookie_data = sapi_module.read_cookies();
  408. }
  409. if (sapi_module.activate) {
  410. sapi_module.activate();
  411. }
  412. if (sapi_module.input_filter_init) {
  413. sapi_module.input_filter_init();
  414. }
  415. }
  416. static void sapi_send_headers_free(void)
  417. {
  418. if (SG(sapi_headers).http_status_line) {
  419. efree(SG(sapi_headers).http_status_line);
  420. SG(sapi_headers).http_status_line = NULL;
  421. }
  422. }
  423. SAPI_API void sapi_deactivate(void)
  424. {
  425. zend_llist_destroy(&SG(sapi_headers).headers);
  426. if (SG(request_info).request_body) {
  427. SG(request_info).request_body = NULL;
  428. } else if (SG(server_context)) {
  429. if (!SG(post_read)) {
  430. /* make sure we've consumed all request input data */
  431. char dummy[SAPI_POST_BLOCK_SIZE];
  432. size_t read_bytes;
  433. do {
  434. read_bytes = sapi_read_post_block(dummy, SAPI_POST_BLOCK_SIZE);
  435. } while (SAPI_POST_BLOCK_SIZE == read_bytes);
  436. }
  437. }
  438. if (SG(request_info).auth_user) {
  439. efree(SG(request_info).auth_user);
  440. }
  441. if (SG(request_info).auth_password) {
  442. efree(SG(request_info).auth_password);
  443. }
  444. if (SG(request_info).auth_digest) {
  445. efree(SG(request_info).auth_digest);
  446. }
  447. if (SG(request_info).content_type_dup) {
  448. efree(SG(request_info).content_type_dup);
  449. }
  450. if (SG(request_info).current_user) {
  451. efree(SG(request_info).current_user);
  452. }
  453. if (sapi_module.deactivate) {
  454. sapi_module.deactivate();
  455. }
  456. if (SG(rfc1867_uploaded_files)) {
  457. destroy_uploaded_files_hash();
  458. }
  459. if (SG(sapi_headers).mimetype) {
  460. efree(SG(sapi_headers).mimetype);
  461. SG(sapi_headers).mimetype = NULL;
  462. }
  463. sapi_send_headers_free();
  464. SG(sapi_started) = 0;
  465. SG(headers_sent) = 0;
  466. SG(request_info).headers_read = 0;
  467. SG(global_request_time) = 0;
  468. }
  469. SAPI_API void sapi_initialize_empty_request(void)
  470. {
  471. SG(server_context) = NULL;
  472. SG(request_info).request_method = NULL;
  473. SG(request_info).auth_digest = SG(request_info).auth_user = SG(request_info).auth_password = NULL;
  474. SG(request_info).content_type_dup = NULL;
  475. }
  476. static int sapi_extract_response_code(const char *header_line)
  477. {
  478. int code = 200;
  479. const char *ptr;
  480. for (ptr = header_line; *ptr; ptr++) {
  481. if (*ptr == ' ' && *(ptr + 1) != ' ') {
  482. code = atoi(ptr + 1);
  483. break;
  484. }
  485. }
  486. return code;
  487. }
  488. static void sapi_update_response_code(int ncode)
  489. {
  490. /* if the status code did not change, we do not want
  491. to change the status line, and no need to change the code */
  492. if (SG(sapi_headers).http_response_code == ncode) {
  493. return;
  494. }
  495. if (SG(sapi_headers).http_status_line) {
  496. efree(SG(sapi_headers).http_status_line);
  497. SG(sapi_headers).http_status_line = NULL;
  498. }
  499. SG(sapi_headers).http_response_code = ncode;
  500. }
  501. /*
  502. * since zend_llist_del_element only remove one matched item once,
  503. * we should remove them by ourself
  504. */
  505. static void sapi_remove_header(zend_llist *l, char *name, size_t len) {
  506. sapi_header_struct *header;
  507. zend_llist_element *next;
  508. zend_llist_element *current=l->head;
  509. while (current) {
  510. header = (sapi_header_struct *)(current->data);
  511. next = current->next;
  512. if (header->header_len > len && header->header[len] == ':'
  513. && !strncasecmp(header->header, name, len)) {
  514. if (current->prev) {
  515. current->prev->next = next;
  516. } else {
  517. l->head = next;
  518. }
  519. if (next) {
  520. next->prev = current->prev;
  521. } else {
  522. l->tail = current->prev;
  523. }
  524. sapi_free_header(header);
  525. efree(current);
  526. --l->count;
  527. }
  528. current = next;
  529. }
  530. }
  531. SAPI_API int sapi_add_header_ex(char *header_line, size_t header_line_len, zend_bool duplicate, zend_bool replace)
  532. {
  533. sapi_header_line ctr = {0};
  534. int r;
  535. ctr.line = header_line;
  536. ctr.line_len = header_line_len;
  537. r = sapi_header_op(replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD,
  538. &ctr);
  539. if (!duplicate)
  540. efree(header_line);
  541. return r;
  542. }
  543. static void sapi_header_add_op(sapi_header_op_enum op, sapi_header_struct *sapi_header)
  544. {
  545. if (!sapi_module.header_handler ||
  546. (SAPI_HEADER_ADD & sapi_module.header_handler(sapi_header, op, &SG(sapi_headers)))) {
  547. if (op == SAPI_HEADER_REPLACE) {
  548. char *colon_offset = strchr(sapi_header->header, ':');
  549. if (colon_offset) {
  550. char sav = *colon_offset;
  551. *colon_offset = 0;
  552. sapi_remove_header(&SG(sapi_headers).headers, sapi_header->header, strlen(sapi_header->header));
  553. *colon_offset = sav;
  554. }
  555. }
  556. zend_llist_add_element(&SG(sapi_headers).headers, (void *) sapi_header);
  557. } else {
  558. sapi_free_header(sapi_header);
  559. }
  560. }
  561. SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg)
  562. {
  563. sapi_header_struct sapi_header;
  564. char *colon_offset;
  565. char *header_line;
  566. size_t header_line_len;
  567. int http_response_code;
  568. if (SG(headers_sent) && !SG(request_info).no_headers) {
  569. const char *output_start_filename = php_output_get_start_filename();
  570. int output_start_lineno = php_output_get_start_lineno();
  571. if (output_start_filename) {
  572. sapi_module.sapi_error(E_WARNING, "Cannot modify header information - headers already sent by (output started at %s:%d)",
  573. output_start_filename, output_start_lineno);
  574. } else {
  575. sapi_module.sapi_error(E_WARNING, "Cannot modify header information - headers already sent");
  576. }
  577. return FAILURE;
  578. }
  579. switch (op) {
  580. case SAPI_HEADER_SET_STATUS:
  581. sapi_update_response_code((int)(zend_intptr_t) arg);
  582. return SUCCESS;
  583. case SAPI_HEADER_ADD:
  584. case SAPI_HEADER_REPLACE:
  585. case SAPI_HEADER_DELETE: {
  586. sapi_header_line *p = arg;
  587. if (!p->line || !p->line_len) {
  588. return FAILURE;
  589. }
  590. header_line = p->line;
  591. header_line_len = p->line_len;
  592. http_response_code = p->response_code;
  593. break;
  594. }
  595. case SAPI_HEADER_DELETE_ALL:
  596. if (sapi_module.header_handler) {
  597. sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers));
  598. }
  599. zend_llist_clean(&SG(sapi_headers).headers);
  600. return SUCCESS;
  601. default:
  602. return FAILURE;
  603. }
  604. header_line = estrndup(header_line, header_line_len);
  605. /* cut off trailing spaces, linefeeds and carriage-returns */
  606. if (header_line_len && isspace(header_line[header_line_len-1])) {
  607. do {
  608. header_line_len--;
  609. } while(header_line_len && isspace(header_line[header_line_len-1]));
  610. header_line[header_line_len]='\0';
  611. }
  612. if (op == SAPI_HEADER_DELETE) {
  613. if (strchr(header_line, ':')) {
  614. efree(header_line);
  615. sapi_module.sapi_error(E_WARNING, "Header to delete may not contain colon.");
  616. return FAILURE;
  617. }
  618. if (sapi_module.header_handler) {
  619. sapi_header.header = header_line;
  620. sapi_header.header_len = header_line_len;
  621. sapi_module.header_handler(&sapi_header, op, &SG(sapi_headers));
  622. }
  623. sapi_remove_header(&SG(sapi_headers).headers, header_line, header_line_len);
  624. efree(header_line);
  625. return SUCCESS;
  626. } else {
  627. /* new line/NUL character safety check */
  628. uint32_t i;
  629. for (i = 0; i < header_line_len; i++) {
  630. /* RFC 7230 ch. 3.2.4 deprecates folding support */
  631. if (header_line[i] == '\n' || header_line[i] == '\r') {
  632. efree(header_line);
  633. sapi_module.sapi_error(E_WARNING, "Header may not contain "
  634. "more than a single header, new line detected");
  635. return FAILURE;
  636. }
  637. if (header_line[i] == '\0') {
  638. efree(header_line);
  639. sapi_module.sapi_error(E_WARNING, "Header may not contain NUL bytes");
  640. return FAILURE;
  641. }
  642. }
  643. }
  644. sapi_header.header = header_line;
  645. sapi_header.header_len = header_line_len;
  646. /* Check the header for a few cases that we have special support for in SAPI */
  647. if (header_line_len>=5
  648. && !strncasecmp(header_line, "HTTP/", 5)) {
  649. /* filter out the response code */
  650. sapi_update_response_code(sapi_extract_response_code(header_line));
  651. /* sapi_update_response_code doesn't free the status line if the code didn't change */
  652. if (SG(sapi_headers).http_status_line) {
  653. efree(SG(sapi_headers).http_status_line);
  654. }
  655. SG(sapi_headers).http_status_line = header_line;
  656. return SUCCESS;
  657. } else {
  658. colon_offset = strchr(header_line, ':');
  659. if (colon_offset) {
  660. *colon_offset = 0;
  661. if (!strcasecmp(header_line, "Content-Type")) {
  662. char *ptr = colon_offset+1, *mimetype = NULL, *newheader;
  663. size_t len = header_line_len - (ptr - header_line), newlen;
  664. while (*ptr == ' ') {
  665. ptr++;
  666. len--;
  667. }
  668. /* Disable possible output compression for images */
  669. if (!strncmp(ptr, "image/", sizeof("image/")-1)) {
  670. zend_string *key = zend_string_init("zlib.output_compression", sizeof("zlib.output_compression")-1, 0);
  671. zend_alter_ini_entry_chars(key, "0", sizeof("0") - 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
  672. zend_string_release_ex(key, 0);
  673. }
  674. mimetype = estrdup(ptr);
  675. newlen = sapi_apply_default_charset(&mimetype, len);
  676. if (!SG(sapi_headers).mimetype){
  677. SG(sapi_headers).mimetype = estrdup(mimetype);
  678. }
  679. if (newlen != 0) {
  680. newlen += sizeof("Content-type: ");
  681. newheader = emalloc(newlen);
  682. PHP_STRLCPY(newheader, "Content-type: ", newlen, sizeof("Content-type: ")-1);
  683. strlcat(newheader, mimetype, newlen);
  684. sapi_header.header = newheader;
  685. sapi_header.header_len = (uint32_t)(newlen - 1);
  686. efree(header_line);
  687. }
  688. efree(mimetype);
  689. SG(sapi_headers).send_default_content_type = 0;
  690. } else if (!strcasecmp(header_line, "Content-Length")) {
  691. /* Script is setting Content-length. The script cannot reasonably
  692. * know the size of the message body after compression, so it's best
  693. * do disable compression altogether. This contributes to making scripts
  694. * portable between setups that have and don't have zlib compression
  695. * enabled globally. See req #44164 */
  696. zend_string *key = zend_string_init("zlib.output_compression", sizeof("zlib.output_compression")-1, 0);
  697. zend_alter_ini_entry_chars(key,
  698. "0", sizeof("0") - 1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
  699. zend_string_release_ex(key, 0);
  700. } else if (!strcasecmp(header_line, "Location")) {
  701. if ((SG(sapi_headers).http_response_code < 300 ||
  702. SG(sapi_headers).http_response_code > 399) &&
  703. SG(sapi_headers).http_response_code != 201) {
  704. /* Return a Found Redirect if one is not already specified */
  705. if (http_response_code) { /* user specified redirect code */
  706. sapi_update_response_code(http_response_code);
  707. } else if (SG(request_info).proto_num > 1000 &&
  708. SG(request_info).request_method &&
  709. strcmp(SG(request_info).request_method, "HEAD") &&
  710. strcmp(SG(request_info).request_method, "GET")) {
  711. sapi_update_response_code(303);
  712. } else {
  713. sapi_update_response_code(302);
  714. }
  715. }
  716. } else if (!strcasecmp(header_line, "WWW-Authenticate")) { /* HTTP Authentication */
  717. sapi_update_response_code(401); /* authentication-required */
  718. }
  719. if (sapi_header.header==header_line) {
  720. *colon_offset = ':';
  721. }
  722. }
  723. }
  724. if (http_response_code) {
  725. sapi_update_response_code(http_response_code);
  726. }
  727. sapi_header_add_op(op, &sapi_header);
  728. return SUCCESS;
  729. }
  730. SAPI_API int sapi_send_headers(void)
  731. {
  732. int retval;
  733. int ret = FAILURE;
  734. if (SG(headers_sent) || SG(request_info).no_headers) {
  735. return SUCCESS;
  736. }
  737. /* Success-oriented. We set headers_sent to 1 here to avoid an infinite loop
  738. * in case of an error situation.
  739. */
  740. if (SG(sapi_headers).send_default_content_type && sapi_module.send_headers) {
  741. uint32_t len = 0;
  742. char *default_mimetype = get_default_content_type(0, &len);
  743. if (default_mimetype && len) {
  744. sapi_header_struct default_header;
  745. SG(sapi_headers).mimetype = default_mimetype;
  746. default_header.header_len = sizeof("Content-type: ") - 1 + len;
  747. default_header.header = emalloc(default_header.header_len + 1);
  748. memcpy(default_header.header, "Content-type: ", sizeof("Content-type: ") - 1);
  749. memcpy(default_header.header + sizeof("Content-type: ") - 1, SG(sapi_headers).mimetype, len + 1);
  750. sapi_header_add_op(SAPI_HEADER_ADD, &default_header);
  751. } else {
  752. efree(default_mimetype);
  753. }
  754. SG(sapi_headers).send_default_content_type = 0;
  755. }
  756. if (Z_TYPE(SG(callback_func)) != IS_UNDEF) {
  757. zval cb;
  758. ZVAL_COPY_VALUE(&cb, &SG(callback_func));
  759. ZVAL_UNDEF(&SG(callback_func));
  760. sapi_run_header_callback(&cb);
  761. zval_ptr_dtor(&cb);
  762. }
  763. SG(headers_sent) = 1;
  764. if (sapi_module.send_headers) {
  765. retval = sapi_module.send_headers(&SG(sapi_headers));
  766. } else {
  767. retval = SAPI_HEADER_DO_SEND;
  768. }
  769. switch (retval) {
  770. case SAPI_HEADER_SENT_SUCCESSFULLY:
  771. ret = SUCCESS;
  772. break;
  773. case SAPI_HEADER_DO_SEND: {
  774. sapi_header_struct http_status_line;
  775. char buf[255];
  776. if (SG(sapi_headers).http_status_line) {
  777. http_status_line.header = SG(sapi_headers).http_status_line;
  778. http_status_line.header_len = (uint32_t)strlen(SG(sapi_headers).http_status_line);
  779. } else {
  780. http_status_line.header = buf;
  781. http_status_line.header_len = slprintf(buf, sizeof(buf), "HTTP/1.0 %d X", SG(sapi_headers).http_response_code);
  782. }
  783. sapi_module.send_header(&http_status_line, SG(server_context));
  784. }
  785. zend_llist_apply_with_argument(&SG(sapi_headers).headers, (llist_apply_with_arg_func_t) sapi_module.send_header, SG(server_context));
  786. if(SG(sapi_headers).send_default_content_type) {
  787. sapi_header_struct default_header;
  788. sapi_get_default_content_type_header(&default_header);
  789. sapi_module.send_header(&default_header, SG(server_context));
  790. sapi_free_header(&default_header);
  791. }
  792. sapi_module.send_header(NULL, SG(server_context));
  793. ret = SUCCESS;
  794. break;
  795. case SAPI_HEADER_SEND_FAILED:
  796. SG(headers_sent) = 0;
  797. ret = FAILURE;
  798. break;
  799. }
  800. sapi_send_headers_free();
  801. return ret;
  802. }
  803. SAPI_API int sapi_register_post_entries(const sapi_post_entry *post_entries)
  804. {
  805. const sapi_post_entry *p=post_entries;
  806. while (p->content_type) {
  807. if (sapi_register_post_entry(p) == FAILURE) {
  808. return FAILURE;
  809. }
  810. p++;
  811. }
  812. return SUCCESS;
  813. }
  814. SAPI_API int sapi_register_post_entry(const sapi_post_entry *post_entry)
  815. {
  816. int ret;
  817. zend_string *key;
  818. if (SG(sapi_started) && EG(current_execute_data)) {
  819. return FAILURE;
  820. }
  821. key = zend_string_init(post_entry->content_type, post_entry->content_type_len, 1);
  822. GC_MAKE_PERSISTENT_LOCAL(key);
  823. ret = zend_hash_add_mem(&SG(known_post_content_types), key,
  824. (void *) post_entry, sizeof(sapi_post_entry)) ? SUCCESS : FAILURE;
  825. zend_string_release_ex(key, 1);
  826. return ret;
  827. }
  828. SAPI_API void sapi_unregister_post_entry(const sapi_post_entry *post_entry)
  829. {
  830. if (SG(sapi_started) && EG(current_execute_data)) {
  831. return;
  832. }
  833. zend_hash_str_del(&SG(known_post_content_types), post_entry->content_type,
  834. post_entry->content_type_len);
  835. }
  836. SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(void))
  837. {
  838. if (SG(sapi_started) && EG(current_execute_data)) {
  839. return FAILURE;
  840. }
  841. sapi_module.default_post_reader = default_post_reader;
  842. return SUCCESS;
  843. }
  844. SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray))
  845. {
  846. if (SG(sapi_started) && EG(current_execute_data)) {
  847. return FAILURE;
  848. }
  849. sapi_module.treat_data = treat_data;
  850. return SUCCESS;
  851. }
  852. SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char **val, size_t val_len, size_t *new_val_len), unsigned int (*input_filter_init)(void))
  853. {
  854. if (SG(sapi_started) && EG(current_execute_data)) {
  855. return FAILURE;
  856. }
  857. sapi_module.input_filter = input_filter;
  858. sapi_module.input_filter_init = input_filter_init;
  859. return SUCCESS;
  860. }
  861. SAPI_API int sapi_flush(void)
  862. {
  863. if (sapi_module.flush) {
  864. sapi_module.flush(SG(server_context));
  865. return SUCCESS;
  866. } else {
  867. return FAILURE;
  868. }
  869. }
  870. SAPI_API zend_stat_t *sapi_get_stat(void)
  871. {
  872. if (sapi_module.get_stat) {
  873. return sapi_module.get_stat();
  874. } else {
  875. if (!SG(request_info).path_translated || (VCWD_STAT(SG(request_info).path_translated, &SG(global_stat)) == -1)) {
  876. return NULL;
  877. }
  878. return &SG(global_stat);
  879. }
  880. }
  881. SAPI_API char *sapi_getenv(char *name, size_t name_len)
  882. {
  883. if (!strncasecmp(name, "HTTP_PROXY", name_len)) {
  884. /* Ugly fix for HTTP_PROXY issue, see bug #72573 */
  885. return NULL;
  886. }
  887. if (sapi_module.getenv) {
  888. char *value, *tmp = sapi_module.getenv(name, name_len);
  889. if (tmp) {
  890. value = estrdup(tmp);
  891. #ifdef PHP_WIN32
  892. if (strlen(sapi_module.name) == sizeof("cgi-fcgi") - 1 && !strcmp(sapi_module.name, "cgi-fcgi")) {
  893. /* XXX more modules to go, if needed. */
  894. free(tmp);
  895. }
  896. #endif
  897. } else {
  898. return NULL;
  899. }
  900. if (sapi_module.input_filter) {
  901. sapi_module.input_filter(PARSE_STRING, name, &value, strlen(value), NULL);
  902. }
  903. return value;
  904. }
  905. return NULL;
  906. }
  907. SAPI_API int sapi_get_fd(int *fd)
  908. {
  909. if (sapi_module.get_fd) {
  910. return sapi_module.get_fd(fd);
  911. } else {
  912. return FAILURE;
  913. }
  914. }
  915. SAPI_API int sapi_force_http_10(void)
  916. {
  917. if (sapi_module.force_http_10) {
  918. return sapi_module.force_http_10();
  919. } else {
  920. return FAILURE;
  921. }
  922. }
  923. SAPI_API int sapi_get_target_uid(uid_t *obj)
  924. {
  925. if (sapi_module.get_target_uid) {
  926. return sapi_module.get_target_uid(obj);
  927. } else {
  928. return FAILURE;
  929. }
  930. }
  931. SAPI_API int sapi_get_target_gid(gid_t *obj)
  932. {
  933. if (sapi_module.get_target_gid) {
  934. return sapi_module.get_target_gid(obj);
  935. } else {
  936. return FAILURE;
  937. }
  938. }
  939. SAPI_API double sapi_get_request_time(void)
  940. {
  941. if(SG(global_request_time)) return SG(global_request_time);
  942. if (sapi_module.get_request_time && SG(server_context)) {
  943. SG(global_request_time) = sapi_module.get_request_time();
  944. } else {
  945. struct timeval tp = {0};
  946. if (!gettimeofday(&tp, NULL)) {
  947. SG(global_request_time) = (double)(tp.tv_sec + tp.tv_usec / 1000000.00);
  948. } else {
  949. SG(global_request_time) = (double)time(0);
  950. }
  951. }
  952. return SG(global_request_time);
  953. }
  954. SAPI_API void sapi_terminate_process(void) {
  955. if (sapi_module.terminate_process) {
  956. sapi_module.terminate_process();
  957. }
  958. }
  959. SAPI_API void sapi_add_request_header(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg) /* {{{ */
  960. {
  961. zval *return_value = (zval*)arg;
  962. char *str = NULL;
  963. ALLOCA_FLAG(use_heap)
  964. if (var_len > 5 &&
  965. var[0] == 'H' &&
  966. var[1] == 'T' &&
  967. var[2] == 'T' &&
  968. var[3] == 'P' &&
  969. var[4] == '_') {
  970. char *p;
  971. var_len -= 5;
  972. p = var + 5;
  973. var = str = do_alloca(var_len + 1, use_heap);
  974. *str++ = *p++;
  975. while (*p) {
  976. if (*p == '_') {
  977. *str++ = '-';
  978. p++;
  979. if (*p) {
  980. *str++ = *p++;
  981. }
  982. } else if (*p >= 'A' && *p <= 'Z') {
  983. *str++ = (*p++ - 'A' + 'a');
  984. } else {
  985. *str++ = *p++;
  986. }
  987. }
  988. *str = 0;
  989. } else if (var_len == sizeof("CONTENT_TYPE")-1 &&
  990. memcmp(var, "CONTENT_TYPE", sizeof("CONTENT_TYPE")-1) == 0) {
  991. var = "Content-Type";
  992. } else if (var_len == sizeof("CONTENT_LENGTH")-1 &&
  993. memcmp(var, "CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1) == 0) {
  994. var = "Content-Length";
  995. } else {
  996. return;
  997. }
  998. add_assoc_stringl_ex(return_value, var, var_len, val, val_len);
  999. if (str) {
  1000. free_alloca(var, use_heap);
  1001. }
  1002. }
  1003. /* }}} */
  1004. /*
  1005. * Local variables:
  1006. * tab-width: 4
  1007. * c-basic-offset: 4
  1008. * End:
  1009. * vim600: sw=4 ts=4 fdm=marker
  1010. * vim<600: sw=4 ts=4
  1011. */