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