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 12 #include <nxt_main.h> 13 #include <nxt_router.h> 14 #include <nxt_unit.h> 15 #include <nxt_unit_request.h> 16 17 18 typedef struct nxt_php_run_ctx_s nxt_php_run_ctx_t; 19 20 static nxt_int_t nxt_php_init(nxt_task_t *task, nxt_common_app_conf_t *conf); 21 22 static void nxt_php_str_trim_trail(nxt_str_t *str, u_char t); 23 static void nxt_php_str_trim_lead(nxt_str_t *str, u_char t); 24 nxt_inline u_char *nxt_realpath(const void *c); 25 26 static void nxt_php_request_handler(nxt_unit_request_info_t *req); 27 28 #if PHP_MAJOR_VERSION >= 7 29 # define NXT_PHP7 1 30 # if PHP_MINOR_VERSION >= 1 31 # define NXT_HAVE_PHP_LOG_MESSAGE_WITH_SYSLOG_TYPE 1 32 # else 33 # define NXT_HAVE_PHP_INTERRUPTS 1 34 # endif 35 # define NXT_HAVE_PHP_IGNORE_CWD 1 36 #else 37 # define NXT_HAVE_PHP_INTERRUPTS 1 38 # if PHP_MINOR_VERSION >= 4 39 # define NXT_HAVE_PHP_IGNORE_CWD 1 40 # endif 41 #endif 42 43 static int nxt_php_startup(sapi_module_struct *sapi_module); 44 static void nxt_php_set_options(nxt_task_t *task, nxt_conf_value_t *options, 45 int type); 46 static nxt_int_t nxt_php_alter_option(nxt_str_t *name, nxt_str_t *value, 47 int type); 48 static int nxt_php_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC); 49 static char *nxt_php_read_cookies(TSRMLS_D); 50 static void nxt_php_set_sptr(nxt_unit_request_info_t *req, const char *name, 51 nxt_unit_sptr_t *v, uint32_t len, zval *track_vars_array TSRMLS_DC); 52 nxt_inline void nxt_php_set_str(nxt_unit_request_info_t *req, const char *name, 53 nxt_str_t *s, zval *track_vars_array TSRMLS_DC); 54 static void nxt_php_set_cstr(nxt_unit_request_info_t *req, const char *name, 55 char *str, uint32_t len, zval *track_vars_array TSRMLS_DC); 56 static void nxt_php_register_variables(zval *track_vars_array TSRMLS_DC); 57 #ifdef NXT_HAVE_PHP_LOG_MESSAGE_WITH_SYSLOG_TYPE 58 static void nxt_php_log_message(char *message, int syslog_type_int); 59 #else 60 static void nxt_php_log_message(char *message TSRMLS_DC); 61 #endif 62 63 #ifdef NXT_PHP7 64 static size_t nxt_php_unbuffered_write(const char *str, 65 size_t str_length TSRMLS_DC); 66 static size_t nxt_php_read_post(char *buffer, size_t count_bytes TSRMLS_DC); 67 #else 68 static int nxt_php_unbuffered_write(const char *str, uint str_length TSRMLS_DC); 69 static int nxt_php_read_post(char *buffer, uint count_bytes TSRMLS_DC); 70 #endif 71 72 73 static sapi_module_struct nxt_php_sapi_module = 74 { 75 (char *) "cli-server", 76 (char *) "unit", 77 78 nxt_php_startup, /* startup */ 79 php_module_shutdown_wrapper, /* shutdown */ 80 81 NULL, /* activate */ 82 NULL, /* deactivate */ 83 84 nxt_php_unbuffered_write, /* unbuffered write */ 85 NULL, /* flush */ 86 NULL, /* get uid */ 87 NULL, /* getenv */ 88 89 php_error, /* error handler */ 90 91 NULL, /* header handler */ 92 nxt_php_send_headers, /* send headers handler */ 93 NULL, /* send header handler */ 94 95 nxt_php_read_post, /* read POST data */ 96 nxt_php_read_cookies, /* read Cookies */ 97 98 nxt_php_register_variables, /* register server variables */ 99 nxt_php_log_message, /* log message */ 100 NULL, /* get request time */ 101 NULL, /* terminate process */ 102 103 NULL, /* php_ini_path_override */ 104 #ifdef NXT_HAVE_PHP_INTERRUPTS 105 NULL, /* block_interruptions */ 106 NULL, /* unblock_interruptions */ 107 #endif 108 NULL, /* default_post_reader */ 109 NULL, /* treat_data */ 110 NULL, /* executable_location */ 111 112 0, /* php_ini_ignore */ 113 #ifdef NXT_HAVE_PHP_IGNORE_CWD 114 1, /* php_ini_ignore_cwd */ 115 #endif 116 NULL, /* get_fd */ 117 118 NULL, /* force_http_10 */ 119 120 NULL, /* get_target_uid */ 121 NULL, /* get_target_gid */ 122 123 NULL, /* input_filter */ 124 125 NULL, /* ini_defaults */ 126 0, /* phpinfo_as_text */ 127 128 NULL, /* ini_entries */ 129 NULL, /* additional_functions */ 130 NULL /* input_filter_init */ 131 }; 132 133 134 struct nxt_php_run_ctx_s { 135 char *cookie; 136 nxt_str_t script; 137 nxt_unit_request_info_t *req; 138 }; 139 140 141 static nxt_str_t nxt_php_path; 142 static nxt_str_t nxt_php_root; 143 static nxt_str_t nxt_php_script; 144 static nxt_str_t nxt_php_index = nxt_string("index.php"); 145 146 147 static uint32_t compat[] = { 148 NXT_VERNUM, NXT_DEBUG, 149 }; 150 151 152 NXT_EXPORT nxt_app_module_t nxt_app_module = { 153 sizeof(compat), 154 compat, 155 nxt_string("php"), 156 PHP_VERSION, 157 nxt_php_init, 158 }; 159 160 161 static nxt_task_t *nxt_php_task; 162 #ifdef ZTS 163 static void ***tsrm_ls; 164 #endif 165 166 167 static nxt_int_t 168 nxt_php_init(nxt_task_t *task, nxt_common_app_conf_t *conf) 169 { 170 u_char *p; 171 nxt_str_t rpath, ini_path; 172 nxt_str_t *root, *path, *script, *index; 173 nxt_port_t *my_port, *main_port; 174 nxt_runtime_t *rt; 175 nxt_unit_ctx_t *unit_ctx; 176 nxt_unit_init_t php_init; 177 nxt_conf_value_t *value; 178 nxt_php_app_conf_t *c; 179 180 static nxt_str_t file_str = nxt_string("file"); 181 static nxt_str_t user_str = nxt_string("user"); 182 static nxt_str_t admin_str = nxt_string("admin"); 183 184 nxt_php_task = task; 185 186 c = &conf->u.php; 187 188 if (c->root == NULL) { 189 nxt_alert(task, "php root is empty"); 190 return NXT_ERROR; 191 } 192 193 root = &nxt_php_root; 194 path = &nxt_php_path; 195 script = &nxt_php_script; 196 index = &nxt_php_index; 197 198 root->start = nxt_realpath(c->root); 199 if (nxt_slow_path(root->start == NULL)) { 200 nxt_alert(task, "root realpath(%s) failed %E", c->root, nxt_errno); 201 return NXT_ERROR; 202 } 203 204 root->length = nxt_strlen(root->start); 205 206 nxt_php_str_trim_trail(root, '/'); 207 208 if (c->script.length > 0) { 209 nxt_php_str_trim_lead(&c->script, '/'); 210 211 path->length = root->length + 1 + c->script.length; 212 path->start = nxt_malloc(path->length + 1); 213 if (nxt_slow_path(path->start == NULL)) { 214 return NXT_ERROR; 215 } 216 217 p = nxt_cpymem(path->start, root->start, root->length); 218 *p++ = '/'; 219 220 p = nxt_cpymem(p, c->script.start, c->script.length); 221 *p = '\0'; 222 223 rpath.start = nxt_realpath(path->start); 224 if (nxt_slow_path(rpath.start == NULL)) { 225 nxt_alert(task, "script realpath(%V) failed %E", path, nxt_errno); 226 return NXT_ERROR; 227 } 228 229 rpath.length = nxt_strlen(rpath.start); 230 231 if (!nxt_str_start(&rpath, root->start, root->length)) { 232 nxt_alert(task, "script is not under php root"); 233 return NXT_ERROR; 234 } 235 236 nxt_free(path->start); 237 238 *path = rpath; 239 240 script->length = c->script.length + 1; 241 script->start = nxt_malloc(script->length); 242 if (nxt_slow_path(script->start == NULL)) { 243 return NXT_ERROR; 244 } 245 246 script->start[0] = '/'; 247 nxt_memcpy(script->start + 1, c->script.start, c->script.length); 248 249 nxt_log_error(NXT_LOG_INFO, task->log, 250 "(ABS_MODE) php script \"%V\" root: \"%V\"", 251 script, root); 252 253 } else { 254 nxt_log_error(NXT_LOG_INFO, task->log, 255 "(non ABS_MODE) php root: \"%V\"", root); 256 } 257 258 if (c->index.length > 0) { 259 index->length = c->index.length; 260 index->start = nxt_malloc(index->length); 261 if (nxt_slow_path(index->start == NULL)) { 262 return NXT_ERROR; 263 } 264 265 nxt_memcpy(index->start, c->index.start, c->index.length); 266 } 267 268 #ifdef ZTS 269 tsrm_startup(1, 1, 0, NULL); 270 tsrm_ls = ts_resource(0); 271 #endif 272 273 #if defined(NXT_PHP7) && defined(ZEND_SIGNALS) 274 275 #if (NXT_ZEND_SIGNAL_STARTUP) 276 zend_signal_startup(); 277 #elif defined(ZTS) 278 #error PHP is built with thread safety and broken signals. 279 #endif 280 281 #endif 282 283 sapi_startup(&nxt_php_sapi_module); 284 285 if (c->options != NULL) { 286 value = nxt_conf_get_object_member(c->options, &file_str, NULL); 287 288 if (value != NULL) { 289 nxt_conf_get_string(value, &ini_path); 290 291 p = nxt_malloc(ini_path.length + 1); 292 if (nxt_slow_path(p == NULL)) { 293 return NXT_ERROR; 294 } 295 296 nxt_php_sapi_module.php_ini_path_override = (char *) p; 297 298 p = nxt_cpymem(p, ini_path.start, ini_path.length); 299 *p = '\0'; 300 } 301 } 302 303 nxt_php_startup(&nxt_php_sapi_module); 304 305 if (c->options != NULL) { 306 value = nxt_conf_get_object_member(c->options, &admin_str, NULL); 307 nxt_php_set_options(task, value, ZEND_INI_SYSTEM); 308 309 value = nxt_conf_get_object_member(c->options, &user_str, NULL); 310 nxt_php_set_options(task, value, ZEND_INI_USER); 311 } 312 313 nxt_memzero(&php_init, sizeof(nxt_unit_init_t)); 314 315 rt = task->thread->runtime; 316 317 main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 318 if (nxt_slow_path(main_port == NULL)) { 319 return NXT_ERROR; 320 } 321 322 my_port = nxt_runtime_port_find(rt, nxt_pid, 0); 323 if (nxt_slow_path(my_port == NULL)) { 324 return NXT_ERROR; 325 } 326 327 php_init.callbacks.request_handler = nxt_php_request_handler; 328 php_init.ready_port.id.pid = main_port->pid; 329 php_init.ready_port.id.id = main_port->id; 330 php_init.ready_port.out_fd = main_port->pair[1]; 331 332 nxt_fd_blocking(task, main_port->pair[1]); 333 334 php_init.ready_stream = my_port->process->init->stream; 335 336 php_init.read_port.id.pid = my_port->pid; 337 php_init.read_port.id.id = my_port->id; 338 php_init.read_port.in_fd = my_port->pair[0]; 339 340 nxt_fd_blocking(task, my_port->pair[0]); 341 342 php_init.log_fd = 2; 343 344 unit_ctx = nxt_unit_init(&php_init); 345 if (nxt_slow_path(unit_ctx == NULL)) { 346 return NXT_ERROR; 347 } 348 349 nxt_unit_run(unit_ctx); 350 351 nxt_unit_done(unit_ctx); 352 353 exit(0); 354 355 return NXT_OK; 356 } 357 358 359 static void 360 nxt_php_set_options(nxt_task_t *task, nxt_conf_value_t *options, int type) 361 { 362 uint32_t next; 363 nxt_str_t name, value; 364 nxt_conf_value_t *value_obj; 365 366 if (options != NULL) { 367 next = 0; 368 369 for ( ;; ) { 370 value_obj = nxt_conf_next_object_member(options, &name, &next); 371 if (value_obj == NULL) { 372 break; 373 } 374 375 nxt_conf_get_string(value_obj, &value); 376 377 if (nxt_php_alter_option(&name, &value, type) != NXT_OK) { 378 nxt_log(task, NXT_LOG_ERR, 379 "setting PHP option \"%V: %V\" failed", &name, &value); 380 } 381 } 382 } 383 } 384 385 386 #if (NXT_PHP7) 387 388 static nxt_int_t 389 nxt_php_alter_option(nxt_str_t *name, nxt_str_t *value, int type) 390 { 391 zend_string *zs; 392 zend_ini_entry *ini_entry; 393 394 ini_entry = zend_hash_str_find_ptr(EG(ini_directives), 395 (char *) name->start, name->length); 396 397 if (ini_entry == NULL) { 398 return NXT_ERROR; 399 } 400 401 /* PHP exits on memory allocation errors. */ 402 zs = zend_string_init((char *) value->start, value->length, 1); 403 404 if (ini_entry->on_modify 405 && ini_entry->on_modify(ini_entry, zs, ini_entry->mh_arg1, 406 ini_entry->mh_arg2, ini_entry->mh_arg3, 407 ZEND_INI_STAGE_ACTIVATE) 408 != SUCCESS) 409 { 410 zend_string_release(zs); 411 return NXT_ERROR; 412 } 413 414 ini_entry->value = zs; 415 ini_entry->modifiable = type; 416 417 return NXT_OK; 418 } 419 420 #else /* PHP 5. */ 421 422 static nxt_int_t 423 nxt_php_alter_option(nxt_str_t *name, nxt_str_t *value, int type) 424 { 425 char *cstr; 426 zend_ini_entry *ini_entry; 427 char buf[256]; 428 429 if (nxt_slow_path(name->length >= sizeof(buf))) { 430 return NXT_ERROR; 431 } 432 433 nxt_memcpy(buf, name->start, name->length); 434 buf[name->length] = '\0'; 435 436 if (zend_hash_find(EG(ini_directives), buf, name->length + 1, 437 (void **) &ini_entry) 438 == FAILURE) 439 { 440 return NXT_ERROR; 441 } 442 443 cstr = nxt_malloc(value->length + 1); 444 if (nxt_slow_path(cstr == NULL)) { 445 return NXT_ERROR; 446 } 447 448 nxt_memcpy(cstr, value->start, value->length); 449 cstr[value->length] = '\0'; 450 451 if (ini_entry->on_modify 452 && ini_entry->on_modify(ini_entry, cstr, value->length, 453 ini_entry->mh_arg1, ini_entry->mh_arg2, 454 ini_entry->mh_arg3, ZEND_INI_STAGE_ACTIVATE 455 TSRMLS_CC) 456 != SUCCESS) 457 { 458 nxt_free(cstr); 459 return NXT_ERROR; 460 } 461 462 ini_entry->value = cstr; 463 ini_entry->value_length = value->length; 464 ini_entry->modifiable = type; 465 466 return NXT_OK; 467 } 468 469 #endif 470 471 472 static void 473 nxt_php_str_trim_trail(nxt_str_t *str, u_char t) 474 { 475 while (str->length > 0 && str->start[str->length - 1] == t) { 476 str->length--; 477 } 478 479 str->start[str->length] = '\0'; 480 } 481 482 483 static void 484 nxt_php_str_trim_lead(nxt_str_t *str, u_char t) 485 { 486 while (str->length > 0 && str->start[0] == t) { 487 str->length--; 488 str->start++; 489 } 490 } 491 492 493 nxt_inline u_char * 494 nxt_realpath(const void *c) 495 { 496 return (u_char *) realpath(c, NULL); 497 } 498 499 500 static void 501 nxt_php_request_handler(nxt_unit_request_info_t *req) 502 { 503 int rc; 504 u_char *p; 505 nxt_str_t path, script_name; 506 nxt_unit_field_t *f; 507 zend_file_handle file_handle; 508 nxt_php_run_ctx_t run_ctx, *ctx; 509 nxt_unit_request_t *r; 510 511 nxt_memzero(&run_ctx, sizeof(run_ctx)); 512 513 ctx = &run_ctx; 514 ctx->req = req; 515 516 r = req->request; 517 518 path.length = r->path_length; 519 path.start = nxt_unit_sptr_get(&r->path); 520 521 if (nxt_php_path.start == NULL) { 522 if (path.start[path.length - 1] == '/') { 523 script_name = nxt_php_index; 524 525 } else { 526 script_name.length = 0; 527 script_name.start = NULL; 528 } 529 530 ctx->script.length = nxt_php_root.length + path.length 531 + script_name.length; 532 p = ctx->script.start = nxt_malloc(ctx->script.length + 1); 533 if (nxt_slow_path(p == NULL)) { 534 nxt_unit_request_done(req, NXT_UNIT_ERROR); 535 536 return; 537 } 538 539 p = nxt_cpymem(p, nxt_php_root.start, nxt_php_root.length); 540 p = nxt_cpymem(p, path.start, path.length); 541 542 if (script_name.length > 0) { 543 p = nxt_cpymem(p, script_name.start, script_name.length); 544 } 545 546 *p = '\0'; 547 548 } else { 549 ctx->script = nxt_php_path; 550 } 551 552 SG(server_context) = ctx; 553 SG(request_info).request_uri = nxt_unit_sptr_get(&r->target); 554 SG(request_info).request_method = nxt_unit_sptr_get(&r->method); 555 556 SG(request_info).proto_num = 1001; 557 558 SG(request_info).query_string = r->query.offset 559 ? nxt_unit_sptr_get(&r->query) : NULL; 560 SG(request_info).content_length = r->content_length; 561 562 if (r->content_type_field != NXT_UNIT_NONE_FIELD) { 563 f = r->fields + r->content_type_field; 564 565 SG(request_info).content_type = nxt_unit_sptr_get(&f->value); 566 } 567 568 if (r->cookie_field != NXT_UNIT_NONE_FIELD) { 569 f = r->fields + r->cookie_field; 570 571 ctx->cookie = nxt_unit_sptr_get(&f->value); 572 } 573 574 SG(sapi_headers).http_response_code = 200; 575 576 SG(request_info).path_translated = NULL; 577 578 file_handle.type = ZEND_HANDLE_FILENAME; 579 file_handle.filename = (char *) ctx->script.start; 580 file_handle.free_filename = 0; 581 file_handle.opened_path = NULL; 582 583 nxt_unit_req_debug(req, "handle.filename = '%s'", ctx->script.start); 584 585 if (nxt_php_path.start != NULL) { 586 nxt_unit_req_debug(req, "run script %.*s in absolute mode", 587 (int) nxt_php_path.length, 588 (char *) nxt_php_path.start); 589 590 } else { 591 nxt_unit_req_debug(req, "run script %.*s", (int) ctx->script.length, 592 (char *) ctx->script.start); 593 } 594 595 #if (NXT_PHP7) 596 if (nxt_slow_path(php_request_startup() == FAILURE)) { 597 #else 598 if (nxt_slow_path(php_request_startup(TSRMLS_C) == FAILURE)) { 599 #endif 600 nxt_unit_req_debug(req, "php_request_startup() failed"); 601 rc = NXT_UNIT_ERROR; 602 603 goto fail; 604 } 605 606 rc = NXT_UNIT_OK; 607 608 php_execute_script(&file_handle TSRMLS_CC); 609 php_request_shutdown(NULL); 610 611 fail: 612 613 nxt_unit_request_done(req, rc); 614 615 if (ctx->script.start != nxt_php_path.start) { 616 nxt_free(ctx->script.start); 617 } 618 } 619 620 621 static int 622 nxt_php_startup(sapi_module_struct *sapi_module) 623 { 624 return php_module_startup(sapi_module, NULL, 0); 625 } 626 627 628 #ifdef NXT_PHP7 629 static size_t 630 nxt_php_unbuffered_write(const char *str, size_t str_length TSRMLS_DC) 631 #else 632 static int 633 nxt_php_unbuffered_write(const char *str, uint str_length TSRMLS_DC) 634 #endif 635 { 636 int rc; 637 nxt_php_run_ctx_t *ctx; 638 639 ctx = SG(server_context); 640 641 rc = nxt_unit_response_write(ctx->req, str, str_length); 642 if (nxt_fast_path(rc == NXT_UNIT_OK)) { 643 return str_length; 644 } 645 646 php_handle_aborted_connection(); 647 return 0; 648 } 649 650 651 static int 652 nxt_php_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) 653 { 654 int rc, fields_count; 655 char *colon, *status_line, *value; 656 uint16_t status; 657 uint32_t resp_size; 658 nxt_php_run_ctx_t *ctx; 659 sapi_header_struct *h; 660 zend_llist_position zpos; 661 nxt_unit_request_info_t *req; 662 663 ctx = SG(server_context); 664 req = ctx->req; 665 666 nxt_unit_req_debug(req, "nxt_php_send_headers"); 667 668 if (SG(request_info).no_headers == 1) { 669 rc = nxt_unit_response_init(req, 200, 0, 0); 670 if (nxt_slow_path(rc != NXT_UNIT_OK)) { 671 return SAPI_HEADER_SEND_FAILED; 672 } 673 674 return SAPI_HEADER_SENT_SUCCESSFULLY; 675 } 676 677 resp_size = 0; 678 fields_count = zend_llist_count(&sapi_headers->headers); 679 680 for (h = zend_llist_get_first_ex(&sapi_headers->headers, &zpos); 681 h; 682 h = zend_llist_get_next_ex(&sapi_headers->headers, &zpos)) 683 { 684 resp_size += h->header_len; 685 } 686 687 if (SG(sapi_headers).http_status_line) { 688 status_line = SG(sapi_headers).http_status_line; 689 690 status = nxt_int_parse((u_char *) status_line + 9, 3); 691 692 } else if (SG(sapi_headers).http_response_code) { 693 status = SG(sapi_headers).http_response_code; 694 695 } else { 696 status = 200; 697 } 698 699 rc = nxt_unit_response_init(req, status, fields_count, resp_size); 700 if (nxt_slow_path(rc != NXT_UNIT_OK)) { 701 return SAPI_HEADER_SEND_FAILED; 702 } 703 704 for (h = zend_llist_get_first_ex(&sapi_headers->headers, &zpos); 705 h; 706 h = zend_llist_get_next_ex(&sapi_headers->headers, &zpos)) 707 { 708 nxt_unit_req_debug(req, "header: %.*s", (int) h->header_len, h->header); 709 710 colon = memchr(h->header, ':', h->header_len); 711 if (nxt_slow_path(colon == NULL)) { 712 nxt_unit_req_warn(req, "colon not found in header '%.*s'", 713 (int) h->header_len, h->header); 714 continue; 715 } 716 717 value = colon + 1; 718 while(isspace(*value)) { 719 value++; 720 } 721 722 nxt_unit_response_add_field(req, h->header, colon - h->header, 723 value, 724 h->header_len - (value - h->header)); 725 } 726 727 rc = nxt_unit_response_send(req); 728 if (nxt_slow_path(rc != NXT_UNIT_OK)) { 729 nxt_unit_req_debug(req, "failed to send response"); 730 731 return SAPI_HEADER_SEND_FAILED; 732 } 733 734 return SAPI_HEADER_SENT_SUCCESSFULLY; 735 } 736 737 738 #ifdef NXT_PHP7 739 static size_t 740 nxt_php_read_post(char *buffer, size_t count_bytes TSRMLS_DC) 741 #else 742 static int 743 nxt_php_read_post(char *buffer, uint count_bytes TSRMLS_DC) 744 #endif 745 { 746 nxt_php_run_ctx_t *ctx; 747 748 ctx = SG(server_context); 749 750 nxt_unit_req_debug(ctx->req, "nxt_php_read_post %d", (int) count_bytes); 751 752 return nxt_unit_request_read(ctx->req, buffer, count_bytes); 753 } 754 755 756 static char * 757 nxt_php_read_cookies(TSRMLS_D) 758 { 759 nxt_php_run_ctx_t *ctx; 760 761 ctx = SG(server_context); 762 763 nxt_unit_req_debug(ctx->req, "nxt_php_read_cookies"); 764 765 return ctx->cookie; 766 } 767 768 769 static void 770 nxt_php_register_variables(zval *track_vars_array TSRMLS_DC) 771 { 772 char *host_start, *port_start; 773 uint32_t host_length, port_length; 774 const char *name; 775 nxt_unit_field_t *f, *f_end; 776 nxt_php_run_ctx_t *ctx; 777 nxt_unit_request_t *r; 778 nxt_unit_request_info_t *req; 779 780 ctx = SG(server_context); 781 782 req = ctx->req; 783 r = req->request; 784 785 nxt_unit_req_debug(req, "nxt_php_register_variables"); 786 787 php_register_variable_safe((char *) "SERVER_SOFTWARE", 788 (char *) nxt_server.start, 789 nxt_server.length, track_vars_array TSRMLS_CC); 790 791 nxt_php_set_sptr(req, "SERVER_PROTOCOL", &r->version, r->version_length, 792 track_vars_array TSRMLS_CC); 793 794 /* 795 * 'SCRIPT_NAME' 796 * Contains the current script's path. This is useful for pages which need to 797 * point to themselves. The __FILE__ constant contains the full path and 798 * filename of the current (i.e. included) file. 799 */ 800 801 /* 802 * 'SCRIPT_FILENAME' 803 * The absolute pathname of the currently executing script. 804 */ 805 806 /* 807 * 'DOCUMENT_ROOT' 808 * The document root directory under which the current script is executing, 809 * as defined in the server's configuration file. 810 */ 811 812 if (nxt_php_script.start != NULL) { 813 // ABS_MODE 814 /* 815 * 'PHP_SELF' 816 * The filename of the currently executing script, relative to the document 817 * root. For instance, $_SERVER['PHP_SELF'] in a script at the address 818 * http://example.com/foo/bar.php would be /foo/bar.php. The __FILE__ constant 819 * contains the full path and filename of the current (i.e. included) file. 820 * If PHP is running as a command-line processor this variable contains the 821 * script name since PHP 4.3.0. Previously it was not available. 822 */ 823 nxt_php_set_str(req, "PHP_SELF", &nxt_php_script, 824 track_vars_array TSRMLS_CC); 825 nxt_php_set_str(req, "SCRIPT_NAME", &nxt_php_script, 826 track_vars_array TSRMLS_CC); 827 828 } else { 829 nxt_php_set_sptr(req, "PHP_SELF", &r->path, r->path_length, 830 track_vars_array TSRMLS_CC); 831 nxt_php_set_sptr(req, "SCRIPT_NAME", &r->path, r->path_length, 832 track_vars_array TSRMLS_CC); 833 } 834 835 nxt_php_set_str(req, "SCRIPT_FILENAME", &ctx->script, 836 track_vars_array TSRMLS_CC); 837 nxt_php_set_str(req, "DOCUMENT_ROOT", &nxt_php_root, 838 track_vars_array TSRMLS_CC); 839 840 nxt_php_set_sptr(req, "REQUEST_METHOD", &r->method, r->method_length, 841 track_vars_array TSRMLS_CC); 842 nxt_php_set_sptr(req, "REQUEST_URI", &r->target, r->target_length, 843 track_vars_array TSRMLS_CC); 844 if (r->query.offset) { 845 nxt_php_set_sptr(req, "QUERY_STRING", &r->query, r->query_length, 846 track_vars_array TSRMLS_CC); 847 } 848 849 nxt_php_set_sptr(req, "REMOTE_ADDR", &r->remote, r->remote_length, 850 track_vars_array TSRMLS_CC); 851 nxt_php_set_sptr(req, "SERVER_ADDR", &r->local, r->local_length, 852 track_vars_array TSRMLS_CC); 853 854 f_end = r->fields + r->fields_count; 855 for (f = r->fields; f < f_end; f++) { 856 name = nxt_unit_sptr_get(&f->name); 857 858 nxt_php_set_sptr(req, name, &f->value, f->value_length, 859 track_vars_array TSRMLS_CC); 860 } 861 862 if (r->content_length_field != NXT_UNIT_NONE_FIELD) { 863 f = r->fields + r->content_length_field; 864 865 nxt_php_set_sptr(req, "CONTENT_LENGTH", &f->value, f->value_length, 866 track_vars_array TSRMLS_CC); 867 } 868 869 if (r->content_type_field != NXT_UNIT_NONE_FIELD) { 870 f = r->fields + r->content_type_field; 871 872 nxt_php_set_sptr(req, "CONTENT_TYPE", &f->value, f->value_length, 873 track_vars_array TSRMLS_CC); 874 } 875 876 if (r->host_field != NXT_UNIT_NONE_FIELD) { 877 f = r->fields + r->host_field; 878 879 host_start = nxt_unit_sptr_get(&f->value); 880 host_length = f->value_length; 881 882 } else { 883 host_start = NULL; 884 host_length = 0; 885 } 886 887 nxt_unit_split_host(host_start, host_length, &host_start, &host_length, 888 &port_start, &port_length); 889 890 nxt_php_set_cstr(req, "SERVER_NAME", host_start, host_length, 891 track_vars_array TSRMLS_CC); 892 nxt_php_set_cstr(req, "SERVER_PORT", port_start, port_length, 893 track_vars_array TSRMLS_CC); 894 } 895 896 897 static void 898 nxt_php_set_sptr(nxt_unit_request_info_t *req, const char *name, 899 nxt_unit_sptr_t *v, uint32_t len, zval *track_vars_array TSRMLS_DC) 900 { 901 char *str; 902 903 str = nxt_unit_sptr_get(v); 904 905 nxt_unit_req_debug(req, "php: register %s='%.*s'", name, (int) len, str); 906 907 php_register_variable_safe((char *) name, str, len, 908 track_vars_array TSRMLS_CC); 909 } 910 911 912 nxt_inline void 913 nxt_php_set_str(nxt_unit_request_info_t *req, const char *name, 914 nxt_str_t *s, zval *track_vars_array TSRMLS_DC) 915 { 916 nxt_php_set_cstr(req, name, (char *) s->start, s->length, 917 track_vars_array TSRMLS_CC); 918 } 919 920 921 static void 922 nxt_php_set_cstr(nxt_unit_request_info_t *req, const char *name, 923 char *cstr, uint32_t len, zval *track_vars_array TSRMLS_DC) 924 { 925 if (nxt_slow_path(cstr == NULL)) { 926 return; 927 } 928 929 nxt_unit_req_debug(req, "php: register %s='%.*s'", name, (int) len, cstr); 930 931 php_register_variable_safe((char *) name, cstr, len, 932 track_vars_array TSRMLS_CC); 933 } 934 935 936 #ifdef NXT_HAVE_PHP_LOG_MESSAGE_WITH_SYSLOG_TYPE 937 static void 938 nxt_php_log_message(char *message, int syslog_type_int) 939 #else 940 static void 941 nxt_php_log_message(char *message TSRMLS_DC) 942 #endif 943 { 944 nxt_log(nxt_php_task, NXT_LOG_NOTICE, "php message: %s", message); 945 } 946