xref: /unit/src/nxt_php_sapi.c (revision 1562)
10Sigor@sysoev.ru /*
286Smax.romanov@nginx.com  * Copyright (C) Max Romanov
30Sigor@sysoev.ru  * Copyright (C) Valentin V. Bartenev
40Sigor@sysoev.ru  * Copyright (C) NGINX, Inc.
50Sigor@sysoev.ru  */
60Sigor@sysoev.ru 
70Sigor@sysoev.ru #include "php.h"
80Sigor@sysoev.ru #include "SAPI.h"
90Sigor@sysoev.ru #include "php_main.h"
100Sigor@sysoev.ru #include "php_variables.h"
110Sigor@sysoev.ru 
120Sigor@sysoev.ru #include <nxt_main.h>
13446Sigor@sysoev.ru #include <nxt_router.h>
14743Smax.romanov@nginx.com #include <nxt_unit.h>
15743Smax.romanov@nginx.com #include <nxt_unit_request.h>
160Sigor@sysoev.ru 
170Sigor@sysoev.ru 
181369St.nateldemoura@f5.com #if PHP_VERSION_ID >= 50400
191369St.nateldemoura@f5.com #define NXT_HAVE_PHP_IGNORE_CWD 1
2086Smax.romanov@nginx.com #endif
210Sigor@sysoev.ru 
221369St.nateldemoura@f5.com #if PHP_VERSION_ID >= 70100
231369St.nateldemoura@f5.com #define NXT_HAVE_PHP_LOG_MESSAGE_WITH_SYSLOG_TYPE 1
241369St.nateldemoura@f5.com #else
251369St.nateldemoura@f5.com #define NXT_HAVE_PHP_INTERRUPTS 1
261369St.nateldemoura@f5.com #endif
271369St.nateldemoura@f5.com 
281369St.nateldemoura@f5.com #if PHP_VERSION_ID >= 70000
291369St.nateldemoura@f5.com #define NXT_PHP7 1
301369St.nateldemoura@f5.com #endif
31*1562Sremi@remirepo.net #if PHP_VERSION_ID >= 80000
32*1562Sremi@remirepo.net #define NXT_PHP8 1
33*1562Sremi@remirepo.net #endif
34861Svbart@nginx.com 
351482Sremi@remirepo.net /* PHP 8 */
361482Sremi@remirepo.net #ifndef TSRMLS_CC
371482Sremi@remirepo.net #define TSRMLS_CC
381482Sremi@remirepo.net #define TSRMLS_DC
391482Sremi@remirepo.net #define TSRMLS_D  void
401482Sremi@remirepo.net #define TSRMLS_C
411482Sremi@remirepo.net #endif
421482Sremi@remirepo.net 
431473Svbart@nginx.com 
441473Svbart@nginx.com typedef struct {
451473Svbart@nginx.com     nxt_str_t  root;
461473Svbart@nginx.com     nxt_str_t  index;
471473Svbart@nginx.com     nxt_str_t  script_name;
481473Svbart@nginx.com     nxt_str_t  script_dirname;
491473Svbart@nginx.com     nxt_str_t  script_filename;
501473Svbart@nginx.com } nxt_php_target_t;
511473Svbart@nginx.com 
521473Svbart@nginx.com 
531376St.nateldemoura@f5.com typedef struct {
541376St.nateldemoura@f5.com     char                     *cookie;
551473Svbart@nginx.com     nxt_str_t                *root;
561473Svbart@nginx.com     nxt_str_t                *index;
571376St.nateldemoura@f5.com     nxt_str_t                path_info;
581376St.nateldemoura@f5.com     nxt_str_t                script_name;
591376St.nateldemoura@f5.com     nxt_str_t                script_filename;
601376St.nateldemoura@f5.com     nxt_str_t                script_dirname;
611376St.nateldemoura@f5.com     nxt_unit_request_info_t  *req;
621376St.nateldemoura@f5.com 
631376St.nateldemoura@f5.com     uint8_t                  chdir;  /* 1 bit */
641376St.nateldemoura@f5.com } nxt_php_run_ctx_t;
651376St.nateldemoura@f5.com 
66861Svbart@nginx.com 
67*1562Sremi@remirepo.net #if NXT_PHP8
68*1562Sremi@remirepo.net typedef int (*nxt_php_disable_t)(const char *p, size_t size);
69*1562Sremi@remirepo.net #elif NXT_PHP7
70861Svbart@nginx.com typedef int (*nxt_php_disable_t)(char *p, size_t size);
71861Svbart@nginx.com #else
72861Svbart@nginx.com typedef int (*nxt_php_disable_t)(char *p, uint TSRMLS_DC);
73861Svbart@nginx.com #endif
74861Svbart@nginx.com 
751376St.nateldemoura@f5.com #if PHP_VERSION_ID < 70200
761376St.nateldemoura@f5.com typedef void (*zif_handler)(INTERNAL_FUNCTION_PARAMETERS);
771376St.nateldemoura@f5.com #endif
781376St.nateldemoura@f5.com 
79861Svbart@nginx.com 
801488St.nateldemoura@f5.com static nxt_int_t nxt_php_start(nxt_task_t *task, nxt_process_data_t *data);
811473Svbart@nginx.com static nxt_int_t nxt_php_set_target(nxt_task_t *task, nxt_php_target_t *target,
821473Svbart@nginx.com     nxt_conf_value_t *conf);
83688Svbart@nginx.com static void nxt_php_set_options(nxt_task_t *task, nxt_conf_value_t *options,
84688Svbart@nginx.com     int type);
85713Svbart@nginx.com static nxt_int_t nxt_php_alter_option(nxt_str_t *name, nxt_str_t *value,
86713Svbart@nginx.com     int type);
87861Svbart@nginx.com static void nxt_php_disable(nxt_task_t *task, const char *type,
88861Svbart@nginx.com     nxt_str_t *value, char **ptr, nxt_php_disable_t disable);
891473Svbart@nginx.com 
901473Svbart@nginx.com static nxt_int_t nxt_php_dirname(const nxt_str_t *file, nxt_str_t *dir);
911473Svbart@nginx.com static void nxt_php_str_trim_trail(nxt_str_t *str, u_char t);
921473Svbart@nginx.com static void nxt_php_str_trim_lead(nxt_str_t *str, u_char t);
931473Svbart@nginx.com nxt_inline u_char *nxt_realpath(const void *c);
941473Svbart@nginx.com 
951473Svbart@nginx.com static void nxt_php_request_handler(nxt_unit_request_info_t *req);
961473Svbart@nginx.com static void nxt_php_dynamic_request(nxt_php_run_ctx_t *ctx,
971473Svbart@nginx.com     nxt_unit_request_t *r);
981473Svbart@nginx.com static void nxt_php_execute(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r);
991473Svbart@nginx.com nxt_inline void nxt_php_vcwd_chdir(nxt_unit_request_info_t *req, u_char *dir);
1001473Svbart@nginx.com 
1011473Svbart@nginx.com static int nxt_php_startup(sapi_module_struct *sapi_module);
102857Svbart@nginx.com static int nxt_php_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC);
1031376St.nateldemoura@f5.com static void *nxt_php_hash_str_find_ptr(const HashTable *ht,
1041376St.nateldemoura@f5.com     const nxt_str_t *str);
105857Svbart@nginx.com static char *nxt_php_read_cookies(TSRMLS_D);
106743Smax.romanov@nginx.com static void nxt_php_set_sptr(nxt_unit_request_info_t *req, const char *name,
107743Smax.romanov@nginx.com     nxt_unit_sptr_t *v, uint32_t len, zval *track_vars_array TSRMLS_DC);
108743Smax.romanov@nginx.com nxt_inline void nxt_php_set_str(nxt_unit_request_info_t *req, const char *name,
109743Smax.romanov@nginx.com     nxt_str_t *s, zval *track_vars_array TSRMLS_DC);
110743Smax.romanov@nginx.com static void nxt_php_set_cstr(nxt_unit_request_info_t *req, const char *name,
111967Svbart@nginx.com     const char *str, uint32_t len, zval *track_vars_array TSRMLS_DC);
112857Svbart@nginx.com static void nxt_php_register_variables(zval *track_vars_array TSRMLS_DC);
113*1562Sremi@remirepo.net #if NXT_PHP8
114*1562Sremi@remirepo.net static void nxt_php_log_message(const char *message, int syslog_type_int);
115*1562Sremi@remirepo.net #else
11686Smax.romanov@nginx.com #ifdef NXT_HAVE_PHP_LOG_MESSAGE_WITH_SYSLOG_TYPE
117579Svbart@nginx.com static void nxt_php_log_message(char *message, int syslog_type_int);
118579Svbart@nginx.com #else
119857Svbart@nginx.com static void nxt_php_log_message(char *message TSRMLS_DC);
12086Smax.romanov@nginx.com #endif
121*1562Sremi@remirepo.net #endif
1220Sigor@sysoev.ru 
1230Sigor@sysoev.ru #ifdef NXT_PHP7
1240Sigor@sysoev.ru static size_t nxt_php_unbuffered_write(const char *str,
1250Sigor@sysoev.ru     size_t str_length TSRMLS_DC);
1260Sigor@sysoev.ru static size_t nxt_php_read_post(char *buffer, size_t count_bytes TSRMLS_DC);
1270Sigor@sysoev.ru #else
1280Sigor@sysoev.ru static int nxt_php_unbuffered_write(const char *str, uint str_length TSRMLS_DC);
1290Sigor@sysoev.ru static int nxt_php_read_post(char *buffer, uint count_bytes TSRMLS_DC);
1300Sigor@sysoev.ru #endif
1310Sigor@sysoev.ru 
1320Sigor@sysoev.ru 
1331376St.nateldemoura@f5.com PHP_MINIT_FUNCTION(nxt_php_ext);
1341376St.nateldemoura@f5.com ZEND_NAMED_FUNCTION(nxt_php_chdir);
1351376St.nateldemoura@f5.com 
1361376St.nateldemoura@f5.com zif_handler  nxt_php_chdir_handler;
1371376St.nateldemoura@f5.com 
1381376St.nateldemoura@f5.com 
1391376St.nateldemoura@f5.com static zend_module_entry  nxt_php_unit_module = {
1401376St.nateldemoura@f5.com     STANDARD_MODULE_HEADER,
1411376St.nateldemoura@f5.com     "unit",
1421376St.nateldemoura@f5.com     NULL,                        /* function table */
1431376St.nateldemoura@f5.com     PHP_MINIT(nxt_php_ext),      /* initialization */
1441376St.nateldemoura@f5.com     NULL,                        /* shutdown */
1451376St.nateldemoura@f5.com     NULL,                        /* request initialization */
1461376St.nateldemoura@f5.com     NULL,                        /* request shutdown */
1471376St.nateldemoura@f5.com     NULL,                        /* information */
1481376St.nateldemoura@f5.com     NXT_VERSION,
1491376St.nateldemoura@f5.com     STANDARD_MODULE_PROPERTIES
1501376St.nateldemoura@f5.com };
1511376St.nateldemoura@f5.com 
1521376St.nateldemoura@f5.com 
1531376St.nateldemoura@f5.com PHP_MINIT_FUNCTION(nxt_php_ext)
1541376St.nateldemoura@f5.com {
1551376St.nateldemoura@f5.com     zend_function  *func;
1561376St.nateldemoura@f5.com 
1571376St.nateldemoura@f5.com     static const nxt_str_t  chdir = nxt_string("chdir");
1581376St.nateldemoura@f5.com 
1591376St.nateldemoura@f5.com     func = nxt_php_hash_str_find_ptr(CG(function_table), &chdir);
1601376St.nateldemoura@f5.com     if (nxt_slow_path(func == NULL)) {
1611376St.nateldemoura@f5.com         return FAILURE;
1621376St.nateldemoura@f5.com     }
1631376St.nateldemoura@f5.com 
1641376St.nateldemoura@f5.com     nxt_php_chdir_handler = func->internal_function.handler;
1651376St.nateldemoura@f5.com     func->internal_function.handler = nxt_php_chdir;
1661376St.nateldemoura@f5.com 
1671376St.nateldemoura@f5.com     return SUCCESS;
1681376St.nateldemoura@f5.com }
1691376St.nateldemoura@f5.com 
1701376St.nateldemoura@f5.com 
1711376St.nateldemoura@f5.com ZEND_NAMED_FUNCTION(nxt_php_chdir)
1721376St.nateldemoura@f5.com {
1731376St.nateldemoura@f5.com     nxt_php_run_ctx_t  *ctx;
1741376St.nateldemoura@f5.com 
1751376St.nateldemoura@f5.com     ctx = SG(server_context);
1761376St.nateldemoura@f5.com     ctx->chdir = 1;
1771376St.nateldemoura@f5.com 
1781376St.nateldemoura@f5.com     nxt_php_chdir_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
1791376St.nateldemoura@f5.com }
1801376St.nateldemoura@f5.com 
1811376St.nateldemoura@f5.com 
1820Sigor@sysoev.ru static sapi_module_struct  nxt_php_sapi_module =
1830Sigor@sysoev.ru {
1840Sigor@sysoev.ru     (char *) "cli-server",
185259Sigor@sysoev.ru     (char *) "unit",
1860Sigor@sysoev.ru 
1870Sigor@sysoev.ru     nxt_php_startup,             /* startup */
1880Sigor@sysoev.ru     php_module_shutdown_wrapper, /* shutdown */
1890Sigor@sysoev.ru 
1900Sigor@sysoev.ru     NULL,                        /* activate */
1910Sigor@sysoev.ru     NULL,                        /* deactivate */
1920Sigor@sysoev.ru 
1930Sigor@sysoev.ru     nxt_php_unbuffered_write,    /* unbuffered write */
194743Smax.romanov@nginx.com     NULL,                        /* flush */
1950Sigor@sysoev.ru     NULL,                        /* get uid */
1960Sigor@sysoev.ru     NULL,                        /* getenv */
1970Sigor@sysoev.ru 
1980Sigor@sysoev.ru     php_error,                   /* error handler */
1990Sigor@sysoev.ru 
2000Sigor@sysoev.ru     NULL,                        /* header handler */
2010Sigor@sysoev.ru     nxt_php_send_headers,        /* send headers handler */
2020Sigor@sysoev.ru     NULL,                        /* send header handler */
2030Sigor@sysoev.ru 
2040Sigor@sysoev.ru     nxt_php_read_post,           /* read POST data */
2050Sigor@sysoev.ru     nxt_php_read_cookies,        /* read Cookies */
2060Sigor@sysoev.ru 
2070Sigor@sysoev.ru     nxt_php_register_variables,  /* register server variables */
2080Sigor@sysoev.ru     nxt_php_log_message,         /* log message */
20986Smax.romanov@nginx.com     NULL,                        /* get request time */
21086Smax.romanov@nginx.com     NULL,                        /* terminate process */
2110Sigor@sysoev.ru 
21286Smax.romanov@nginx.com     NULL,                        /* php_ini_path_override */
21386Smax.romanov@nginx.com #ifdef NXT_HAVE_PHP_INTERRUPTS
21486Smax.romanov@nginx.com     NULL,                        /* block_interruptions */
21586Smax.romanov@nginx.com     NULL,                        /* unblock_interruptions */
21686Smax.romanov@nginx.com #endif
21786Smax.romanov@nginx.com     NULL,                        /* default_post_reader */
21886Smax.romanov@nginx.com     NULL,                        /* treat_data */
21986Smax.romanov@nginx.com     NULL,                        /* executable_location */
22086Smax.romanov@nginx.com 
22186Smax.romanov@nginx.com     0,                           /* php_ini_ignore */
22286Smax.romanov@nginx.com #ifdef NXT_HAVE_PHP_IGNORE_CWD
223687Svbart@nginx.com     1,                           /* php_ini_ignore_cwd */
22486Smax.romanov@nginx.com #endif
22586Smax.romanov@nginx.com     NULL,                        /* get_fd */
22686Smax.romanov@nginx.com 
22786Smax.romanov@nginx.com     NULL,                        /* force_http_10 */
22886Smax.romanov@nginx.com 
22986Smax.romanov@nginx.com     NULL,                        /* get_target_uid */
23086Smax.romanov@nginx.com     NULL,                        /* get_target_gid */
23186Smax.romanov@nginx.com 
23286Smax.romanov@nginx.com     NULL,                        /* input_filter */
23386Smax.romanov@nginx.com 
23486Smax.romanov@nginx.com     NULL,                        /* ini_defaults */
23586Smax.romanov@nginx.com     0,                           /* phpinfo_as_text */
23686Smax.romanov@nginx.com 
23786Smax.romanov@nginx.com     NULL,                        /* ini_entries */
23886Smax.romanov@nginx.com     NULL,                        /* additional_functions */
23986Smax.romanov@nginx.com     NULL                         /* input_filter_init */
2400Sigor@sysoev.ru };
2410Sigor@sysoev.ru 
242206Smax.romanov@nginx.com 
243258Sigor@sysoev.ru static uint32_t  compat[] = {
244360Sigor@sysoev.ru     NXT_VERNUM, NXT_DEBUG,
245258Sigor@sysoev.ru };
246258Sigor@sysoev.ru 
2470Sigor@sysoev.ru 
248743Smax.romanov@nginx.com NXT_EXPORT nxt_app_module_t  nxt_app_module = {
249258Sigor@sysoev.ru     sizeof(compat),
250258Sigor@sysoev.ru     compat,
251216Sigor@sysoev.ru     nxt_string("php"),
252612Salexander.borisov@nginx.com     PHP_VERSION,
253977Smax.romanov@gmail.com     NULL,
2541489St.nateldemoura@f5.com     0,
2551489St.nateldemoura@f5.com     NULL,
2561488St.nateldemoura@f5.com     nxt_php_start,
25786Smax.romanov@nginx.com };
2580Sigor@sysoev.ru 
2590Sigor@sysoev.ru 
2601473Svbart@nginx.com static nxt_php_target_t  *nxt_php_targets;
2611473Svbart@nginx.com static nxt_int_t         nxt_php_last_target = -1;
2621473Svbart@nginx.com 
2631513Svbart@nginx.com static nxt_unit_ctx_t    *nxt_php_unit_ctx;
2641369St.nateldemoura@f5.com #if defined(ZTS) && PHP_VERSION_ID < 70400
2651513Svbart@nginx.com static void              ***tsrm_ls;
266857Svbart@nginx.com #endif
267708Sigor@sysoev.ru 
268708Sigor@sysoev.ru 
26986Smax.romanov@nginx.com static nxt_int_t
2701488St.nateldemoura@f5.com nxt_php_start(nxt_task_t *task, nxt_process_data_t *data)
2710Sigor@sysoev.ru {
2721488St.nateldemoura@f5.com     u_char                 *p;
2731488St.nateldemoura@f5.com     uint32_t               next;
2741488St.nateldemoura@f5.com     nxt_str_t              ini_path, name;
2751488St.nateldemoura@f5.com     nxt_int_t              ret;
2761488St.nateldemoura@f5.com     nxt_uint_t             n;
2771488St.nateldemoura@f5.com     nxt_unit_ctx_t         *unit_ctx;
2781488St.nateldemoura@f5.com     nxt_unit_init_t        php_init;
2791488St.nateldemoura@f5.com     nxt_conf_value_t       *value;
2801488St.nateldemoura@f5.com     nxt_php_app_conf_t     *c;
2811488St.nateldemoura@f5.com     nxt_common_app_conf_t  *conf;
282142Smax.romanov@nginx.com 
283687Svbart@nginx.com     static nxt_str_t  file_str = nxt_string("file");
284688Svbart@nginx.com     static nxt_str_t  user_str = nxt_string("user");
285688Svbart@nginx.com     static nxt_str_t  admin_str = nxt_string("admin");
286687Svbart@nginx.com 
2871488St.nateldemoura@f5.com     conf = data->app;
288142Smax.romanov@nginx.com     c = &conf->u.php;
289142Smax.romanov@nginx.com 
2901473Svbart@nginx.com     n = (c->targets != NULL) ? nxt_conf_object_members_count(c->targets) : 1;
291142Smax.romanov@nginx.com 
2921473Svbart@nginx.com     nxt_php_targets = nxt_zalloc(sizeof(nxt_php_target_t) * n);
2931473Svbart@nginx.com     if (nxt_slow_path(nxt_php_targets == NULL)) {
294462Smax.romanov@nginx.com         return NXT_ERROR;
295462Smax.romanov@nginx.com     }
296462Smax.romanov@nginx.com 
2971473Svbart@nginx.com     if (c->targets != NULL) {
2981473Svbart@nginx.com         next = 0;
299142Smax.romanov@nginx.com 
3001473Svbart@nginx.com         for (n = 0; /* void */; n++) {
3011473Svbart@nginx.com             value = nxt_conf_next_object_member(c->targets, &name, &next);
3021473Svbart@nginx.com             if (value == NULL) {
3031473Svbart@nginx.com                 break;
3041473Svbart@nginx.com             }
305142Smax.romanov@nginx.com 
3061473Svbart@nginx.com             ret = nxt_php_set_target(task, &nxt_php_targets[n], value);
3071473Svbart@nginx.com             if (nxt_slow_path(ret != NXT_OK)) {
3081473Svbart@nginx.com                 return NXT_ERROR;
3091473Svbart@nginx.com             }
310462Smax.romanov@nginx.com         }
311142Smax.romanov@nginx.com 
3121473Svbart@nginx.com     } else {
3131473Svbart@nginx.com         ret = nxt_php_set_target(task, &nxt_php_targets[0], conf->self);
3141376St.nateldemoura@f5.com         if (nxt_slow_path(ret != NXT_OK)) {
3151376St.nateldemoura@f5.com             return NXT_ERROR;
3161376St.nateldemoura@f5.com         }
3171376St.nateldemoura@f5.com     }
3181376St.nateldemoura@f5.com 
319857Svbart@nginx.com #ifdef ZTS
3201369St.nateldemoura@f5.com 
3211369St.nateldemoura@f5.com #if PHP_VERSION_ID >= 70400
3221369St.nateldemoura@f5.com     php_tsrm_startup();
3231369St.nateldemoura@f5.com #else
324857Svbart@nginx.com     tsrm_startup(1, 1, 0, NULL);
325857Svbart@nginx.com     tsrm_ls = ts_resource(0);
326857Svbart@nginx.com #endif
327857Svbart@nginx.com 
3281369St.nateldemoura@f5.com #endif
3291369St.nateldemoura@f5.com 
330858Svbart@nginx.com #if defined(NXT_PHP7) && defined(ZEND_SIGNALS)
331858Svbart@nginx.com 
332858Svbart@nginx.com #if (NXT_ZEND_SIGNAL_STARTUP)
333857Svbart@nginx.com     zend_signal_startup();
334858Svbart@nginx.com #elif defined(ZTS)
335858Svbart@nginx.com #error PHP is built with thread safety and broken signals.
336857Svbart@nginx.com #endif
337858Svbart@nginx.com 
338857Svbart@nginx.com #endif
339857Svbart@nginx.com 
340142Smax.romanov@nginx.com     sapi_startup(&nxt_php_sapi_module);
341687Svbart@nginx.com 
342687Svbart@nginx.com     if (c->options != NULL) {
343687Svbart@nginx.com         value = nxt_conf_get_object_member(c->options, &file_str, NULL);
344687Svbart@nginx.com 
345687Svbart@nginx.com         if (value != NULL) {
346687Svbart@nginx.com             nxt_conf_get_string(value, &ini_path);
347687Svbart@nginx.com 
348687Svbart@nginx.com             p = nxt_malloc(ini_path.length + 1);
349687Svbart@nginx.com             if (nxt_slow_path(p == NULL)) {
350687Svbart@nginx.com                 return NXT_ERROR;
351687Svbart@nginx.com             }
352687Svbart@nginx.com 
353687Svbart@nginx.com             nxt_php_sapi_module.php_ini_path_override = (char *) p;
354687Svbart@nginx.com 
355687Svbart@nginx.com             p = nxt_cpymem(p, ini_path.start, ini_path.length);
356687Svbart@nginx.com             *p = '\0';
357687Svbart@nginx.com         }
358687Svbart@nginx.com     }
359687Svbart@nginx.com 
3601376St.nateldemoura@f5.com     if (nxt_slow_path(nxt_php_startup(&nxt_php_sapi_module) == FAILURE)) {
3611376St.nateldemoura@f5.com         nxt_alert(task, "failed to initialize SAPI module and extension");
3621376St.nateldemoura@f5.com         return NXT_ERROR;
3631376St.nateldemoura@f5.com     }
364142Smax.romanov@nginx.com 
365688Svbart@nginx.com     if (c->options != NULL) {
366688Svbart@nginx.com         value = nxt_conf_get_object_member(c->options, &admin_str, NULL);
367688Svbart@nginx.com         nxt_php_set_options(task, value, ZEND_INI_SYSTEM);
368688Svbart@nginx.com 
369688Svbart@nginx.com         value = nxt_conf_get_object_member(c->options, &user_str, NULL);
370688Svbart@nginx.com         nxt_php_set_options(task, value, ZEND_INI_USER);
371688Svbart@nginx.com     }
372688Svbart@nginx.com 
3731519Smax.romanov@nginx.com     ret = nxt_unit_default_init(task, &php_init);
3741519Smax.romanov@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
3751519Smax.romanov@nginx.com         nxt_alert(task, "nxt_unit_default_init() failed");
3761519Smax.romanov@nginx.com         return ret;
377743Smax.romanov@nginx.com     }
378743Smax.romanov@nginx.com 
3791473Svbart@nginx.com     php_init.callbacks.request_handler = nxt_php_request_handler;
3801320Smax.romanov@nginx.com     php_init.shm_limit = conf->shm_limit;
381743Smax.romanov@nginx.com 
382743Smax.romanov@nginx.com     unit_ctx = nxt_unit_init(&php_init);
383743Smax.romanov@nginx.com     if (nxt_slow_path(unit_ctx == NULL)) {
384743Smax.romanov@nginx.com         return NXT_ERROR;
385743Smax.romanov@nginx.com     }
386743Smax.romanov@nginx.com 
3871513Svbart@nginx.com     nxt_php_unit_ctx = unit_ctx;
3881513Svbart@nginx.com 
389743Smax.romanov@nginx.com     nxt_unit_run(unit_ctx);
390743Smax.romanov@nginx.com 
391743Smax.romanov@nginx.com     nxt_unit_done(unit_ctx);
392743Smax.romanov@nginx.com 
393743Smax.romanov@nginx.com     exit(0);
394743Smax.romanov@nginx.com 
3950Sigor@sysoev.ru     return NXT_OK;
3960Sigor@sysoev.ru }
3970Sigor@sysoev.ru 
3980Sigor@sysoev.ru 
3991473Svbart@nginx.com static nxt_int_t
4001473Svbart@nginx.com nxt_php_set_target(nxt_task_t *task, nxt_php_target_t *target,
4011473Svbart@nginx.com     nxt_conf_value_t *conf)
4021473Svbart@nginx.com {
4031473Svbart@nginx.com     u_char            *tmp, *p;
4041473Svbart@nginx.com     nxt_str_t         str;
4051473Svbart@nginx.com     nxt_int_t         ret;
4061473Svbart@nginx.com     nxt_conf_value_t  *value;
4071473Svbart@nginx.com 
4081473Svbart@nginx.com     static nxt_str_t  root_str = nxt_string("root");
4091473Svbart@nginx.com     static nxt_str_t  script_str = nxt_string("script");
4101473Svbart@nginx.com     static nxt_str_t  index_str = nxt_string("index");
4111473Svbart@nginx.com 
4121473Svbart@nginx.com     value = nxt_conf_get_object_member(conf, &root_str, NULL);
4131473Svbart@nginx.com 
4141473Svbart@nginx.com     nxt_conf_get_string(value, &str);
4151473Svbart@nginx.com 
4161473Svbart@nginx.com     tmp = nxt_malloc(str.length + 1);
4171473Svbart@nginx.com     if (nxt_slow_path(tmp == NULL)) {
4181473Svbart@nginx.com         return NXT_ERROR;
4191473Svbart@nginx.com     }
4201473Svbart@nginx.com 
4211473Svbart@nginx.com     p = tmp;
4221473Svbart@nginx.com 
4231473Svbart@nginx.com     p = nxt_cpymem(p, str.start, str.length);
4241473Svbart@nginx.com     *p = '\0';
4251473Svbart@nginx.com 
4261473Svbart@nginx.com     p = nxt_realpath(tmp);
4271473Svbart@nginx.com     if (nxt_slow_path(p == NULL)) {
4281473Svbart@nginx.com         nxt_alert(task, "root realpath(%s) failed %E", tmp, nxt_errno);
4291473Svbart@nginx.com         return NXT_ERROR;
4301473Svbart@nginx.com     }
4311473Svbart@nginx.com 
4321473Svbart@nginx.com     nxt_free(tmp);
4331473Svbart@nginx.com 
4341473Svbart@nginx.com     target->root.length = nxt_strlen(p);
4351473Svbart@nginx.com     target->root.start = p;
4361473Svbart@nginx.com 
4371473Svbart@nginx.com     nxt_php_str_trim_trail(&target->root, '/');
4381473Svbart@nginx.com 
4391473Svbart@nginx.com     value = nxt_conf_get_object_member(conf, &script_str, NULL);
4401473Svbart@nginx.com 
4411473Svbart@nginx.com     if (value != NULL) {
4421473Svbart@nginx.com         nxt_conf_get_string(value, &str);
4431473Svbart@nginx.com 
4441473Svbart@nginx.com         nxt_php_str_trim_lead(&str, '/');
4451473Svbart@nginx.com 
4461473Svbart@nginx.com         tmp = nxt_malloc(target->root.length + 1 + str.length + 1);
4471473Svbart@nginx.com         if (nxt_slow_path(tmp == NULL)) {
4481473Svbart@nginx.com             return NXT_ERROR;
4491473Svbart@nginx.com         }
4501473Svbart@nginx.com 
4511473Svbart@nginx.com         p = tmp;
4521473Svbart@nginx.com 
4531473Svbart@nginx.com         p = nxt_cpymem(p, target->root.start, target->root.length);
4541473Svbart@nginx.com         *p++ = '/';
4551473Svbart@nginx.com 
4561473Svbart@nginx.com         p = nxt_cpymem(p, str.start, str.length);
4571473Svbart@nginx.com         *p = '\0';
4581473Svbart@nginx.com 
4591473Svbart@nginx.com         p = nxt_realpath(tmp);
4601473Svbart@nginx.com         if (nxt_slow_path(p == NULL)) {
4611473Svbart@nginx.com             nxt_alert(task, "script realpath(%s) failed %E", tmp, nxt_errno);
4621473Svbart@nginx.com             return NXT_ERROR;
4631473Svbart@nginx.com         }
4641473Svbart@nginx.com 
4651473Svbart@nginx.com         nxt_free(tmp);
4661473Svbart@nginx.com 
4671473Svbart@nginx.com         target->script_filename.length = nxt_strlen(p);
4681473Svbart@nginx.com         target->script_filename.start = p;
4691473Svbart@nginx.com 
4701473Svbart@nginx.com         if (!nxt_str_start(&target->script_filename,
4711473Svbart@nginx.com                            target->root.start, target->root.length))
4721473Svbart@nginx.com         {
4731473Svbart@nginx.com             nxt_alert(task, "script is not under php root");
4741473Svbart@nginx.com             return NXT_ERROR;
4751473Svbart@nginx.com         }
4761473Svbart@nginx.com 
4771473Svbart@nginx.com         ret = nxt_php_dirname(&target->script_filename,
4781473Svbart@nginx.com                               &target->script_dirname);
4791473Svbart@nginx.com         if (nxt_slow_path(ret != NXT_OK)) {
4801473Svbart@nginx.com             return NXT_ERROR;
4811473Svbart@nginx.com         }
4821473Svbart@nginx.com 
4831473Svbart@nginx.com         target->script_name.length = target->script_filename.length
4841473Svbart@nginx.com                                      - target->root.length;
4851473Svbart@nginx.com         target->script_name.start = target->script_filename.start
4861473Svbart@nginx.com                                     + target->root.length;
4871473Svbart@nginx.com 
4881473Svbart@nginx.com     } else {
4891473Svbart@nginx.com         value = nxt_conf_get_object_member(conf, &index_str, NULL);
4901473Svbart@nginx.com 
4911473Svbart@nginx.com         if (value != NULL) {
4921473Svbart@nginx.com             nxt_conf_get_string(value, &str);
4931473Svbart@nginx.com 
4941473Svbart@nginx.com             tmp = nxt_malloc(str.length);
4951473Svbart@nginx.com             if (nxt_slow_path(tmp == NULL)) {
4961473Svbart@nginx.com                 return NXT_ERROR;
4971473Svbart@nginx.com             }
4981473Svbart@nginx.com 
4991473Svbart@nginx.com             nxt_memcpy(tmp, str.start, str.length);
5001473Svbart@nginx.com 
5011473Svbart@nginx.com             target->index.length = str.length;
5021473Svbart@nginx.com             target->index.start = tmp;
5031473Svbart@nginx.com 
5041473Svbart@nginx.com         } else {
5051473Svbart@nginx.com             nxt_str_set(&target->index, "index.php");
5061473Svbart@nginx.com         }
5071473Svbart@nginx.com     }
5081473Svbart@nginx.com 
5091473Svbart@nginx.com     return NXT_OK;
5101473Svbart@nginx.com }
5111473Svbart@nginx.com 
5121473Svbart@nginx.com 
513688Svbart@nginx.com static void
514688Svbart@nginx.com nxt_php_set_options(nxt_task_t *task, nxt_conf_value_t *options, int type)
515688Svbart@nginx.com {
516688Svbart@nginx.com     uint32_t          next;
517688Svbart@nginx.com     nxt_str_t         name, value;
518688Svbart@nginx.com     nxt_conf_value_t  *value_obj;
519688Svbart@nginx.com 
520688Svbart@nginx.com     if (options != NULL) {
521688Svbart@nginx.com         next = 0;
522688Svbart@nginx.com 
523688Svbart@nginx.com         for ( ;; ) {
524688Svbart@nginx.com             value_obj = nxt_conf_next_object_member(options, &name, &next);
525688Svbart@nginx.com             if (value_obj == NULL) {
526688Svbart@nginx.com                 break;
527688Svbart@nginx.com             }
528688Svbart@nginx.com 
529688Svbart@nginx.com             nxt_conf_get_string(value_obj, &value);
530688Svbart@nginx.com 
531713Svbart@nginx.com             if (nxt_php_alter_option(&name, &value, type) != NXT_OK) {
532688Svbart@nginx.com                 nxt_log(task, NXT_LOG_ERR,
533688Svbart@nginx.com                         "setting PHP option \"%V: %V\" failed", &name, &value);
534861Svbart@nginx.com                 continue;
535861Svbart@nginx.com             }
536861Svbart@nginx.com 
537861Svbart@nginx.com             if (nxt_str_eq(&name, "disable_functions", 17)) {
538861Svbart@nginx.com                 nxt_php_disable(task, "function", &value,
539861Svbart@nginx.com                                 &PG(disable_functions),
540861Svbart@nginx.com                                 zend_disable_function);
541861Svbart@nginx.com                 continue;
542861Svbart@nginx.com             }
543861Svbart@nginx.com 
544861Svbart@nginx.com             if (nxt_str_eq(&name, "disable_classes", 15)) {
545861Svbart@nginx.com                 nxt_php_disable(task, "class", &value,
546861Svbart@nginx.com                                 &PG(disable_classes),
547861Svbart@nginx.com                                 zend_disable_class);
548861Svbart@nginx.com                 continue;
549688Svbart@nginx.com             }
550688Svbart@nginx.com         }
551688Svbart@nginx.com     }
552688Svbart@nginx.com }
553688Svbart@nginx.com 
554688Svbart@nginx.com 
5551376St.nateldemoura@f5.com #ifdef NXT_PHP7
556713Svbart@nginx.com 
557713Svbart@nginx.com static nxt_int_t
558713Svbart@nginx.com nxt_php_alter_option(nxt_str_t *name, nxt_str_t *value, int type)
559713Svbart@nginx.com {
560713Svbart@nginx.com     zend_string     *zs;
561713Svbart@nginx.com     zend_ini_entry  *ini_entry;
562713Svbart@nginx.com 
5631376St.nateldemoura@f5.com     ini_entry = nxt_php_hash_str_find_ptr(EG(ini_directives), name);
5641376St.nateldemoura@f5.com     if (nxt_slow_path(ini_entry == NULL)) {
565713Svbart@nginx.com         return NXT_ERROR;
566713Svbart@nginx.com     }
567713Svbart@nginx.com 
568713Svbart@nginx.com     /* PHP exits on memory allocation errors. */
569713Svbart@nginx.com     zs = zend_string_init((char *) value->start, value->length, 1);
570713Svbart@nginx.com 
571713Svbart@nginx.com     if (ini_entry->on_modify
572713Svbart@nginx.com         && ini_entry->on_modify(ini_entry, zs, ini_entry->mh_arg1,
573713Svbart@nginx.com                                 ini_entry->mh_arg2, ini_entry->mh_arg3,
574713Svbart@nginx.com                                 ZEND_INI_STAGE_ACTIVATE)
575713Svbart@nginx.com            != SUCCESS)
576713Svbart@nginx.com     {
577713Svbart@nginx.com         zend_string_release(zs);
578713Svbart@nginx.com         return NXT_ERROR;
579713Svbart@nginx.com     }
580713Svbart@nginx.com 
581713Svbart@nginx.com     ini_entry->value = zs;
582713Svbart@nginx.com     ini_entry->modifiable = type;
583713Svbart@nginx.com 
584713Svbart@nginx.com     return NXT_OK;
585713Svbart@nginx.com }
586713Svbart@nginx.com 
587713Svbart@nginx.com #else  /* PHP 5. */
588713Svbart@nginx.com 
589713Svbart@nginx.com static nxt_int_t
590713Svbart@nginx.com nxt_php_alter_option(nxt_str_t *name, nxt_str_t *value, int type)
591713Svbart@nginx.com {
592713Svbart@nginx.com     char            *cstr;
593713Svbart@nginx.com     zend_ini_entry  *ini_entry;
594713Svbart@nginx.com 
5951376St.nateldemoura@f5.com     ini_entry = nxt_php_hash_str_find_ptr(EG(ini_directives), name);
5961376St.nateldemoura@f5.com     if (nxt_slow_path(ini_entry == NULL)) {
597713Svbart@nginx.com         return NXT_ERROR;
598713Svbart@nginx.com     }
599713Svbart@nginx.com 
600713Svbart@nginx.com     cstr = nxt_malloc(value->length + 1);
601713Svbart@nginx.com     if (nxt_slow_path(cstr == NULL)) {
602713Svbart@nginx.com         return NXT_ERROR;
603713Svbart@nginx.com     }
604713Svbart@nginx.com 
605713Svbart@nginx.com     nxt_memcpy(cstr, value->start, value->length);
606713Svbart@nginx.com     cstr[value->length] = '\0';
607713Svbart@nginx.com 
608713Svbart@nginx.com     if (ini_entry->on_modify
609713Svbart@nginx.com         && ini_entry->on_modify(ini_entry, cstr, value->length,
610713Svbart@nginx.com                                 ini_entry->mh_arg1, ini_entry->mh_arg2,
611857Svbart@nginx.com                                 ini_entry->mh_arg3, ZEND_INI_STAGE_ACTIVATE
612857Svbart@nginx.com                                 TSRMLS_CC)
613713Svbart@nginx.com            != SUCCESS)
614713Svbart@nginx.com     {
615713Svbart@nginx.com         nxt_free(cstr);
616713Svbart@nginx.com         return NXT_ERROR;
617713Svbart@nginx.com     }
618713Svbart@nginx.com 
619713Svbart@nginx.com     ini_entry->value = cstr;
620713Svbart@nginx.com     ini_entry->value_length = value->length;
621713Svbart@nginx.com     ini_entry->modifiable = type;
622713Svbart@nginx.com 
623713Svbart@nginx.com     return NXT_OK;
624713Svbart@nginx.com }
625713Svbart@nginx.com 
626713Svbart@nginx.com #endif
627713Svbart@nginx.com 
628713Svbart@nginx.com 
629743Smax.romanov@nginx.com static void
630861Svbart@nginx.com nxt_php_disable(nxt_task_t *task, const char *type, nxt_str_t *value,
631861Svbart@nginx.com     char **ptr, nxt_php_disable_t disable)
632861Svbart@nginx.com {
633861Svbart@nginx.com     char  c, *p, *start;
634861Svbart@nginx.com 
635861Svbart@nginx.com     p = nxt_malloc(value->length + 1);
636861Svbart@nginx.com     if (nxt_slow_path(p == NULL)) {
637861Svbart@nginx.com         return;
638861Svbart@nginx.com     }
639861Svbart@nginx.com 
640861Svbart@nginx.com     /*
641861Svbart@nginx.com      * PHP frees this memory on module shutdown.
642861Svbart@nginx.com      * See core_globals_dtor() for details.
643861Svbart@nginx.com      */
644861Svbart@nginx.com     *ptr = p;
645861Svbart@nginx.com 
646861Svbart@nginx.com     nxt_memcpy(p, value->start, value->length);
647861Svbart@nginx.com     p[value->length] = '\0';
648861Svbart@nginx.com 
649861Svbart@nginx.com     start = p;
650861Svbart@nginx.com 
651861Svbart@nginx.com     do {
652861Svbart@nginx.com         c = *p;
653861Svbart@nginx.com 
654861Svbart@nginx.com         if (c == ' ' || c == ',' || c == '\0') {
655861Svbart@nginx.com 
656861Svbart@nginx.com             if (p != start) {
657861Svbart@nginx.com                 *p = '\0';
658861Svbart@nginx.com 
659861Svbart@nginx.com #ifdef NXT_PHP7
660861Svbart@nginx.com                 if (disable(start, p - start)
661861Svbart@nginx.com #else
662861Svbart@nginx.com                 if (disable(start, p - start TSRMLS_CC)
663861Svbart@nginx.com #endif
664861Svbart@nginx.com                     != SUCCESS)
665861Svbart@nginx.com                 {
666861Svbart@nginx.com                     nxt_log(task, NXT_LOG_ERR,
667861Svbart@nginx.com                             "PHP: failed to disable \"%s\": no such %s",
668861Svbart@nginx.com                             start, type);
669861Svbart@nginx.com                 }
670861Svbart@nginx.com             }
671861Svbart@nginx.com 
672861Svbart@nginx.com             start = p + 1;
673861Svbart@nginx.com         }
674861Svbart@nginx.com 
675861Svbart@nginx.com         p++;
676861Svbart@nginx.com 
677861Svbart@nginx.com     } while (c != '\0');
678861Svbart@nginx.com }
679861Svbart@nginx.com 
680861Svbart@nginx.com 
6811376St.nateldemoura@f5.com static nxt_int_t
6821376St.nateldemoura@f5.com nxt_php_dirname(const nxt_str_t *file, nxt_str_t *dir)
6831376St.nateldemoura@f5.com {
6841376St.nateldemoura@f5.com     size_t  length;
6851376St.nateldemoura@f5.com 
6861517Smax.romanov@nginx.com     if (file->length == 0 || file->start[0] != '/') {
6871517Smax.romanov@nginx.com         nxt_unit_alert(NULL, "php_dirname: invalid file name "
6881517Smax.romanov@nginx.com                        "(not starts from '/')");
6891517Smax.romanov@nginx.com         return NXT_ERROR;
6901517Smax.romanov@nginx.com     }
6911376St.nateldemoura@f5.com 
6921376St.nateldemoura@f5.com     length = file->length;
6931376St.nateldemoura@f5.com 
6941376St.nateldemoura@f5.com     while (file->start[length - 1] != '/') {
6951376St.nateldemoura@f5.com         length--;
6961376St.nateldemoura@f5.com     }
6971376St.nateldemoura@f5.com 
6981376St.nateldemoura@f5.com     dir->length = length;
6991376St.nateldemoura@f5.com     dir->start = nxt_malloc(length + 1);
7001376St.nateldemoura@f5.com     if (nxt_slow_path(dir->start == NULL)) {
7011376St.nateldemoura@f5.com         return NXT_ERROR;
7021376St.nateldemoura@f5.com     }
7031376St.nateldemoura@f5.com 
7041376St.nateldemoura@f5.com     nxt_memcpy(dir->start, file->start, length);
7051376St.nateldemoura@f5.com 
7061376St.nateldemoura@f5.com     dir->start[length] = '\0';
7071376St.nateldemoura@f5.com 
7081376St.nateldemoura@f5.com     return NXT_OK;
7091376St.nateldemoura@f5.com }
7101376St.nateldemoura@f5.com 
7111376St.nateldemoura@f5.com 
712861Svbart@nginx.com static void
713743Smax.romanov@nginx.com nxt_php_str_trim_trail(nxt_str_t *str, u_char t)
7140Sigor@sysoev.ru {
715743Smax.romanov@nginx.com     while (str->length > 0 && str->start[str->length - 1] == t) {
716743Smax.romanov@nginx.com         str->length--;
7170Sigor@sysoev.ru     }
7180Sigor@sysoev.ru 
719743Smax.romanov@nginx.com     str->start[str->length] = '\0';
720743Smax.romanov@nginx.com }
721743Smax.romanov@nginx.com 
722743Smax.romanov@nginx.com 
723743Smax.romanov@nginx.com static void
724743Smax.romanov@nginx.com nxt_php_str_trim_lead(nxt_str_t *str, u_char t)
725743Smax.romanov@nginx.com {
726743Smax.romanov@nginx.com     while (str->length > 0 && str->start[0] == t) {
727743Smax.romanov@nginx.com         str->length--;
728743Smax.romanov@nginx.com         str->start++;
729112Smax.romanov@nginx.com     }
730743Smax.romanov@nginx.com }
731743Smax.romanov@nginx.com 
732743Smax.romanov@nginx.com 
733743Smax.romanov@nginx.com nxt_inline u_char *
734743Smax.romanov@nginx.com nxt_realpath(const void *c)
735743Smax.romanov@nginx.com {
736743Smax.romanov@nginx.com     return (u_char *) realpath(c, NULL);
737743Smax.romanov@nginx.com }
738743Smax.romanov@nginx.com 
739743Smax.romanov@nginx.com 
740743Smax.romanov@nginx.com static void
7411473Svbart@nginx.com nxt_php_request_handler(nxt_unit_request_info_t *req)
742743Smax.romanov@nginx.com {
7431473Svbart@nginx.com     nxt_php_target_t    *target;
7441473Svbart@nginx.com     nxt_php_run_ctx_t   ctx;
7451473Svbart@nginx.com     nxt_unit_request_t  *r;
7461473Svbart@nginx.com 
7471473Svbart@nginx.com     r = req->request;
7481473Svbart@nginx.com     target = &nxt_php_targets[r->app_target];
7491376St.nateldemoura@f5.com 
7501376St.nateldemoura@f5.com     nxt_memzero(&ctx, sizeof(ctx));
7511376St.nateldemoura@f5.com 
7521376St.nateldemoura@f5.com     ctx.req = req;
7531473Svbart@nginx.com     ctx.root = &target->root;
7541473Svbart@nginx.com     ctx.index = &target->index;
7551376St.nateldemoura@f5.com 
7561473Svbart@nginx.com     if (target->script_filename.length == 0) {
7571473Svbart@nginx.com         nxt_php_dynamic_request(&ctx, r);
7581376St.nateldemoura@f5.com         return;
7591376St.nateldemoura@f5.com     }
7601376St.nateldemoura@f5.com 
7611473Svbart@nginx.com     ctx.script_filename = target->script_filename;
7621473Svbart@nginx.com     ctx.script_dirname = target->script_dirname;
7631473Svbart@nginx.com     ctx.script_name = target->script_name;
7641376St.nateldemoura@f5.com 
7651473Svbart@nginx.com     ctx.chdir = (r->app_target != nxt_php_last_target);
7661376St.nateldemoura@f5.com 
7671473Svbart@nginx.com     nxt_php_execute(&ctx, r);
7681376St.nateldemoura@f5.com 
7691473Svbart@nginx.com     nxt_php_last_target = ctx.chdir ? -1 : r->app_target;
7701376St.nateldemoura@f5.com }
7711376St.nateldemoura@f5.com 
7721376St.nateldemoura@f5.com 
7731376St.nateldemoura@f5.com static void
7741473Svbart@nginx.com nxt_php_dynamic_request(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r)
7751376St.nateldemoura@f5.com {
7761473Svbart@nginx.com     u_char     *p;
7771473Svbart@nginx.com     nxt_str_t  path, script_name;
7781473Svbart@nginx.com     nxt_int_t  ret;
779743Smax.romanov@nginx.com 
780743Smax.romanov@nginx.com     path.length = r->path_length;
781743Smax.romanov@nginx.com     path.start = nxt_unit_sptr_get(&r->path);
782112Smax.romanov@nginx.com 
7831376St.nateldemoura@f5.com     nxt_str_null(&script_name);
7841345Svbart@nginx.com 
7851376St.nateldemoura@f5.com     ctx->path_info.start = (u_char *) strstr((char *) path.start, ".php/");
7861376St.nateldemoura@f5.com     if (ctx->path_info.start != NULL) {
7871376St.nateldemoura@f5.com         ctx->path_info.start += 4;
7881376St.nateldemoura@f5.com         path.length = ctx->path_info.start - path.start;
7891091Smax.romanov@nginx.com 
7901376St.nateldemoura@f5.com         ctx->path_info.length = r->path_length - path.length;
791277Sigor@sysoev.ru 
7921376St.nateldemoura@f5.com     } else if (path.start[path.length - 1] == '/') {
7931473Svbart@nginx.com         script_name = *ctx->index;
7941345Svbart@nginx.com 
7951376St.nateldemoura@f5.com     } else {
7961376St.nateldemoura@f5.com         if (nxt_slow_path(path.length < 4
7971376St.nateldemoura@f5.com                           || nxt_memcmp(path.start + (path.length - 4),
7981376St.nateldemoura@f5.com                                         ".php", 4)))
7991376St.nateldemoura@f5.com         {
8001473Svbart@nginx.com             nxt_unit_request_done(ctx->req, NXT_UNIT_ERROR);
801743Smax.romanov@nginx.com 
802743Smax.romanov@nginx.com             return;
803462Smax.romanov@nginx.com         }
8041376St.nateldemoura@f5.com     }
8051091Smax.romanov@nginx.com 
8061473Svbart@nginx.com     ctx->script_filename.length = ctx->root->length
8071376St.nateldemoura@f5.com                                   + path.length
8081376St.nateldemoura@f5.com                                   + script_name.length;
8091091Smax.romanov@nginx.com 
8101376St.nateldemoura@f5.com     p = nxt_malloc(ctx->script_filename.length + 1);
8111376St.nateldemoura@f5.com     if (nxt_slow_path(p == NULL)) {
8121473Svbart@nginx.com         nxt_unit_request_done(ctx->req, NXT_UNIT_ERROR);
81394Smax.romanov@nginx.com 
8141376St.nateldemoura@f5.com         return;
8151376St.nateldemoura@f5.com     }
8161376St.nateldemoura@f5.com 
8171376St.nateldemoura@f5.com     ctx->script_filename.start = p;
81894Smax.romanov@nginx.com 
8191376St.nateldemoura@f5.com     ctx->script_name.length = path.length + script_name.length;
8201473Svbart@nginx.com     ctx->script_name.start = p + ctx->root->length;
821464Smax.romanov@nginx.com 
8221473Svbart@nginx.com     p = nxt_cpymem(p, ctx->root->start, ctx->root->length);
8231376St.nateldemoura@f5.com     p = nxt_cpymem(p, path.start, path.length);
8241376St.nateldemoura@f5.com 
8251376St.nateldemoura@f5.com     if (script_name.length > 0) {
8261376St.nateldemoura@f5.com         p = nxt_cpymem(p, script_name.start, script_name.length);
82786Smax.romanov@nginx.com     }
82886Smax.romanov@nginx.com 
8291376St.nateldemoura@f5.com     *p = '\0';
8301376St.nateldemoura@f5.com 
8311473Svbart@nginx.com     ctx->chdir = 1;
8321376St.nateldemoura@f5.com 
8331376St.nateldemoura@f5.com     ret = nxt_php_dirname(&ctx->script_filename, &ctx->script_dirname);
8341376St.nateldemoura@f5.com     if (nxt_slow_path(ret != NXT_OK)) {
8351473Svbart@nginx.com         nxt_unit_request_done(ctx->req, NXT_UNIT_ERROR);
8361376St.nateldemoura@f5.com         nxt_free(ctx->script_filename.start);
8371376St.nateldemoura@f5.com 
8381376St.nateldemoura@f5.com         return;
8391376St.nateldemoura@f5.com     }
8401376St.nateldemoura@f5.com 
8411473Svbart@nginx.com     nxt_php_execute(ctx, r);
8421376St.nateldemoura@f5.com 
8431376St.nateldemoura@f5.com     nxt_free(ctx->script_filename.start);
8441376St.nateldemoura@f5.com     nxt_free(ctx->script_dirname.start);
8451473Svbart@nginx.com 
8461473Svbart@nginx.com     nxt_php_last_target = -1;
8471376St.nateldemoura@f5.com }
8481376St.nateldemoura@f5.com 
8491376St.nateldemoura@f5.com 
8501473Svbart@nginx.com static void
8511473Svbart@nginx.com nxt_php_execute(nxt_php_run_ctx_t *ctx, nxt_unit_request_t *r)
8521376St.nateldemoura@f5.com {
8531376St.nateldemoura@f5.com     nxt_unit_field_t  *f;
8541473Svbart@nginx.com     zend_file_handle  file_handle;
8551473Svbart@nginx.com 
8561473Svbart@nginx.com     nxt_unit_req_debug(ctx->req, "PHP execute script %s",
8571473Svbart@nginx.com                        ctx->script_filename.start);
8581376St.nateldemoura@f5.com 
859743Smax.romanov@nginx.com     SG(server_context) = ctx;
8601376St.nateldemoura@f5.com     SG(options) |= SAPI_OPTION_NO_CHDIR;
861743Smax.romanov@nginx.com     SG(request_info).request_uri = nxt_unit_sptr_get(&r->target);
862743Smax.romanov@nginx.com     SG(request_info).request_method = nxt_unit_sptr_get(&r->method);
8630Sigor@sysoev.ru 
8640Sigor@sysoev.ru     SG(request_info).proto_num = 1001;
8650Sigor@sysoev.ru 
866743Smax.romanov@nginx.com     SG(request_info).query_string = r->query.offset
867743Smax.romanov@nginx.com                                     ? nxt_unit_sptr_get(&r->query) : NULL;
868743Smax.romanov@nginx.com     SG(request_info).content_length = r->content_length;
869743Smax.romanov@nginx.com 
870743Smax.romanov@nginx.com     if (r->content_type_field != NXT_UNIT_NONE_FIELD) {
871743Smax.romanov@nginx.com         f = r->fields + r->content_type_field;
8720Sigor@sysoev.ru 
873743Smax.romanov@nginx.com         SG(request_info).content_type = nxt_unit_sptr_get(&f->value);
874743Smax.romanov@nginx.com     }
875743Smax.romanov@nginx.com 
876743Smax.romanov@nginx.com     if (r->cookie_field != NXT_UNIT_NONE_FIELD) {
877743Smax.romanov@nginx.com         f = r->fields + r->cookie_field;
878743Smax.romanov@nginx.com 
879743Smax.romanov@nginx.com         ctx->cookie = nxt_unit_sptr_get(&f->value);
8800Sigor@sysoev.ru     }
8810Sigor@sysoev.ru 
8820Sigor@sysoev.ru     SG(sapi_headers).http_response_code = 200;
8830Sigor@sysoev.ru 
8840Sigor@sysoev.ru     SG(request_info).path_translated = NULL;
8850Sigor@sysoev.ru 
8861376St.nateldemoura@f5.com #ifdef NXT_PHP7
8870Sigor@sysoev.ru     if (nxt_slow_path(php_request_startup() == FAILURE)) {
888857Svbart@nginx.com #else
889857Svbart@nginx.com     if (nxt_slow_path(php_request_startup(TSRMLS_C) == FAILURE)) {
890857Svbart@nginx.com #endif
8911376St.nateldemoura@f5.com         nxt_unit_req_debug(ctx->req, "php_request_startup() failed");
892743Smax.romanov@nginx.com 
8931473Svbart@nginx.com         nxt_unit_request_done(ctx->req, NXT_UNIT_ERROR);
8941473Svbart@nginx.com         return;
8951473Svbart@nginx.com     }
8961473Svbart@nginx.com 
8971473Svbart@nginx.com     if (ctx->chdir) {
8981473Svbart@nginx.com         ctx->chdir = 0;
8991473Svbart@nginx.com         nxt_php_vcwd_chdir(ctx->req, ctx->script_dirname.start);
9000Sigor@sysoev.ru     }
9010Sigor@sysoev.ru 
9021473Svbart@nginx.com     nxt_memzero(&file_handle, sizeof(file_handle));
9031473Svbart@nginx.com 
9041473Svbart@nginx.com     file_handle.type = ZEND_HANDLE_FILENAME;
9051473Svbart@nginx.com     file_handle.filename = (char *) ctx->script_filename.start;
9061473Svbart@nginx.com 
9071473Svbart@nginx.com     php_execute_script(&file_handle TSRMLS_CC);
9081473Svbart@nginx.com 
9091473Svbart@nginx.com     php_request_shutdown(NULL);
9101473Svbart@nginx.com 
9111473Svbart@nginx.com     nxt_unit_request_done(ctx->req, NXT_UNIT_OK);
9120Sigor@sysoev.ru }
9130Sigor@sysoev.ru 
9140Sigor@sysoev.ru 
9151376St.nateldemoura@f5.com nxt_inline void
9161473Svbart@nginx.com nxt_php_vcwd_chdir(nxt_unit_request_info_t *req, u_char *dir)
9170Sigor@sysoev.ru {
9181473Svbart@nginx.com     if (nxt_slow_path(VCWD_CHDIR((char *) dir) != 0)) {
9191385St.nateldemoura@f5.com         nxt_unit_req_alert(req, "VCWD_CHDIR(%s) failed (%d: %s)",
9201473Svbart@nginx.com                            dir, errno, strerror(errno));
9211376St.nateldemoura@f5.com     }
9220Sigor@sysoev.ru }
9230Sigor@sysoev.ru 
9240Sigor@sysoev.ru 
9251473Svbart@nginx.com static int
9261473Svbart@nginx.com nxt_php_startup(sapi_module_struct *sapi_module)
9271473Svbart@nginx.com {
9281473Svbart@nginx.com     return php_module_startup(sapi_module, &nxt_php_unit_module, 1);
9291473Svbart@nginx.com }
9301473Svbart@nginx.com 
9311473Svbart@nginx.com 
9320Sigor@sysoev.ru #ifdef NXT_PHP7
9330Sigor@sysoev.ru static size_t
9340Sigor@sysoev.ru nxt_php_unbuffered_write(const char *str, size_t str_length TSRMLS_DC)
9350Sigor@sysoev.ru #else
9360Sigor@sysoev.ru static int
9370Sigor@sysoev.ru nxt_php_unbuffered_write(const char *str, uint str_length TSRMLS_DC)
9380Sigor@sysoev.ru #endif
9390Sigor@sysoev.ru {
940743Smax.romanov@nginx.com     int                rc;
94186Smax.romanov@nginx.com     nxt_php_run_ctx_t  *ctx;
9420Sigor@sysoev.ru 
94386Smax.romanov@nginx.com     ctx = SG(server_context);
9440Sigor@sysoev.ru 
945743Smax.romanov@nginx.com     rc = nxt_unit_response_write(ctx->req, str, str_length);
946743Smax.romanov@nginx.com     if (nxt_fast_path(rc == NXT_UNIT_OK)) {
947114Smax.romanov@nginx.com         return str_length;
948114Smax.romanov@nginx.com     }
9490Sigor@sysoev.ru 
950114Smax.romanov@nginx.com     php_handle_aborted_connection();
951114Smax.romanov@nginx.com     return 0;
952114Smax.romanov@nginx.com }
953114Smax.romanov@nginx.com 
954114Smax.romanov@nginx.com 
9550Sigor@sysoev.ru static int
9560Sigor@sysoev.ru nxt_php_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
9570Sigor@sysoev.ru {
958743Smax.romanov@nginx.com     int                      rc, fields_count;
9591090Svbart@nginx.com     char                     *colon, *value;
960743Smax.romanov@nginx.com     uint16_t                 status;
961743Smax.romanov@nginx.com     uint32_t                 resp_size;
962743Smax.romanov@nginx.com     nxt_php_run_ctx_t        *ctx;
963743Smax.romanov@nginx.com     sapi_header_struct       *h;
964743Smax.romanov@nginx.com     zend_llist_position      zpos;
965743Smax.romanov@nginx.com     nxt_unit_request_info_t  *req;
96686Smax.romanov@nginx.com 
96786Smax.romanov@nginx.com     ctx = SG(server_context);
968743Smax.romanov@nginx.com     req = ctx->req;
9690Sigor@sysoev.ru 
970743Smax.romanov@nginx.com     nxt_unit_req_debug(req, "nxt_php_send_headers");
971114Smax.romanov@nginx.com 
9720Sigor@sysoev.ru     if (SG(request_info).no_headers == 1) {
973743Smax.romanov@nginx.com         rc = nxt_unit_response_init(req, 200, 0, 0);
974743Smax.romanov@nginx.com         if (nxt_slow_path(rc != NXT_UNIT_OK)) {
975743Smax.romanov@nginx.com             return SAPI_HEADER_SEND_FAILED;
976743Smax.romanov@nginx.com         }
977743Smax.romanov@nginx.com 
9780Sigor@sysoev.ru         return SAPI_HEADER_SENT_SUCCESSFULLY;
9790Sigor@sysoev.ru     }
9800Sigor@sysoev.ru 
981743Smax.romanov@nginx.com     resp_size = 0;
982743Smax.romanov@nginx.com     fields_count = zend_llist_count(&sapi_headers->headers);
983743Smax.romanov@nginx.com 
984743Smax.romanov@nginx.com     for (h = zend_llist_get_first_ex(&sapi_headers->headers, &zpos);
985743Smax.romanov@nginx.com          h;
986743Smax.romanov@nginx.com          h = zend_llist_get_next_ex(&sapi_headers->headers, &zpos))
987743Smax.romanov@nginx.com     {
988743Smax.romanov@nginx.com         resp_size += h->header_len;
989743Smax.romanov@nginx.com     }
990743Smax.romanov@nginx.com 
9911090Svbart@nginx.com     status = SG(sapi_headers).http_response_code;
992743Smax.romanov@nginx.com 
993743Smax.romanov@nginx.com     rc = nxt_unit_response_init(req, status, fields_count, resp_size);
994743Smax.romanov@nginx.com     if (nxt_slow_path(rc != NXT_UNIT_OK)) {
995743Smax.romanov@nginx.com         return SAPI_HEADER_SEND_FAILED;
9960Sigor@sysoev.ru     }
9970Sigor@sysoev.ru 
998743Smax.romanov@nginx.com     for (h = zend_llist_get_first_ex(&sapi_headers->headers, &zpos);
999743Smax.romanov@nginx.com          h;
1000743Smax.romanov@nginx.com          h = zend_llist_get_next_ex(&sapi_headers->headers, &zpos))
1001743Smax.romanov@nginx.com     {
1002743Smax.romanov@nginx.com         colon = memchr(h->header, ':', h->header_len);
1003743Smax.romanov@nginx.com         if (nxt_slow_path(colon == NULL)) {
1004743Smax.romanov@nginx.com             nxt_unit_req_warn(req, "colon not found in header '%.*s'",
1005743Smax.romanov@nginx.com                               (int) h->header_len, h->header);
1006743Smax.romanov@nginx.com             continue;
1007743Smax.romanov@nginx.com         }
10080Sigor@sysoev.ru 
1009743Smax.romanov@nginx.com         value = colon + 1;
1010743Smax.romanov@nginx.com         while(isspace(*value)) {
1011743Smax.romanov@nginx.com             value++;
1012743Smax.romanov@nginx.com         }
1013743Smax.romanov@nginx.com 
1014743Smax.romanov@nginx.com         nxt_unit_response_add_field(req, h->header, colon - h->header,
1015743Smax.romanov@nginx.com                                     value,
1016743Smax.romanov@nginx.com                                     h->header_len - (value - h->header));
10170Sigor@sysoev.ru     }
10180Sigor@sysoev.ru 
1019743Smax.romanov@nginx.com     rc = nxt_unit_response_send(req);
1020743Smax.romanov@nginx.com     if (nxt_slow_path(rc != NXT_UNIT_OK)) {
1021743Smax.romanov@nginx.com         nxt_unit_req_debug(req, "failed to send response");
1022114Smax.romanov@nginx.com 
1023743Smax.romanov@nginx.com         return SAPI_HEADER_SEND_FAILED;
1024743Smax.romanov@nginx.com     }
10250Sigor@sysoev.ru 
10260Sigor@sysoev.ru     return SAPI_HEADER_SENT_SUCCESSFULLY;
10270Sigor@sysoev.ru }
10280Sigor@sysoev.ru 
10290Sigor@sysoev.ru 
10300Sigor@sysoev.ru #ifdef NXT_PHP7
10310Sigor@sysoev.ru static size_t
10320Sigor@sysoev.ru nxt_php_read_post(char *buffer, size_t count_bytes TSRMLS_DC)
10330Sigor@sysoev.ru #else
10340Sigor@sysoev.ru static int
10350Sigor@sysoev.ru nxt_php_read_post(char *buffer, uint count_bytes TSRMLS_DC)
10360Sigor@sysoev.ru #endif
10370Sigor@sysoev.ru {
1038743Smax.romanov@nginx.com     nxt_php_run_ctx_t  *ctx;
10390Sigor@sysoev.ru 
104086Smax.romanov@nginx.com     ctx = SG(server_context);
10410Sigor@sysoev.ru 
1042743Smax.romanov@nginx.com     nxt_unit_req_debug(ctx->req, "nxt_php_read_post %d", (int) count_bytes);
10430Sigor@sysoev.ru 
1044743Smax.romanov@nginx.com     return nxt_unit_request_read(ctx->req, buffer, count_bytes);
10450Sigor@sysoev.ru }
10460Sigor@sysoev.ru 
10470Sigor@sysoev.ru 
10480Sigor@sysoev.ru static char *
10490Sigor@sysoev.ru nxt_php_read_cookies(TSRMLS_D)
10500Sigor@sysoev.ru {
105186Smax.romanov@nginx.com     nxt_php_run_ctx_t  *ctx;
10520Sigor@sysoev.ru 
105386Smax.romanov@nginx.com     ctx = SG(server_context);
10540Sigor@sysoev.ru 
1055743Smax.romanov@nginx.com     nxt_unit_req_debug(ctx->req, "nxt_php_read_cookies");
105694Smax.romanov@nginx.com 
1057743Smax.romanov@nginx.com     return ctx->cookie;
10580Sigor@sysoev.ru }
10590Sigor@sysoev.ru 
10600Sigor@sysoev.ru 
10610Sigor@sysoev.ru static void
10620Sigor@sysoev.ru nxt_php_register_variables(zval *track_vars_array TSRMLS_DC)
10630Sigor@sysoev.ru {
1064743Smax.romanov@nginx.com     const char               *name;
1065743Smax.romanov@nginx.com     nxt_unit_field_t         *f, *f_end;
1066743Smax.romanov@nginx.com     nxt_php_run_ctx_t        *ctx;
1067743Smax.romanov@nginx.com     nxt_unit_request_t       *r;
1068743Smax.romanov@nginx.com     nxt_unit_request_info_t  *req;
1069114Smax.romanov@nginx.com 
107086Smax.romanov@nginx.com     ctx = SG(server_context);
10710Sigor@sysoev.ru 
1072743Smax.romanov@nginx.com     req = ctx->req;
1073743Smax.romanov@nginx.com     r = req->request;
10740Sigor@sysoev.ru 
1075743Smax.romanov@nginx.com     nxt_unit_req_debug(req, "nxt_php_register_variables");
10760Sigor@sysoev.ru 
1077743Smax.romanov@nginx.com     php_register_variable_safe((char *) "SERVER_SOFTWARE",
1078743Smax.romanov@nginx.com                                (char *) nxt_server.start,
1079743Smax.romanov@nginx.com                                nxt_server.length, track_vars_array TSRMLS_CC);
1080114Smax.romanov@nginx.com 
1081743Smax.romanov@nginx.com     nxt_php_set_sptr(req, "SERVER_PROTOCOL", &r->version, r->version_length,
1082743Smax.romanov@nginx.com                      track_vars_array TSRMLS_CC);
108386Smax.romanov@nginx.com 
10841091Smax.romanov@nginx.com     /*
10851091Smax.romanov@nginx.com      * 'PHP_SELF'
10861091Smax.romanov@nginx.com      * The filename of the currently executing script, relative to the document
10871091Smax.romanov@nginx.com      * root.  For instance, $_SERVER['PHP_SELF'] in a script at the address
10881091Smax.romanov@nginx.com      * http://example.com/foo/bar.php would be /foo/bar.php.  The __FILE__
10891091Smax.romanov@nginx.com      * constant contains the full path and filename of the current (i.e.
10901091Smax.romanov@nginx.com      * included) file.  If PHP is running as a command-line processor this
10911091Smax.romanov@nginx.com      * variable contains the script name since PHP 4.3.0. Previously it was not
10921091Smax.romanov@nginx.com      * available.
10931091Smax.romanov@nginx.com      */
109486Smax.romanov@nginx.com 
10951473Svbart@nginx.com     if (ctx->path_info.length != 0) {
10961473Svbart@nginx.com         nxt_php_set_sptr(req, "PHP_SELF", &r->path, r->path_length,
10971473Svbart@nginx.com                          track_vars_array TSRMLS_CC);
10981473Svbart@nginx.com 
10991473Svbart@nginx.com         nxt_php_set_str(req, "PATH_INFO", &ctx->path_info,
1100743Smax.romanov@nginx.com                         track_vars_array TSRMLS_CC);
1101277Sigor@sysoev.ru 
110286Smax.romanov@nginx.com     } else {
11031473Svbart@nginx.com         nxt_php_set_str(req, "PHP_SELF", &ctx->script_name,
11041091Smax.romanov@nginx.com                         track_vars_array TSRMLS_CC);
110586Smax.romanov@nginx.com     }
11060Sigor@sysoev.ru 
11071091Smax.romanov@nginx.com     /*
11081091Smax.romanov@nginx.com      * 'SCRIPT_NAME'
11091091Smax.romanov@nginx.com      * Contains the current script's path.  This is useful for pages which need
11101091Smax.romanov@nginx.com      * to point to themselves.  The __FILE__ constant contains the full path and
11111091Smax.romanov@nginx.com      * filename of the current (i.e. included) file.
11121091Smax.romanov@nginx.com      */
11131091Smax.romanov@nginx.com 
11141091Smax.romanov@nginx.com     nxt_php_set_str(req, "SCRIPT_NAME", &ctx->script_name,
1115743Smax.romanov@nginx.com                     track_vars_array TSRMLS_CC);
11161091Smax.romanov@nginx.com 
11171091Smax.romanov@nginx.com     /*
11181091Smax.romanov@nginx.com      * 'SCRIPT_FILENAME'
11191091Smax.romanov@nginx.com      * The absolute pathname of the currently executing script.
11201091Smax.romanov@nginx.com      */
11211091Smax.romanov@nginx.com 
11221091Smax.romanov@nginx.com     nxt_php_set_str(req, "SCRIPT_FILENAME", &ctx->script_filename,
11231091Smax.romanov@nginx.com                     track_vars_array TSRMLS_CC);
11241091Smax.romanov@nginx.com 
11251091Smax.romanov@nginx.com     /*
11261091Smax.romanov@nginx.com      * 'DOCUMENT_ROOT'
11271091Smax.romanov@nginx.com      * The document root directory under which the current script is executing,
11281091Smax.romanov@nginx.com      * as defined in the server's configuration file.
11291091Smax.romanov@nginx.com      */
11301091Smax.romanov@nginx.com 
11311473Svbart@nginx.com     nxt_php_set_str(req, "DOCUMENT_ROOT", ctx->root,
1132743Smax.romanov@nginx.com                     track_vars_array TSRMLS_CC);
11330Sigor@sysoev.ru 
1134743Smax.romanov@nginx.com     nxt_php_set_sptr(req, "REQUEST_METHOD", &r->method, r->method_length,
1135743Smax.romanov@nginx.com                      track_vars_array TSRMLS_CC);
1136743Smax.romanov@nginx.com     nxt_php_set_sptr(req, "REQUEST_URI", &r->target, r->target_length,
1137743Smax.romanov@nginx.com                      track_vars_array TSRMLS_CC);
1138981Svbart@nginx.com     nxt_php_set_sptr(req, "QUERY_STRING", &r->query, r->query_length,
1139981Svbart@nginx.com                      track_vars_array TSRMLS_CC);
11400Sigor@sysoev.ru 
1141743Smax.romanov@nginx.com     nxt_php_set_sptr(req, "REMOTE_ADDR", &r->remote, r->remote_length,
1142743Smax.romanov@nginx.com                      track_vars_array TSRMLS_CC);
1143743Smax.romanov@nginx.com     nxt_php_set_sptr(req, "SERVER_ADDR", &r->local, r->local_length,
1144743Smax.romanov@nginx.com                      track_vars_array TSRMLS_CC);
11450Sigor@sysoev.ru 
1146967Svbart@nginx.com     nxt_php_set_sptr(req, "SERVER_NAME", &r->server_name, r->server_name_length,
1147967Svbart@nginx.com                      track_vars_array TSRMLS_CC);
1148967Svbart@nginx.com     nxt_php_set_cstr(req, "SERVER_PORT", "80", 2, track_vars_array TSRMLS_CC);
1149967Svbart@nginx.com 
11501011Smax.romanov@nginx.com     if (r->tls) {
11511011Smax.romanov@nginx.com         nxt_php_set_cstr(req, "HTTPS", "on", 2, track_vars_array TSRMLS_CC);
11521011Smax.romanov@nginx.com     }
11531011Smax.romanov@nginx.com 
1154743Smax.romanov@nginx.com     f_end = r->fields + r->fields_count;
1155743Smax.romanov@nginx.com     for (f = r->fields; f < f_end; f++) {
1156743Smax.romanov@nginx.com         name = nxt_unit_sptr_get(&f->name);
1157743Smax.romanov@nginx.com 
1158743Smax.romanov@nginx.com         nxt_php_set_sptr(req, name, &f->value, f->value_length,
1159743Smax.romanov@nginx.com                          track_vars_array TSRMLS_CC);
1160114Smax.romanov@nginx.com     }
1161114Smax.romanov@nginx.com 
1162743Smax.romanov@nginx.com     if (r->content_length_field != NXT_UNIT_NONE_FIELD) {
1163743Smax.romanov@nginx.com         f = r->fields + r->content_length_field;
1164743Smax.romanov@nginx.com 
1165743Smax.romanov@nginx.com         nxt_php_set_sptr(req, "CONTENT_LENGTH", &f->value, f->value_length,
1166743Smax.romanov@nginx.com                          track_vars_array TSRMLS_CC);
116786Smax.romanov@nginx.com     }
11680Sigor@sysoev.ru 
1169743Smax.romanov@nginx.com     if (r->content_type_field != NXT_UNIT_NONE_FIELD) {
1170743Smax.romanov@nginx.com         f = r->fields + r->content_type_field;
1171114Smax.romanov@nginx.com 
1172743Smax.romanov@nginx.com         nxt_php_set_sptr(req, "CONTENT_TYPE", &f->value, f->value_length,
1173743Smax.romanov@nginx.com                          track_vars_array TSRMLS_CC);
1174114Smax.romanov@nginx.com     }
1175743Smax.romanov@nginx.com }
1176743Smax.romanov@nginx.com 
1177743Smax.romanov@nginx.com 
1178743Smax.romanov@nginx.com static void
1179743Smax.romanov@nginx.com nxt_php_set_sptr(nxt_unit_request_info_t *req, const char *name,
1180743Smax.romanov@nginx.com     nxt_unit_sptr_t *v, uint32_t len, zval *track_vars_array TSRMLS_DC)
1181743Smax.romanov@nginx.com {
1182743Smax.romanov@nginx.com     char  *str;
1183743Smax.romanov@nginx.com 
1184743Smax.romanov@nginx.com     str = nxt_unit_sptr_get(v);
1185743Smax.romanov@nginx.com 
1186743Smax.romanov@nginx.com     nxt_unit_req_debug(req, "php: register %s='%.*s'", name, (int) len, str);
11870Sigor@sysoev.ru 
1188743Smax.romanov@nginx.com     php_register_variable_safe((char *) name, str, len,
1189743Smax.romanov@nginx.com                                track_vars_array TSRMLS_CC);
1190743Smax.romanov@nginx.com }
1191743Smax.romanov@nginx.com 
119294Smax.romanov@nginx.com 
1193743Smax.romanov@nginx.com nxt_inline void
1194743Smax.romanov@nginx.com nxt_php_set_str(nxt_unit_request_info_t *req, const char *name,
1195743Smax.romanov@nginx.com     nxt_str_t *s, zval *track_vars_array TSRMLS_DC)
1196743Smax.romanov@nginx.com {
1197743Smax.romanov@nginx.com     nxt_php_set_cstr(req, name, (char *) s->start, s->length,
1198743Smax.romanov@nginx.com                      track_vars_array TSRMLS_CC);
1199743Smax.romanov@nginx.com }
1200743Smax.romanov@nginx.com 
1201743Smax.romanov@nginx.com 
12021376St.nateldemoura@f5.com #ifdef NXT_PHP7
12031376St.nateldemoura@f5.com 
12041376St.nateldemoura@f5.com static void *
12051376St.nateldemoura@f5.com nxt_php_hash_str_find_ptr(const HashTable *ht, const nxt_str_t *str)
12061376St.nateldemoura@f5.com {
12071376St.nateldemoura@f5.com     return zend_hash_str_find_ptr(ht, (const char *) str->start, str->length);
12081376St.nateldemoura@f5.com }
12091376St.nateldemoura@f5.com 
12101376St.nateldemoura@f5.com #else
12111376St.nateldemoura@f5.com 
12121376St.nateldemoura@f5.com static void *
12131376St.nateldemoura@f5.com nxt_php_hash_str_find_ptr(const HashTable *ht, const nxt_str_t *str)
12141376St.nateldemoura@f5.com {
12151376St.nateldemoura@f5.com     int   ret;
12161376St.nateldemoura@f5.com     void  *entry;
12171376St.nateldemoura@f5.com     char  buf[256];
12181376St.nateldemoura@f5.com 
12191376St.nateldemoura@f5.com     if (nxt_slow_path(str->length >= (sizeof(buf) - 1))) {
12201376St.nateldemoura@f5.com         return NULL;
12211376St.nateldemoura@f5.com     }
12221376St.nateldemoura@f5.com 
12231376St.nateldemoura@f5.com     nxt_memcpy(buf, str->start, str->length);
12241376St.nateldemoura@f5.com     buf[str->length] = '\0';
12251376St.nateldemoura@f5.com 
12261376St.nateldemoura@f5.com     ret = zend_hash_find(ht, buf, str->length + 1, &entry);
12271376St.nateldemoura@f5.com     if (nxt_fast_path(ret == SUCCESS)) {
12281376St.nateldemoura@f5.com         return entry;
12291376St.nateldemoura@f5.com     }
12301376St.nateldemoura@f5.com 
12311376St.nateldemoura@f5.com     return NULL;
12321376St.nateldemoura@f5.com }
12331376St.nateldemoura@f5.com 
12341376St.nateldemoura@f5.com #endif
12351376St.nateldemoura@f5.com 
12361376St.nateldemoura@f5.com 
1237743Smax.romanov@nginx.com static void
1238743Smax.romanov@nginx.com nxt_php_set_cstr(nxt_unit_request_info_t *req, const char *name,
1239967Svbart@nginx.com     const char *cstr, uint32_t len, zval *track_vars_array TSRMLS_DC)
1240743Smax.romanov@nginx.com {
1241743Smax.romanov@nginx.com     if (nxt_slow_path(cstr == NULL)) {
1242743Smax.romanov@nginx.com         return;
12430Sigor@sysoev.ru     }
1244114Smax.romanov@nginx.com 
1245743Smax.romanov@nginx.com     nxt_unit_req_debug(req, "php: register %s='%.*s'", name, (int) len, cstr);
1246743Smax.romanov@nginx.com 
1247967Svbart@nginx.com     php_register_variable_safe((char *) name, (char *) cstr, len,
1248743Smax.romanov@nginx.com                                track_vars_array TSRMLS_CC);
12490Sigor@sysoev.ru }
12500Sigor@sysoev.ru 
12510Sigor@sysoev.ru 
1252*1562Sremi@remirepo.net #if NXT_PHP8
1253*1562Sremi@remirepo.net static void
1254*1562Sremi@remirepo.net nxt_php_log_message(const char *message, int syslog_type_int)
1255*1562Sremi@remirepo.net #else
1256579Svbart@nginx.com #ifdef NXT_HAVE_PHP_LOG_MESSAGE_WITH_SYSLOG_TYPE
12570Sigor@sysoev.ru static void
1258579Svbart@nginx.com nxt_php_log_message(char *message, int syslog_type_int)
1259579Svbart@nginx.com #else
1260579Svbart@nginx.com static void
1261857Svbart@nginx.com nxt_php_log_message(char *message TSRMLS_DC)
126286Smax.romanov@nginx.com #endif
1263*1562Sremi@remirepo.net #endif
12640Sigor@sysoev.ru {
12651514Svbart@nginx.com     nxt_php_run_ctx_t  *ctx;
12661514Svbart@nginx.com 
12671514Svbart@nginx.com     ctx = SG(server_context);
12681514Svbart@nginx.com 
12691514Svbart@nginx.com     if (ctx != NULL) {
12701514Svbart@nginx.com         nxt_unit_req_log(ctx->req, NXT_UNIT_LOG_NOTICE,
12711514Svbart@nginx.com                          "php message: %s", message);
12721514Svbart@nginx.com 
12731514Svbart@nginx.com     } else {
12741514Svbart@nginx.com         nxt_unit_log(nxt_php_unit_ctx, NXT_UNIT_LOG_NOTICE,
12751514Svbart@nginx.com                      "php message: %s", message);
12761514Svbart@nginx.com     }
12770Sigor@sysoev.ru }
1278