1 /* 2 * Copyright (C) Max Romanov 3 * Copyright (C) Valentin V. Bartenev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7 #include "php.h" 8 #include "SAPI.h" 9 #include "php_main.h" 10 #include "php_variables.h" 11 #include "ext/standard/php_standard.h" 12 13 #include <nxt_main.h> 14 #include <nxt_router.h> 15 #include <nxt_unit.h> 16 #include <nxt_unit_request.h> 17 18 19 #if PHP_VERSION_ID >= 50400 20 #define NXT_HAVE_PHP_IGNORE_CWD 1 21 #endif 22 23 #if PHP_VERSION_ID >= 70100 24 #define NXT_HAVE_PHP_LOG_MESSAGE_WITH_SYSLOG_TYPE 1 25 #else 26 #define NXT_HAVE_PHP_INTERRUPTS 1 27 #endif 28 29 #if PHP_VERSION_ID >= 70000 30 #define NXT_PHP7 1 31 #endif 32 #if PHP_VERSION_ID >= 80000 33 #define NXT_PHP8 1 34 #endif 35 36 /* PHP 8 */ 37 #ifndef TSRMLS_CC 38 #define TSRMLS_CC 39 #define TSRMLS_DC 40 #define TSRMLS_D void 41 #define TSRMLS_C 42 #endif 43 44 45 typedef struct { 46 nxt_str_t root; 47 nxt_str_t index; 48 nxt_str_t script_name; 49 nxt_str_t script_dirname; 50 nxt_str_t script_filename; 51 } nxt_php_target_t; 52 53 54 typedef struct { 55 char *cookie; 56 nxt_str_t *root; 57 nxt_str_t *index; 58 nxt_str_t path_info; 59 nxt_str_t script_name; 60 nxt_str_t script_filename; 61 nxt_str_t script_dirname; 62 nxt_unit_request_info_t *req; 63 64 uint8_t chdir; /* 1 bit */ 65 } nxt_php_run_ctx_t; 66 67 68 #if NXT_PHP8 69 typedef int (*nxt_php_disable_t)(const char *p, size_t size); 70 #elif NXT_PHP7 71 typedef int (*nxt_php_disable_t)(char *p, size_t size); 72 #else 73 typedef int (*nxt_php_disable_t)(char *p, uint TSRMLS_DC); 74 #endif 75 76 #if PHP_VERSION_ID < 70200 77 typedef void (*zif_handler)(INTERNAL_FUNCTION_PARAMETERS); 78 #endif 79 80 81 static nxt_int_t nxt_php_setup(nxt_task_t *task, nxt_process_t *process, 82 nxt_common_app_conf_t *conf); 83 static nxt_int_t nxt_php_start(nxt_task_t *task, nxt_process_data_t *data); 84 static nxt_int_t nxt_php_set_target(nxt_task_t *task, nxt_php_target_t *target, 85 nxt_conf_value_t *conf); 86 static nxt_int_t nxt_php_set_ini_path(nxt_task_t *task, nxt_str_t *path, 87 char *workdir); 88 static void nxt_php_set_options(nxt_task_t *task, nxt_conf_value_t *options, 89 int type); 90 static nxt_int_t nxt_php_alter_option(nxt_str_t *name, nxt_str_t *value, 91 int type); 92 #ifdef NXT_PHP8 93 static void nxt_php_disable_functions(nxt_str_t *str); 94 #endif 95 static void nxt_php_disable(nxt_task_t *task, const char *type, 96 nxt_str_t *value, char **ptr, nxt_php_disable_t disable); 97 98 static nxt_int_t nxt_php_dirname(const nxt_str_t *file, nxt_str_t *dir); 99 static void nxt_php_str_trim_trail(nxt_str_t *str, u_char t); 100 static void nxt_php_str_trim_lead(nxt_str_t *str, u_char t); 101 nxt_inline u_char *nxt_realpath(const void *c); 102 103 static void nxt_php_request_handler(nxt_unit_request_info_t *req); 104 static void nxt_php_dynamic_request(nxt_php_run_ctx_t *ctx, 105 nxt_unit_request_t *r); 106 static void nxt_php_execute(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r); 107 nxt_inline void nxt_php_vcwd_chdir(nxt_unit_request_info_t *req, u_char *dir); 108 109 static int nxt_php_startup(sapi_module_struct *sapi_module); 110 static int nxt_php_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC); 111 static void *nxt_php_hash_str_find_ptr(const HashTable *ht, 112 const nxt_str_t *str); 113 static char *nxt_php_read_cookies(TSRMLS_D); 114 static void nxt_php_set_sptr(nxt_unit_request_info_t *req, const char *name, 115 nxt_unit_sptr_t *v, uint32_t len, zval *track_vars_array TSRMLS_DC); 116 nxt_inline void nxt_php_set_str(nxt_unit_request_info_t *req, const char *name, 117 nxt_str_t *s, zval *track_vars_array TSRMLS_DC); 118 static void nxt_php_set_cstr(nxt_unit_request_info_t *req, const char *name, 119 const char *str, uint32_t len, zval *track_vars_array TSRMLS_DC); 120 static void nxt_php_register_variables(zval *track_vars_array TSRMLS_DC); 121 #if NXT_PHP8 122 static void nxt_php_log_message(const char *message, int syslog_type_int); 123 #else 124 #ifdef NXT_HAVE_PHP_LOG_MESSAGE_WITH_SYSLOG_TYPE 125 static void nxt_php_log_message(char *message, int syslog_type_int); 126 #else 127 static void nxt_php_log_message(char *message TSRMLS_DC); 128 #endif 129 #endif 130 131 #ifdef NXT_PHP7 132 static size_t nxt_php_unbuffered_write(const char *str, 133 size_t str_length TSRMLS_DC); 134 static size_t nxt_php_read_post(char *buffer, size_t count_bytes TSRMLS_DC); 135 #else 136 static int nxt_php_unbuffered_write(const char *str, uint str_length TSRMLS_DC); 137 static int nxt_php_read_post(char *buffer, uint count_bytes TSRMLS_DC); 138 #endif 139 140 141 #ifdef NXT_PHP7 142 #if PHP_VERSION_ID < 70200 143 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_fastcgi_finish_request, 0, 0, 144 _IS_BOOL, NULL, 0) 145 #else 146 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_fastcgi_finish_request, 0, 0, 147 _IS_BOOL, 0) 148 #endif 149 #else /* PHP5 */ 150 ZEND_BEGIN_ARG_INFO_EX(arginfo_fastcgi_finish_request, 0, 0, 0) 151 #endif 152 ZEND_END_ARG_INFO() 153 154 ZEND_FUNCTION(fastcgi_finish_request); 155 156 PHP_MINIT_FUNCTION(nxt_php_ext); 157 ZEND_NAMED_FUNCTION(nxt_php_chdir); 158 159 160 static const zend_function_entry nxt_php_ext_functions[] = { 161 ZEND_FE(fastcgi_finish_request, arginfo_fastcgi_finish_request) 162 ZEND_FE_END 163 }; 164 165 166 zif_handler nxt_php_chdir_handler; 167 zend_auto_global *nxt_php_server_ag; 168 169 170 static zend_module_entry nxt_php_unit_module = { 171 STANDARD_MODULE_HEADER, 172 "unit", 173 nxt_php_ext_functions, /* function table */ 174 PHP_MINIT(nxt_php_ext), /* initialization */ 175 NULL, /* shutdown */ 176 NULL, /* request initialization */ 177 NULL, /* request shutdown */ 178 NULL, /* information */ 179 NXT_VERSION, 180 STANDARD_MODULE_PROPERTIES 181 }; 182 183 184 PHP_MINIT_FUNCTION(nxt_php_ext) 185 { 186 zend_function *func; 187 188 static const nxt_str_t chdir = nxt_string("chdir"); 189 190 func = nxt_php_hash_str_find_ptr(CG(function_table), &chdir); 191 if (nxt_slow_path(func == NULL)) { 192 return FAILURE; 193 } 194 195 nxt_php_chdir_handler = func->internal_function.handler; 196 func->internal_function.handler = nxt_php_chdir; 197 198 return SUCCESS; 199 } 200 201 202 ZEND_NAMED_FUNCTION(nxt_php_chdir) 203 { 204 nxt_php_run_ctx_t *ctx; 205 206 ctx = SG(server_context); 207 208 if (nxt_fast_path(ctx != NULL)) { 209 ctx->chdir = 1; 210 } 211 212 nxt_php_chdir_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); 213 } 214 215 216 PHP_FUNCTION(fastcgi_finish_request) 217 { 218 zend_auto_global *ag; 219 nxt_php_run_ctx_t *ctx; 220 221 if (nxt_slow_path(zend_parse_parameters_none() == FAILURE)) { 222 #ifdef NXT_PHP8 223 RETURN_THROWS(); 224 #else 225 return; 226 #endif 227 } 228 229 ctx = SG(server_context); 230 231 if (nxt_slow_path(ctx == NULL || ctx->req == NULL)) { 232 RETURN_FALSE; 233 } 234 235 #ifdef NXT_PHP7 236 php_output_end_all(); 237 php_header(); 238 #else 239 #ifdef PHP_OUTPUT_NEWAPI 240 php_output_end_all(TSRMLS_C); 241 #else 242 php_end_ob_buffers(1 TSRMLS_CC); 243 #endif 244 245 php_header(TSRMLS_C); 246 #endif 247 248 ag = nxt_php_server_ag; 249 250 if (ag->armed) { 251 #ifdef NXT_PHP7 252 ag->armed = ag->auto_global_callback(ag->name); 253 #else 254 ag->armed = ag->auto_global_callback(ag->name, ag->name_len TSRMLS_CC); 255 #endif 256 } 257 258 nxt_unit_request_done(ctx->req, NXT_UNIT_OK); 259 ctx->req = NULL; 260 261 PG(connection_status) = PHP_CONNECTION_ABORTED; 262 #ifdef NXT_PHP7 263 php_output_set_status(PHP_OUTPUT_DISABLED); 264 #else 265 #ifdef PHP_OUTPUT_NEWAPI 266 php_output_set_status(PHP_OUTPUT_DISABLED TSRMLS_CC); 267 #else 268 php_output_set_status(0 TSRMLS_CC); 269 #endif 270 #endif 271 272 RETURN_TRUE; 273 } 274 275 276 static sapi_module_struct nxt_php_sapi_module = 277 { 278 (char *) "cli-server", 279 (char *) "unit", 280 281 nxt_php_startup, /* startup */ 282 php_module_shutdown_wrapper, /* shutdown */ 283 284 NULL, /* activate */ 285 NULL, /* deactivate */ 286 287 nxt_php_unbuffered_write, /* unbuffered write */ 288 NULL, /* flush */ 289 NULL, /* get uid */ 290 NULL, /* getenv */ 291 292 php_error, /* error handler */ 293 294 NULL, /* header handler */ 295 nxt_php_send_headers, /* send headers handler */ 296 NULL, /* send header handler */ 297 298 nxt_php_read_post, /* read POST data */ 299 nxt_php_read_cookies, /* read Cookies */ 300 301 nxt_php_register_variables, /* register server variables */ 302 nxt_php_log_message, /* log message */ 303 NULL, /* get request time */ 304 NULL, /* terminate process */ 305 306 NULL, /* php_ini_path_override */ 307 #ifdef NXT_HAVE_PHP_INTERRUPTS 308 NULL, /* block_interruptions */ 309 NULL, /* unblock_interruptions */ 310 #endif 311 NULL, /* default_post_reader */ 312 NULL, /* treat_data */ 313 NULL, /* executable_location */ 314 315 0, /* php_ini_ignore */ 316 #ifdef NXT_HAVE_PHP_IGNORE_CWD 317 1, /* php_ini_ignore_cwd */ 318 #endif 319 NULL, /* get_fd */ 320 321 NULL, /* force_http_10 */ 322 323 NULL, /* get_target_uid */ 324 NULL, /* get_target_gid */ 325 326 NULL, /* input_filter */ 327 328 NULL, /* ini_defaults */ 329 0, /* phpinfo_as_text */ 330 331 NULL, /* ini_entries */ 332 NULL, /* additional_functions */ 333 NULL /* input_filter_init */ 334 }; 335 336 337 static uint32_t compat[] = { 338 NXT_VERNUM, NXT_DEBUG, 339 }; 340 341 342 NXT_EXPORT nxt_app_module_t nxt_app_module = { 343 sizeof(compat), 344 compat, 345 nxt_string("php"), 346 PHP_VERSION, 347 NULL, 348 0, 349 nxt_php_setup, 350 nxt_php_start, 351 }; 352 353 354 static nxt_php_target_t *nxt_php_targets; 355 static nxt_int_t nxt_php_last_target = -1; 356 357 static nxt_unit_ctx_t *nxt_php_unit_ctx; 358 #if defined(ZTS) && PHP_VERSION_ID < 70400 359 static void ***tsrm_ls; 360 #endif 361 362 363 static nxt_int_t 364 nxt_php_setup(nxt_task_t *task, nxt_process_t *process, 365 nxt_common_app_conf_t *conf) 366 { 367 nxt_str_t ini_path; 368 nxt_int_t ret; 369 nxt_conf_value_t *value; 370 nxt_php_app_conf_t *c; 371 372 static nxt_str_t file_str = nxt_string("file"); 373 static nxt_str_t user_str = nxt_string("user"); 374 static nxt_str_t admin_str = nxt_string("admin"); 375 376 c = &conf->u.php; 377 378 #ifdef ZTS 379 380 #if PHP_VERSION_ID >= 70400 381 php_tsrm_startup(); 382 #else 383 tsrm_startup(1, 1, 0, NULL); 384 tsrm_ls = ts_resource(0); 385 #endif 386 387 #endif 388 389 #if defined(NXT_PHP7) && defined(ZEND_SIGNALS) 390 391 #if (NXT_ZEND_SIGNAL_STARTUP) 392 zend_signal_startup(); 393 #elif defined(ZTS) 394 #error PHP is built with thread safety and broken signals. 395 #endif 396 397 #endif 398 399 sapi_startup(&nxt_php_sapi_module); 400 401 if (c->options != NULL) { 402 value = nxt_conf_get_object_member(c->options, &file_str, NULL); 403 404 if (value != NULL) { 405 nxt_conf_get_string(value, &ini_path); 406 407 ret = nxt_php_set_ini_path(task, &ini_path, 408 conf->working_directory); 409 410 if (nxt_slow_path(ret != NXT_OK)) { 411 return NXT_ERROR; 412 } 413 } 414 } 415 416 if (nxt_slow_path(nxt_php_startup(&nxt_php_sapi_module) == FAILURE)) { 417 nxt_alert(task, "failed to initialize SAPI module and extension"); 418 return NXT_ERROR; 419 } 420 421 if (c->options != NULL) { 422 value = nxt_conf_get_object_member(c->options, &admin_str, NULL); 423 nxt_php_set_options(task, value, ZEND_INI_SYSTEM); 424 425 value = nxt_conf_get_object_member(c->options, &user_str, NULL); 426 nxt_php_set_options(task, value, ZEND_INI_USER); 427 } 428 429 #ifdef NXT_PHP7 430 nxt_php_server_ag = zend_hash_str_find_ptr(CG(auto_globals), "_SERVER", 431 nxt_length("_SERVER")); 432 #else 433 zend_hash_quick_find(CG(auto_globals), "_SERVER", sizeof("_SERVER"), 434 zend_hash_func("_SERVER", sizeof("_SERVER")), 435 (void **) &nxt_php_server_ag); 436 #endif 437 if (nxt_slow_path(nxt_php_server_ag == NULL)) { 438 nxt_alert(task, "failed to find $_SERVER auto global"); 439 return NXT_ERROR; 440 } 441 442 return NXT_OK; 443 } 444 445 446 static nxt_int_t 447 nxt_php_start(nxt_task_t *task, nxt_process_data_t *data) 448 { 449 uint32_t next; 450 nxt_int_t ret; 451 nxt_str_t name; 452 nxt_uint_t n; 453 nxt_unit_ctx_t *unit_ctx; 454 nxt_unit_init_t php_init; 455 nxt_conf_value_t *value; 456 nxt_php_app_conf_t *c; 457 nxt_common_app_conf_t *conf; 458 459 conf = data->app; 460 c = &conf->u.php; 461 462 n = (c->targets != NULL) ? nxt_conf_object_members_count(c->targets) : 1; 463 464 nxt_php_targets = nxt_zalloc(sizeof(nxt_php_target_t) * n); 465 if (nxt_slow_path(nxt_php_targets == NULL)) { 466 return NXT_ERROR; 467 } 468 469 if (c->targets != NULL) { 470 next = 0; 471 472 for (n = 0; /* void */; n++) { 473 value = nxt_conf_next_object_member(c->targets, &name, &next); 474 if (value == NULL) { 475 break; 476 } 477 478 ret = nxt_php_set_target(task, &nxt_php_targets[n], value); 479 if (nxt_slow_path(ret != NXT_OK)) { 480 return NXT_ERROR; 481 } 482 } 483 484 } else { 485 ret = nxt_php_set_target(task, &nxt_php_targets[0], conf->self); 486 if (nxt_slow_path(ret != NXT_OK)) { 487 return NXT_ERROR; 488 } 489 } 490 491 ret = nxt_unit_default_init(task, &php_init, conf); 492 if (nxt_slow_path(ret != NXT_OK)) { 493 nxt_alert(task, "nxt_unit_default_init() failed"); 494 return ret; 495 } 496 497 php_init.callbacks.request_handler = nxt_php_request_handler; 498 499 unit_ctx = nxt_unit_init(&php_init); 500 if (nxt_slow_path(unit_ctx == NULL)) { 501 return NXT_ERROR; 502 } 503 504 nxt_php_unit_ctx = unit_ctx; 505 506 nxt_unit_run(nxt_php_unit_ctx); 507 nxt_unit_done(nxt_php_unit_ctx); 508 509 exit(0); 510 511 return NXT_OK; 512 } 513 514 515 static nxt_int_t 516 nxt_php_set_target(nxt_task_t *task, nxt_php_target_t *target, 517 nxt_conf_value_t *conf) 518 { 519 u_char *tmp, *p; 520 nxt_str_t str; 521 nxt_int_t ret; 522 nxt_conf_value_t *value; 523 524 static nxt_str_t root_str = nxt_string("root"); 525 static nxt_str_t script_str = nxt_string("script"); 526 static nxt_str_t index_str = nxt_string("index"); 527 528 value = nxt_conf_get_object_member(conf, &root_str, NULL); 529 530 nxt_conf_get_string(value, &str); 531 532 tmp = nxt_malloc(str.length + 1); 533 if (nxt_slow_path(tmp == NULL)) { 534 return NXT_ERROR; 535 } 536 537 p = tmp; 538 539 p = nxt_cpymem(p, str.start, str.length); 540 *p = '\0'; 541 542 p = nxt_realpath(tmp); 543 if (nxt_slow_path(p == NULL)) { 544 nxt_alert(task, "root realpath(%s) failed %E", tmp, nxt_errno); 545 return NXT_ERROR; 546 } 547 548 nxt_free(tmp); 549 550 target->root.length = nxt_strlen(p); 551 target->root.start = p; 552 553 nxt_php_str_trim_trail(&target->root, '/'); 554 555 value = nxt_conf_get_object_member(conf, &script_str, NULL); 556 557 if (value != NULL) { 558 nxt_conf_get_string(value, &str); 559 560 nxt_php_str_trim_lead(&str, '/'); 561 562 tmp = nxt_malloc(target->root.length + 1 + str.length + 1); 563 if (nxt_slow_path(tmp == NULL)) { 564 return NXT_ERROR; 565 } 566 567 p = tmp; 568 569 p = nxt_cpymem(p, target->root.start, target->root.length); 570 *p++ = '/'; 571 572 p = nxt_cpymem(p, str.start, str.length); 573 *p = '\0'; 574 575 p = nxt_realpath(tmp); 576 if (nxt_slow_path(p == NULL)) { 577 nxt_alert(task, "script realpath(%s) failed %E", tmp, nxt_errno); 578 return NXT_ERROR; 579 } 580 581 nxt_free(tmp); 582 583 target->script_filename.length = nxt_strlen(p); 584 target->script_filename.start = p; 585 586 if (!nxt_str_start(&target->script_filename, 587 target->root.start, target->root.length)) 588 { 589 nxt_alert(task, "script is not under php root"); 590 return NXT_ERROR; 591 } 592 593 ret = nxt_php_dirname(&target->script_filename, 594 &target->script_dirname); 595 if (nxt_slow_path(ret != NXT_OK)) { 596 return NXT_ERROR; 597 } 598 599 target->script_name.length = target->script_filename.length 600 - target->root.length; 601 target->script_name.start = target->script_filename.start 602 + target->root.length; 603 604 } else { 605 value = nxt_conf_get_object_member(conf, &index_str, NULL); 606 607 if (value != NULL) { 608 nxt_conf_get_string(value, &str); 609 610 tmp = nxt_malloc(str.length); 611 if (nxt_slow_path(tmp == NULL)) { 612 return NXT_ERROR; 613 } 614 615 nxt_memcpy(tmp, str.start, str.length); 616 617 target->index.length = str.length; 618 target->index.start = tmp; 619 620 } else { 621 nxt_str_set(&target->index, "index.php"); 622 } 623 } 624 625 return NXT_OK; 626 } 627 628 629 static nxt_int_t 630 nxt_php_set_ini_path(nxt_task_t *task, nxt_str_t *ini_path, char *workdir) 631 { 632 size_t wdlen; 633 u_char *p, *start; 634 635 if (ini_path->start[0] == '/' || workdir == NULL) { 636 p = nxt_malloc(ini_path->length + 1); 637 if (nxt_slow_path(p == NULL)) { 638 return NXT_ERROR; 639 } 640 641 start = p; 642 643 } else { 644 wdlen = nxt_strlen(workdir); 645 646 p = nxt_malloc(wdlen + ini_path->length + 2); 647 if (nxt_slow_path(p == NULL)) { 648 return NXT_ERROR; 649 } 650 651 start = p; 652 653 p = nxt_cpymem(p, workdir, wdlen); 654 655 if (workdir[wdlen - 1] != '/') { 656 *p++ = '/'; 657 } 658 } 659 660 p = nxt_cpymem(p, ini_path->start, ini_path->length); 661 *p = '\0'; 662 663 nxt_php_sapi_module.php_ini_path_override = (char *) start; 664 665 return NXT_OK; 666 } 667 668 669 static void 670 nxt_php_set_options(nxt_task_t *task, nxt_conf_value_t *options, int type) 671 { 672 uint32_t next; 673 nxt_str_t name, value; 674 nxt_conf_value_t *value_obj; 675 676 if (options != NULL) { 677 next = 0; 678 679 for ( ;; ) { 680 value_obj = nxt_conf_next_object_member(options, &name, &next); 681 if (value_obj == NULL) { 682 break; 683 } 684 685 nxt_conf_get_string(value_obj, &value); 686 687 if (nxt_php_alter_option(&name, &value, type) != NXT_OK) { 688 nxt_log(task, NXT_LOG_ERR, 689 "setting PHP option \"%V: %V\" failed", &name, &value); 690 continue; 691 } 692 693 if (nxt_str_eq(&name, "disable_functions", 17)) { 694 #ifdef NXT_PHP8 695 nxt_php_disable_functions(&value); 696 #else 697 nxt_php_disable(task, "function", &value, 698 &PG(disable_functions), 699 zend_disable_function); 700 #endif 701 continue; 702 } 703 704 if (nxt_str_eq(&name, "disable_classes", 15)) { 705 nxt_php_disable(task, "class", &value, 706 &PG(disable_classes), 707 zend_disable_class); 708 continue; 709 } 710 } 711 } 712 } 713 714 715 #ifdef NXT_PHP7 716 717 static nxt_int_t 718 nxt_php_alter_option(nxt_str_t *name, nxt_str_t *value, int type) 719 { 720 zend_string *zs; 721 zend_ini_entry *ini_entry; 722 723 ini_entry = nxt_php_hash_str_find_ptr(EG(ini_directives), name); 724 if (nxt_slow_path(ini_entry == NULL)) { 725 return NXT_ERROR; 726 } 727 728 /* PHP exits on memory allocation errors. */ 729 zs = zend_string_init((char *) value->start, value->length, 1); 730 731 if (ini_entry->on_modify 732 && ini_entry->on_modify(ini_entry, zs, ini_entry->mh_arg1, 733 ini_entry->mh_arg2, ini_entry->mh_arg3, 734 ZEND_INI_STAGE_ACTIVATE) 735 != SUCCESS) 736 { 737 zend_string_release(zs); 738 return NXT_ERROR; 739 } 740 741 ini_entry->value = zs; 742 ini_entry->modifiable = type; 743 744 return NXT_OK; 745 } 746 747 #else /* PHP 5. */ 748 749 static nxt_int_t 750 nxt_php_alter_option(nxt_str_t *name, nxt_str_t *value, int type) 751 { 752 char *cstr; 753 zend_ini_entry *ini_entry; 754 755 ini_entry = nxt_php_hash_str_find_ptr(EG(ini_directives), name); 756 if (nxt_slow_path(ini_entry == NULL)) { 757 return NXT_ERROR; 758 } 759 760 cstr = nxt_malloc(value->length + 1); 761 if (nxt_slow_path(cstr == NULL)) { 762 return NXT_ERROR; 763 } 764 765 nxt_memcpy(cstr, value->start, value->length); 766 cstr[value->length] = '\0'; 767 768 if (ini_entry->on_modify 769 && ini_entry->on_modify(ini_entry, cstr, value->length, 770 ini_entry->mh_arg1, ini_entry->mh_arg2, 771 ini_entry->mh_arg3, ZEND_INI_STAGE_ACTIVATE 772 TSRMLS_CC) 773 != SUCCESS) 774 { 775 nxt_free(cstr); 776 return NXT_ERROR; 777 } 778 779 ini_entry->value = cstr; 780 ini_entry->value_length = value->length; 781 ini_entry->modifiable = type; 782 783 return NXT_OK; 784 } 785 786 #endif 787 788 789 #ifdef NXT_PHP8 790 791 static void 792 nxt_php_disable_functions(nxt_str_t *str) 793 { 794 char *p; 795 796 p = nxt_malloc(str->length + 1); 797 if (nxt_slow_path(p == NULL)) { 798 return; 799 } 800 801 nxt_memcpy(p, str->start, str->length); 802 p[str->length] = '\0'; 803 804 zend_disable_functions(p); 805 806 nxt_free(p); 807 } 808 809 #endif 810 811 812 static void 813 nxt_php_disable(nxt_task_t *task, const char *type, nxt_str_t *value, 814 char **ptr, nxt_php_disable_t disable) 815 { 816 char c, *p, *start; 817 818 p = nxt_malloc(value->length + 1); 819 if (nxt_slow_path(p == NULL)) { 820 return; 821 } 822 823 /* 824 * PHP frees this memory on module shutdown. 825 * See core_globals_dtor() for details. 826 */ 827 *ptr = p; 828 829 nxt_memcpy(p, value->start, value->length); 830 p[value->length] = '\0'; 831 832 start = p; 833 834 do { 835 c = *p; 836 837 if (c == ' ' || c == ',' || c == '\0') { 838 839 if (p != start) { 840 *p = '\0'; 841 842 #ifdef NXT_PHP7 843 if (disable(start, p - start) 844 #else 845 if (disable(start, p - start TSRMLS_CC) 846 #endif 847 != SUCCESS) 848 { 849 nxt_log(task, NXT_LOG_ERR, 850 "PHP: failed to disable \"%s\": no such %s", 851 start, type); 852 } 853 } 854 855 start = p + 1; 856 } 857 858 p++; 859 860 } while (c != '\0'); 861 } 862 863 864 static nxt_int_t 865 nxt_php_dirname(const nxt_str_t *file, nxt_str_t *dir) 866 { 867 size_t length; 868 869 if (file->length == 0 || file->start[0] != '/') { 870 nxt_unit_alert(NULL, "php_dirname: invalid file name " 871 "(not starts from '/')"); 872 return NXT_ERROR; 873 } 874 875 length = file->length; 876 877 while (file->start[length - 1] != '/') { 878 length--; 879 } 880 881 dir->length = length; 882 dir->start = nxt_malloc(length + 1); 883 if (nxt_slow_path(dir->start == NULL)) { 884 return NXT_ERROR; 885 } 886 887 nxt_memcpy(dir->start, file->start, length); 888 889 dir->start[length] = '\0'; 890 891 return NXT_OK; 892 } 893 894 895 static void 896 nxt_php_str_trim_trail(nxt_str_t *str, u_char t) 897 { 898 while (str->length > 0 && str->start[str->length - 1] == t) { 899 str->length--; 900 } 901 902 str->start[str->length] = '\0'; 903 } 904 905 906 static void 907 nxt_php_str_trim_lead(nxt_str_t *str, u_char t) 908 { 909 while (str->length > 0 && str->start[0] == t) { 910 str->length--; 911 str->start++; 912 } 913 } 914 915 916 nxt_inline u_char * 917 nxt_realpath(const void *c) 918 { 919 return (u_char *) realpath(c, NULL); 920 } 921 922 923 static void 924 nxt_php_request_handler(nxt_unit_request_info_t *req) 925 { 926 nxt_php_target_t *target; 927 nxt_php_run_ctx_t ctx; 928 nxt_unit_request_t *r; 929 930 r = req->request; 931 target = &nxt_php_targets[r->app_target]; 932 933 nxt_memzero(&ctx, sizeof(ctx)); 934 935 ctx.req = req; 936 ctx.root = &target->root; 937 ctx.index = &target->index; 938 939 if (target->script_filename.length == 0) { 940 nxt_php_dynamic_request(&ctx, r); 941 return; 942 } 943 944 ctx.script_filename = target->script_filename; 945 ctx.script_dirname = target->script_dirname; 946 ctx.script_name = target->script_name; 947 948 ctx.chdir = (r->app_target != nxt_php_last_target); 949 950 nxt_php_execute(&ctx, r); 951 952 nxt_php_last_target = ctx.chdir ? -1 : r->app_target; 953 } 954 955 956 static void 957 nxt_php_dynamic_request(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r) 958 { 959 u_char *p; 960 nxt_str_t path, script_name; 961 nxt_int_t ret; 962 963 path.length = r->path_length; 964 path.start = nxt_unit_sptr_get(&r->path); 965 966 nxt_str_null(&script_name); 967 968 ctx->path_info.start = (u_char *) strstr((char *) path.start, ".php/"); 969 if (ctx->path_info.start != NULL) { 970 ctx->path_info.start += 4; 971 path.length = ctx->path_info.start - path.start; 972 973 ctx->path_info.length = r->path_length - path.length; 974 975 } else if (path.start[path.length - 1] == '/') { 976 script_name = *ctx->index; 977 978 } else { 979 if (nxt_slow_path(path.length < 4 980 || nxt_memcmp(path.start + (path.length - 4), 981 ".php", 4))) 982 { 983 nxt_unit_request_done(ctx->req, NXT_UNIT_ERROR); 984 985 return; 986 } 987 } 988 989 ctx->script_filename.length = ctx->root->length 990 + path.length 991 + script_name.length; 992 993 p = nxt_malloc(ctx->script_filename.length + 1); 994 if (nxt_slow_path(p == NULL)) { 995 nxt_unit_request_done(ctx->req, NXT_UNIT_ERROR); 996 997 return; 998 } 999 1000 ctx->script_filename.start = p; 1001 1002 ctx->script_name.length = path.length + script_name.length; 1003 ctx->script_name.start = p + ctx->root->length; 1004 1005 p = nxt_cpymem(p, ctx->root->start, ctx->root->length); 1006 p = nxt_cpymem(p, path.start, path.length); 1007 1008 if (script_name.length > 0) { 1009 p = nxt_cpymem(p, script_name.start, script_name.length); 1010 } 1011 1012 *p = '\0'; 1013 1014 ctx->chdir = 1; 1015 1016 ret = nxt_php_dirname(&ctx->script_filename, &ctx->script_dirname); 1017 if (nxt_slow_path(ret != NXT_OK)) { 1018 nxt_unit_request_done(ctx->req, NXT_UNIT_ERROR); 1019 nxt_free(ctx->script_filename.start); 1020 1021 return; 1022 } 1023 1024 nxt_php_execute(ctx, r); 1025 1026 nxt_free(ctx->script_filename.start); 1027 nxt_free(ctx->script_dirname.start); 1028 1029 nxt_php_last_target = -1; 1030 } 1031 1032 1033 static void 1034 nxt_php_execute(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r) 1035 { 1036 #if (PHP_VERSION_ID < 50600) 1037 void *read_post; 1038 #endif 1039 nxt_unit_field_t *f; 1040 zend_file_handle file_handle; 1041 1042 nxt_unit_req_debug(ctx->req, "PHP execute script %s", 1043 ctx->script_filename.start); 1044 1045 SG(server_context) = ctx; 1046 SG(options) |= SAPI_OPTION_NO_CHDIR; 1047 SG(request_info).request_uri = nxt_unit_sptr_get(&r->target); 1048 SG(request_info).request_method = nxt_unit_sptr_get(&r->method); 1049 1050 SG(request_info).proto_num = 1001; 1051 1052 SG(request_info).query_string = r->query.offset 1053 ? nxt_unit_sptr_get(&r->query) : NULL; 1054 SG(request_info).content_length = r->content_length; 1055 1056 if (r->content_type_field != NXT_UNIT_NONE_FIELD) { 1057 f = r->fields + r->content_type_field; 1058 1059 SG(request_info).content_type = nxt_unit_sptr_get(&f->value); 1060 } 1061 1062 if (r->cookie_field != NXT_UNIT_NONE_FIELD) { 1063 f = r->fields + r->cookie_field; 1064 1065 ctx->cookie = nxt_unit_sptr_get(&f->value); 1066 } 1067 1068 if (r->authorization_field != NXT_UNIT_NONE_FIELD) { 1069 f = r->fields + r->authorization_field; 1070 1071 #ifdef NXT_PHP7 1072 php_handle_auth_data(nxt_unit_sptr_get(&f->value)); 1073 #else 1074 php_handle_auth_data(nxt_unit_sptr_get(&f->value) TSRMLS_CC); 1075 #endif 1076 1077 } else { 1078 SG(request_info).auth_digest = NULL; 1079 SG(request_info).auth_user = NULL; 1080 SG(request_info).auth_password = NULL; 1081 } 1082 1083 SG(sapi_headers).http_response_code = 200; 1084 1085 SG(request_info).path_translated = NULL; 1086 1087 #ifdef NXT_PHP7 1088 if (nxt_slow_path(php_request_startup() == FAILURE)) { 1089 #else 1090 if (nxt_slow_path(php_request_startup(TSRMLS_C) == FAILURE)) { 1091 #endif 1092 nxt_unit_req_debug(ctx->req, "php_request_startup() failed"); 1093 1094 nxt_unit_request_done(ctx->req, NXT_UNIT_ERROR); 1095 return; 1096 } 1097 1098 if (ctx->chdir) { 1099 ctx->chdir = 0; 1100 nxt_php_vcwd_chdir(ctx->req, ctx->script_dirname.start); 1101 } 1102 1103 nxt_memzero(&file_handle, sizeof(file_handle)); 1104 1105 file_handle.type = ZEND_HANDLE_FILENAME; 1106 #if (PHP_VERSION_ID >= 80100) 1107 file_handle.filename = zend_string_init((char *) ctx->script_filename.start, 1108 ctx->script_filename.length, 0); 1109 file_handle.primary_script = 1; 1110 #else 1111 file_handle.filename = (char *) ctx->script_filename.start; 1112 #endif 1113 1114 php_execute_script(&file_handle TSRMLS_CC); 1115 1116 #if (PHP_VERSION_ID >= 80100) 1117 zend_destroy_file_handle(&file_handle); 1118 #endif 1119 1120 /* Prevention of consuming possible unread request body. */ 1121 #if (PHP_VERSION_ID < 50600) 1122 read_post = sapi_module.read_post; 1123 sapi_module.read_post = NULL; 1124 #else 1125 SG(post_read) = 1; 1126 #endif 1127 1128 php_request_shutdown(NULL); 1129 1130 if (ctx->req != NULL) { 1131 nxt_unit_request_done(ctx->req, NXT_UNIT_OK); 1132 } 1133 1134 #if (PHP_VERSION_ID < 50600) 1135 sapi_module.read_post = read_post; 1136 #endif 1137 } 1138 1139 1140 nxt_inline void 1141 nxt_php_vcwd_chdir(nxt_unit_request_info_t *req, u_char *dir) 1142 { 1143 if (nxt_slow_path(VCWD_CHDIR((char *) dir) != 0)) { 1144 nxt_unit_req_alert(req, "VCWD_CHDIR(%s) failed (%d: %s)", 1145 dir, errno, strerror(errno)); 1146 } 1147 } 1148 1149 1150 static int 1151 nxt_php_startup(sapi_module_struct *sapi_module) 1152 { 1153 #if (PHP_VERSION_ID < 80200) 1154 return php_module_startup(sapi_module, &nxt_php_unit_module, 1); 1155 #else 1156 return php_module_startup(sapi_module, &nxt_php_unit_module); 1157 #endif 1158 } 1159 1160 1161 #ifdef NXT_PHP7 1162 static size_t 1163 nxt_php_unbuffered_write(const char *str, size_t str_length TSRMLS_DC) 1164 #else 1165 static int 1166 nxt_php_unbuffered_write(const char *str, uint str_length TSRMLS_DC) 1167 #endif 1168 { 1169 int rc; 1170 nxt_php_run_ctx_t *ctx; 1171 1172 ctx = SG(server_context); 1173 1174 rc = nxt_unit_response_write(ctx->req, str, str_length); 1175 if (nxt_fast_path(rc == NXT_UNIT_OK)) { 1176 return str_length; 1177 } 1178 1179 php_handle_aborted_connection(); 1180 return 0; 1181 } 1182 1183 1184 static int 1185 nxt_php_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) 1186 { 1187 int rc, fields_count; 1188 char *colon, *value; 1189 uint16_t status; 1190 uint32_t resp_size; 1191 nxt_php_run_ctx_t *ctx; 1192 sapi_header_struct *h; 1193 zend_llist_position zpos; 1194 nxt_unit_request_info_t *req; 1195 1196 ctx = SG(server_context); 1197 req = ctx->req; 1198 1199 nxt_unit_req_debug(req, "nxt_php_send_headers"); 1200 1201 if (SG(request_info).no_headers == 1) { 1202 rc = nxt_unit_response_init(req, 200, 0, 0); 1203 if (nxt_slow_path(rc != NXT_UNIT_OK)) { 1204 return SAPI_HEADER_SEND_FAILED; 1205 } 1206 1207 return SAPI_HEADER_SENT_SUCCESSFULLY; 1208 } 1209 1210 resp_size = 0; 1211 fields_count = zend_llist_count(&sapi_headers->headers); 1212 1213 for (h = zend_llist_get_first_ex(&sapi_headers->headers, &zpos); 1214 h; 1215 h = zend_llist_get_next_ex(&sapi_headers->headers, &zpos)) 1216 { 1217 resp_size += h->header_len; 1218 } 1219 1220 status = SG(sapi_headers).http_response_code; 1221 1222 rc = nxt_unit_response_init(req, status, fields_count, resp_size); 1223 if (nxt_slow_path(rc != NXT_UNIT_OK)) { 1224 return SAPI_HEADER_SEND_FAILED; 1225 } 1226 1227 for (h = zend_llist_get_first_ex(&sapi_headers->headers, &zpos); 1228 h; 1229 h = zend_llist_get_next_ex(&sapi_headers->headers, &zpos)) 1230 { 1231 colon = memchr(h->header, ':', h->header_len); 1232 if (nxt_slow_path(colon == NULL)) { 1233 nxt_unit_req_warn(req, "colon not found in header '%.*s'", 1234 (int) h->header_len, h->header); 1235 continue; 1236 } 1237 1238 value = colon + 1; 1239 while(isspace(*value)) { 1240 value++; 1241 } 1242 1243 nxt_unit_response_add_field(req, h->header, colon - h->header, 1244 value, 1245 h->header_len - (value - h->header)); 1246 } 1247 1248 rc = nxt_unit_response_send(req); 1249 if (nxt_slow_path(rc != NXT_UNIT_OK)) { 1250 nxt_unit_req_debug(req, "failed to send response"); 1251 1252 return SAPI_HEADER_SEND_FAILED; 1253 } 1254 1255 return SAPI_HEADER_SENT_SUCCESSFULLY; 1256 } 1257 1258 1259 #ifdef NXT_PHP7 1260 static size_t 1261 nxt_php_read_post(char *buffer, size_t count_bytes TSRMLS_DC) 1262 #else 1263 static int 1264 nxt_php_read_post(char *buffer, uint count_bytes TSRMLS_DC) 1265 #endif 1266 { 1267 nxt_php_run_ctx_t *ctx; 1268 1269 ctx = SG(server_context); 1270 1271 nxt_unit_req_debug(ctx->req, "nxt_php_read_post %d", (int) count_bytes); 1272 1273 return nxt_unit_request_read(ctx->req, buffer, count_bytes); 1274 } 1275 1276 1277 static char * 1278 nxt_php_read_cookies(TSRMLS_D) 1279 { 1280 nxt_php_run_ctx_t *ctx; 1281 1282 ctx = SG(server_context); 1283 1284 nxt_unit_req_debug(ctx->req, "nxt_php_read_cookies"); 1285 1286 return ctx->cookie; 1287 } 1288 1289 1290 static void 1291 nxt_php_register_variables(zval *track_vars_array TSRMLS_DC) 1292 { 1293 const char *name; 1294 nxt_unit_field_t *f, *f_end; 1295 nxt_php_run_ctx_t *ctx; 1296 nxt_unit_request_t *r; 1297 nxt_unit_request_info_t *req; 1298 1299 ctx = SG(server_context); 1300 1301 req = ctx->req; 1302 r = req->request; 1303 1304 nxt_unit_req_debug(req, "nxt_php_register_variables"); 1305 1306 php_register_variable_safe((char *) "SERVER_SOFTWARE", 1307 (char *) nxt_server.start, 1308 nxt_server.length, track_vars_array TSRMLS_CC); 1309 1310 nxt_php_set_sptr(req, "SERVER_PROTOCOL", &r->version, r->version_length, 1311 track_vars_array TSRMLS_CC); 1312 1313 /* 1314 * 'PHP_SELF' 1315 * The filename of the currently executing script, relative to the document 1316 * root. For instance, $_SERVER['PHP_SELF'] in a script at the address 1317 * http://example.com/foo/bar.php would be /foo/bar.php. The __FILE__ 1318 * constant contains the full path and filename of the current (i.e. 1319 * included) file. If PHP is running as a command-line processor this 1320 * variable contains the script name since PHP 4.3.0. Previously it was not 1321 * available. 1322 */ 1323 1324 if (ctx->path_info.length != 0) { 1325 nxt_php_set_sptr(req, "PHP_SELF", &r->path, r->path_length, 1326 track_vars_array TSRMLS_CC); 1327 1328 nxt_php_set_str(req, "PATH_INFO", &ctx->path_info, 1329 track_vars_array TSRMLS_CC); 1330 1331 } else { 1332 nxt_php_set_str(req, "PHP_SELF", &ctx->script_name, 1333 track_vars_array TSRMLS_CC); 1334 } 1335 1336 /* 1337 * 'SCRIPT_NAME' 1338 * Contains the current script's path. This is useful for pages which need 1339 * to point to themselves. The __FILE__ constant contains the full path and 1340 * filename of the current (i.e. included) file. 1341 */ 1342 1343 nxt_php_set_str(req, "SCRIPT_NAME", &ctx->script_name, 1344 track_vars_array TSRMLS_CC); 1345 1346 /* 1347 * 'SCRIPT_FILENAME' 1348 * The absolute pathname of the currently executing script. 1349 */ 1350 1351 nxt_php_set_str(req, "SCRIPT_FILENAME", &ctx->script_filename, 1352 track_vars_array TSRMLS_CC); 1353 1354 /* 1355 * 'DOCUMENT_ROOT' 1356 * The document root directory under which the current script is executing, 1357 * as defined in the server's configuration file. 1358 */ 1359 1360 nxt_php_set_str(req, "DOCUMENT_ROOT", ctx->root, 1361 track_vars_array TSRMLS_CC); 1362 1363 nxt_php_set_sptr(req, "REQUEST_METHOD", &r->method, r->method_length, 1364 track_vars_array TSRMLS_CC); 1365 nxt_php_set_sptr(req, "REQUEST_URI", &r->target, r->target_length, 1366 track_vars_array TSRMLS_CC); 1367 nxt_php_set_sptr(req, "QUERY_STRING", &r->query, r->query_length, 1368 track_vars_array TSRMLS_CC); 1369 1370 nxt_php_set_sptr(req, "REMOTE_ADDR", &r->remote, r->remote_length, 1371 track_vars_array TSRMLS_CC); 1372 nxt_php_set_sptr(req, "SERVER_ADDR", &r->local_addr, r->local_addr_length, 1373 track_vars_array TSRMLS_CC); 1374 1375 nxt_php_set_sptr(req, "SERVER_NAME", &r->server_name, r->server_name_length, 1376 track_vars_array TSRMLS_CC); 1377 nxt_php_set_cstr(req, "SERVER_PORT", "80", 2, track_vars_array TSRMLS_CC); 1378 1379 if (r->tls) { 1380 nxt_php_set_cstr(req, "HTTPS", "on", 2, track_vars_array TSRMLS_CC); 1381 } 1382 1383 f_end = r->fields + r->fields_count; 1384 for (f = r->fields; f < f_end; f++) { 1385 name = nxt_unit_sptr_get(&f->name); 1386 1387 nxt_php_set_sptr(req, name, &f->value, f->value_length, 1388 track_vars_array TSRMLS_CC); 1389 } 1390 1391 if (r->content_length_field != NXT_UNIT_NONE_FIELD) { 1392 f = r->fields + r->content_length_field; 1393 1394 nxt_php_set_sptr(req, "CONTENT_LENGTH", &f->value, f->value_length, 1395 track_vars_array TSRMLS_CC); 1396 } 1397 1398 if (r->content_type_field != NXT_UNIT_NONE_FIELD) { 1399 f = r->fields + r->content_type_field; 1400 1401 nxt_php_set_sptr(req, "CONTENT_TYPE", &f->value, f->value_length, 1402 track_vars_array TSRMLS_CC); 1403 } 1404 } 1405 1406 1407 static void 1408 nxt_php_set_sptr(nxt_unit_request_info_t *req, const char *name, 1409 nxt_unit_sptr_t *v, uint32_t len, zval *track_vars_array TSRMLS_DC) 1410 { 1411 char *str; 1412 1413 str = nxt_unit_sptr_get(v); 1414 1415 nxt_unit_req_debug(req, "php: register %s='%.*s'", name, (int) len, str); 1416 1417 php_register_variable_safe((char *) name, str, len, 1418 track_vars_array TSRMLS_CC); 1419 } 1420 1421 1422 nxt_inline void 1423 nxt_php_set_str(nxt_unit_request_info_t *req, const char *name, 1424 nxt_str_t *s, zval *track_vars_array TSRMLS_DC) 1425 { 1426 nxt_php_set_cstr(req, name, (char *) s->start, s->length, 1427 track_vars_array TSRMLS_CC); 1428 } 1429 1430 1431 #ifdef NXT_PHP7 1432 1433 static void * 1434 nxt_php_hash_str_find_ptr(const HashTable *ht, const nxt_str_t *str) 1435 { 1436 return zend_hash_str_find_ptr(ht, (const char *) str->start, str->length); 1437 } 1438 1439 #else 1440 1441 static void * 1442 nxt_php_hash_str_find_ptr(const HashTable *ht, const nxt_str_t *str) 1443 { 1444 int ret; 1445 void *entry; 1446 char buf[256]; 1447 1448 if (nxt_slow_path(str->length >= (sizeof(buf) - 1))) { 1449 return NULL; 1450 } 1451 1452 nxt_memcpy(buf, str->start, str->length); 1453 buf[str->length] = '\0'; 1454 1455 ret = zend_hash_find(ht, buf, str->length + 1, &entry); 1456 if (nxt_fast_path(ret == SUCCESS)) { 1457 return entry; 1458 } 1459 1460 return NULL; 1461 } 1462 1463 #endif 1464 1465 1466 static void 1467 nxt_php_set_cstr(nxt_unit_request_info_t *req, const char *name, 1468 const char *cstr, uint32_t len, zval *track_vars_array TSRMLS_DC) 1469 { 1470 if (nxt_slow_path(cstr == NULL)) { 1471 return; 1472 } 1473 1474 nxt_unit_req_debug(req, "php: register %s='%.*s'", name, (int) len, cstr); 1475 1476 php_register_variable_safe((char *) name, (char *) cstr, len, 1477 track_vars_array TSRMLS_CC); 1478 } 1479 1480 1481 #if NXT_PHP8 1482 static void 1483 nxt_php_log_message(const char *message, int syslog_type_int) 1484 #else 1485 #ifdef NXT_HAVE_PHP_LOG_MESSAGE_WITH_SYSLOG_TYPE 1486 static void 1487 nxt_php_log_message(char *message, int syslog_type_int) 1488 #else 1489 static void 1490 nxt_php_log_message(char *message TSRMLS_DC) 1491 #endif 1492 #endif 1493 { 1494 nxt_php_run_ctx_t *ctx; 1495 1496 ctx = SG(server_context); 1497 1498 if (ctx != NULL) { 1499 nxt_unit_req_log(ctx->req, NXT_UNIT_LOG_NOTICE, 1500 "php message: %s", message); 1501 1502 } else { 1503 nxt_unit_log(nxt_php_unit_ctx, NXT_UNIT_LOG_NOTICE, 1504 "php message: %s", message); 1505 } 1506 } 1507