nxt_php_sapi.c (65:10688b89aa16) nxt_php_sapi.c (86:3b77edf46701)
1
2/*
1
2/*
3 * 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_application.h>
14
15
4 * Copyright (C) Valentin V. Bartenev
5 * Copyright (C) NGINX, Inc.
6 */
7
8#include "php.h"
9#include "SAPI.h"
10#include "php_main.h"
11#include "php_variables.h"
12
13#include <nxt_main.h>
14#include <nxt_application.h>
15
16
16typedef struct {
17 size_t max_name;
17static nxt_int_t nxt_php_init(nxt_task_t *task);
18
18
19 nxt_str_t *cookie;
20 nxt_str_t *content_type;
21 nxt_str_t *content_length;
19static nxt_int_t nxt_php_prepare_msg(nxt_task_t *task,
20 nxt_app_request_t *r, nxt_app_wmsg_t *wmsg);
22
21
23 nxt_str_t script;
24 nxt_str_t query;
22static nxt_int_t nxt_php_run(nxt_task_t *task,
23 nxt_app_rmsg_t *rmsg, nxt_app_wmsg_t *wmsg);
25
24
26 size_t script_name_len;
25#if PHP_MAJOR_VERSION >= 7
26# define NXT_PHP7 1
27# if PHP_MINOR_VERSION >= 1
28# define NXT_HAVE_PHP_LOG_MESSAGE_WITH_SYSLOG_TYPE 1
29# else
30# define NXT_HAVE_PHP_INTERRUPTS 1
31# endif
32# define NXT_HAVE_PHP_IGNORE_CWD 1
33#else
34# define NXT_HAVE_PHP_INTERRUPTS 1
35# if PHP_MINOR_VERSION >= 4
36# define NXT_HAVE_PHP_IGNORE_CWD 1
37# endif
38#endif
27
39
28 off_t content_length_n;
29} nxt_php_ctx_t;
30
31
32nxt_int_t nxt_php_init(nxt_thread_t *thr);
33nxt_int_t nxt_php_request_init(nxt_app_request_t *r);
34nxt_int_t nxt_php_request_header(nxt_app_request_t *r,
35 nxt_app_header_field_t *field);
36nxt_int_t nxt_php_handler(nxt_app_request_t *r);
37
38
39nxt_int_t nxt_python_init();
40
41
42static nxt_int_t nxt_php_opts(nxt_log_t *log);
43
44
45static int nxt_php_startup(sapi_module_struct *sapi_module);
46static int nxt_php_send_headers(sapi_headers_struct *sapi_headers);
47static char *nxt_php_read_cookies(void);
48static void nxt_php_register_variables(zval *track_vars_array);
40static int nxt_php_startup(sapi_module_struct *sapi_module);
41static int nxt_php_send_headers(sapi_headers_struct *sapi_headers);
42static char *nxt_php_read_cookies(void);
43static void nxt_php_register_variables(zval *track_vars_array);
49static void nxt_php_log_message(char *message);
44static void nxt_php_log_message(char *message
45#ifdef NXT_HAVE_PHP_LOG_MESSAGE_WITH_SYSLOG_TYPE
46 , int syslog_type_int
47#endif
48);
50
49
51#define NXT_PHP7 1
52
53#ifdef NXT_PHP7
54static size_t nxt_php_unbuffered_write(const char *str,
55 size_t str_length TSRMLS_DC);
56static size_t nxt_php_read_post(char *buffer, size_t count_bytes TSRMLS_DC);
57#else
58static int nxt_php_unbuffered_write(const char *str, uint str_length TSRMLS_DC);
59static int nxt_php_read_post(char *buffer, uint count_bytes TSRMLS_DC);
60#endif
61
50#ifdef NXT_PHP7
51static size_t nxt_php_unbuffered_write(const char *str,
52 size_t str_length TSRMLS_DC);
53static size_t nxt_php_read_post(char *buffer, size_t count_bytes TSRMLS_DC);
54#else
55static int nxt_php_unbuffered_write(const char *str, uint str_length TSRMLS_DC);
56static int nxt_php_read_post(char *buffer, uint count_bytes TSRMLS_DC);
57#endif
58
59extern nxt_int_t nxt_php_sapi_init(nxt_thread_t *thr, nxt_runtime_t *rt);
62
60
61
63static sapi_module_struct nxt_php_sapi_module =
64{
65 (char *) "cli-server",
66 (char *) "nginext",
67
68 nxt_php_startup, /* startup */
69 php_module_shutdown_wrapper, /* shutdown */
70

--- 11 unchanged lines hidden (view full) ---

82 nxt_php_send_headers, /* send headers handler */
83 NULL, /* send header handler */
84
85 nxt_php_read_post, /* read POST data */
86 nxt_php_read_cookies, /* read Cookies */
87
88 nxt_php_register_variables, /* register server variables */
89 nxt_php_log_message, /* log message */
62static sapi_module_struct nxt_php_sapi_module =
63{
64 (char *) "cli-server",
65 (char *) "nginext",
66
67 nxt_php_startup, /* startup */
68 php_module_shutdown_wrapper, /* shutdown */
69

--- 11 unchanged lines hidden (view full) ---

81 nxt_php_send_headers, /* send headers handler */
82 NULL, /* send header handler */
83
84 nxt_php_read_post, /* read POST data */
85 nxt_php_read_cookies, /* read Cookies */
86
87 nxt_php_register_variables, /* register server variables */
88 nxt_php_log_message, /* log message */
89 NULL, /* get request time */
90 NULL, /* terminate process */
90
91
91 NULL, NULL, NULL, NULL, NULL, NULL,
92 NULL, NULL, 0, 0, NULL, NULL, NULL,
93 NULL, NULL, NULL, 0, NULL, NULL, NULL
92 NULL, /* php_ini_path_override */
93#ifdef NXT_HAVE_PHP_INTERRUPTS
94 NULL, /* block_interruptions */
95 NULL, /* unblock_interruptions */
96#endif
97 NULL, /* default_post_reader */
98 NULL, /* treat_data */
99 NULL, /* executable_location */
100
101 0, /* php_ini_ignore */
102#ifdef NXT_HAVE_PHP_IGNORE_CWD
103 0, /* php_ini_ignore_cwd */
104#endif
105 NULL, /* get_fd */
106
107 NULL, /* force_http_10 */
108
109 NULL, /* get_target_uid */
110 NULL, /* get_target_gid */
111
112 NULL, /* input_filter */
113
114 NULL, /* ini_defaults */
115 0, /* phpinfo_as_text */
116
117 NULL, /* ini_entries */
118 NULL, /* additional_functions */
119 NULL /* input_filter_init */
94};
95
120};
121
122typedef struct {
123 nxt_task_t *task;
124 nxt_app_rmsg_t *rmsg;
125 nxt_app_request_t r;
126 nxt_str_t script;
127 nxt_app_wmsg_t *wmsg;
128 nxt_mp_t *mem_pool;
129} nxt_php_run_ctx_t;
96
130
131nxt_inline nxt_int_t nxt_php_write(nxt_php_run_ctx_t *ctx,
132 const u_char *data, size_t len,
133 nxt_bool_t flush, nxt_bool_t last);
134
135
97static nxt_str_t nxt_php_path;
98static nxt_str_t nxt_php_root;
99static nxt_str_t nxt_php_script;
100
101
136static nxt_str_t nxt_php_path;
137static nxt_str_t nxt_php_root;
138static nxt_str_t nxt_php_script;
139
140
102nxt_int_t
103nxt_php_init(nxt_thread_t *thr)
104{
105 if (nxt_php_opts(thr->log)) {
106 return NXT_ERROR;
107 }
141nxt_application_module_t nxt_php_module = {
142 nxt_php_init,
143 nxt_php_prepare_msg,
144 nxt_php_run
145};
108
146
109 sapi_startup(&nxt_php_sapi_module);
110 nxt_php_startup(&nxt_php_sapi_module);
111
147
112 return NXT_OK;
113}
114
115
116static nxt_int_t
117nxt_php_opts(nxt_log_t *log)
148nxt_int_t
149nxt_php_sapi_init(nxt_thread_t *thr, nxt_runtime_t *rt)
118{
119 char **argv;
120 u_char *p;
121 nxt_uint_t i;
122
123 argv = nxt_process_argv;
124
125 while (*argv != NULL) {
126 p = (u_char *) *argv++;
127
128 if (nxt_strcmp(p, "--php") == 0) {
129 if (*argv == NULL) {
150{
151 char **argv;
152 u_char *p;
153 nxt_uint_t i;
154
155 argv = nxt_process_argv;
156
157 while (*argv != NULL) {
158 p = (u_char *) *argv++;
159
160 if (nxt_strcmp(p, "--php") == 0) {
161 if (*argv == NULL) {
130 nxt_log_error(NXT_LOG_ERR, log,
162 nxt_log_error(NXT_LOG_ERR, thr->log,
131 "no argument for option \"--php\"");
132 return NXT_ERROR;
133 }
134
135 p = (u_char *) *argv;
136
163 "no argument for option \"--php\"");
164 return NXT_ERROR;
165 }
166
167 p = (u_char *) *argv;
168
137 nxt_php_root.data = p;
138 nxt_php_path.data = p;
169 nxt_php_root.start = p;
170 nxt_php_path.start = p;
139
140 i = 0;
141
142 for ( /* void */ ; p[i] != '\0'; i++) {
143 if (p[i] == '/') {
171
172 i = 0;
173
174 for ( /* void */ ; p[i] != '\0'; i++) {
175 if (p[i] == '/') {
144 nxt_php_script.data = &p[i];
145 nxt_php_root.len = i;
176 nxt_php_script.start = &p[i];
177 nxt_php_root.length = i;
146 }
147 }
148
178 }
179 }
180
149 nxt_php_path.len = i;
150 nxt_php_script.len = i - nxt_php_root.len;
181 nxt_php_path.length = i;
182 nxt_php_script.length = i - nxt_php_root.length;
151
183
152 nxt_log_error(NXT_LOG_INFO, log, "php script \"%V\" root: \"%V\"",
184 nxt_log_error(NXT_LOG_INFO, thr->log,
185 "(ABS_MODE) php script \"%V\" root: \"%V\"",
153 &nxt_php_script, &nxt_php_root);
154
186 &nxt_php_script, &nxt_php_root);
187
188 sapi_startup(&nxt_php_sapi_module);
189 nxt_php_startup(&nxt_php_sapi_module);
190
191 nxt_app = &nxt_php_module;
192
155 return NXT_OK;
156 }
193 return NXT_OK;
194 }
157 }
158
195
159 nxt_log_error(NXT_LOG_ERR, log, "no option \"--php\" specified");
196 if (nxt_strcmp(p, "--php-root") == 0) {
197 if (*argv == NULL) {
198 nxt_log_error(NXT_LOG_ERR, thr->log,
199 "no argument for option \"--php\"");
200 return NXT_ERROR;
201 }
160
202
161 return NXT_ERROR;
162}
203 p = (u_char *) *argv;
163
204
205 nxt_php_root.start = p;
206 nxt_php_root.length = nxt_strlen(p);
164
207
165nxt_int_t
166nxt_php_request_init(nxt_app_request_t *r)
167{
168 nxt_php_ctx_t *ctx;
208 nxt_log_error(NXT_LOG_INFO, thr->log,
209 "(non ABS_MODE) php root: \"%V\"",
210 &nxt_php_root);
169
211
170 ctx = nxt_mp_zget(r->mem_pool, sizeof(nxt_php_ctx_t));
171 if (nxt_slow_path(ctx == NULL)) {
172 return NXT_ERROR;
212 sapi_startup(&nxt_php_sapi_module);
213 nxt_php_startup(&nxt_php_sapi_module);
214
215 nxt_app = &nxt_php_module;
216
217 return NXT_OK;
218 }
173 }
174
219 }
220
175 r->ctx = ctx;
221 nxt_log_error(NXT_LOG_ERR, thr->log, "no option \"--php\" specified");
176
222
177 return NXT_OK;
223 return NXT_ERROR;
178}
179
180
224}
225
226
227static nxt_int_t
228nxt_php_init(nxt_task_t *task)
229{
230 return NXT_OK;
231}
181
232
182nxt_int_t
183nxt_php_request_header(nxt_app_request_t *r, nxt_app_header_field_t *field)
233
234static nxt_int_t
235nxt_php_read_request(nxt_task_t *task, nxt_app_rmsg_t *rmsg,
236 nxt_php_run_ctx_t *ctx)
184{
237{
185 nxt_php_ctx_t *ctx;
238 u_char *p;
239 size_t s;
240 nxt_app_request_header_t *h;
186
241
187 static const u_char cookie[6] = "Cookie";
188 static const u_char content_length[14] = "Content-Length";
189 static const u_char content_type[12] = "Content-Type";
242 h = &ctx->r.header;
190
243
191 ctx = r->ctx;
244 nxt_app_msg_read_str(task, rmsg, &h->method);
245 nxt_app_msg_read_str(task, rmsg, &h->path);
246 h->path_no_query = h->path;
192
247
193 ctx->max_name = nxt_max(ctx->max_name, field->name.len);
248 nxt_app_msg_read_size(task, rmsg, &s);
249 if (s > 0) {
250 s--;
251 h->query.start = h->path.start + s;
252 h->query.length = h->path.length - s;
194
253
195 if (field->name.len == sizeof(cookie)
196 && nxt_memcasecmp(field->name.data, cookie, sizeof(cookie)) == 0)
197 {
198 ctx->cookie = &field->value;
254 if (s > 0) {
255 h->path_no_query.length = s - 1;
256 }
257 }
199
258
200 } else if (field->name.len == sizeof(content_length)
201 && nxt_memcasecmp(field->name.data, content_length,
202 sizeof(content_length)) == 0)
203 {
204 ctx->content_length = &field->value;
205 ctx->content_length_n = nxt_off_t_parse(field->value.data,
206 field->value.len);
259 if (nxt_php_path.start == NULL) {
260 ctx->script.length = nxt_php_root.length + h->path_no_query.length;
261 ctx->script.start = nxt_mp_nget(ctx->mem_pool,
262 ctx->script.length + 1);
207
263
208 } else if (field->name.len == sizeof(content_type)
209 && nxt_memcasecmp(field->name.data, content_type,
210 sizeof(content_type)) == 0)
211 {
212 ctx->content_type = &field->value;
213 field->value.data[field->value.len] = '\0';
264 p = ctx->script.start;
265
266 nxt_memcpy(p, nxt_php_root.start, nxt_php_root.length);
267 p += nxt_php_root.length;
268 nxt_memcpy(p, h->path_no_query.start, h->path_no_query.length);
269 p[h->path_no_query.length] = '\0';
270 } else {
271 ctx->script = nxt_php_path;
214 }
215
272 }
273
274 nxt_app_msg_read_str(task, rmsg, &h->version);
275
276 nxt_app_msg_read_str(task, rmsg, &h->cookie);
277 nxt_app_msg_read_str(task, rmsg, &h->content_type);
278 nxt_app_msg_read_str(task, rmsg, &h->content_length);
279
280 nxt_app_msg_read_size(task, rmsg, &s);
281 h->parsed_content_length = s;
282
283 /* Further headers read moved to nxt_php_register_variables. */
216 return NXT_OK;
217}
218
219
284 return NXT_OK;
285}
286
287
220#define ABS_MODE 1
288static nxt_int_t
289nxt_php_prepare_msg(nxt_task_t *task, nxt_app_request_t *r,
290 nxt_app_wmsg_t *wmsg)
291{
292 nxt_int_t rc;
293 nxt_http_field_t *field;
294 nxt_app_request_header_t *h;
221
295
296 static const nxt_str_t prefix = nxt_string("HTTP_");
297 static const nxt_str_t eof = nxt_null_string;
222
298
223#if !ABS_MODE
224static const u_char root[] = "/home/vbart/Development/tests/php/wordpress";
225#endif
299 h = &r->header;
226
300
301#define RC(S) \
302 do { \
303 rc = (S); \
304 if (nxt_slow_path(rc != NXT_OK)) { \
305 goto fail; \
306 } \
307 } while(0)
227
308
228nxt_int_t
229nxt_php_handler(nxt_app_request_t *r)
230{
231 u_char *query;
232#if !ABS_MODE
233 u_char *p;
234#endif
235 nxt_php_ctx_t *ctx;
236 zend_file_handle file_handle;
309#define NXT_WRITE(N) \
310 RC(nxt_app_msg_write_str(task, wmsg, N))
237
311
238#if ABS_MODE
239 if (nxt_php_path.len == 0) {
240 return NXT_ERROR;
312 /* TODO error handle, async mmap buffer assignment */
313
314 NXT_WRITE(&h->method);
315 NXT_WRITE(&h->path);
316
317 if (h->query.start != NULL) {
318 RC(nxt_app_msg_write_size(task, wmsg,
319 h->query.start - h->path.start + 1));
320 } else {
321 RC(nxt_app_msg_write_size(task, wmsg, 0));
241 }
322 }
242#endif
243
323
244 r->header.path.data[r->header.path.len] = '\0';
245 r->header.method.data[r->header.method.len] = '\0';
324 NXT_WRITE(&h->version);
246
325
247 ctx = r->ctx;
326 // PHP_SELF
327 // SCRIPT_NAME
328 // SCRIPT_FILENAME
329 // DOCUMENT_ROOT
248
330
249 query = nxt_memchr(r->header.path.data, '?', r->header.path.len);
331 NXT_WRITE(&h->cookie);
332 NXT_WRITE(&h->content_type);
333 NXT_WRITE(&h->content_length);
250
334
251 if (query != NULL) {
252 ctx->script_name_len = query - r->header.path.data;
335 RC(nxt_app_msg_write_size(task, wmsg, h->parsed_content_length));
253
336
254 ctx->query.data = query + 1;
255 ctx->query.len = r->header.path.data + r->header.path.len
256 - ctx->query.data;
337 nxt_list_each(field, h->fields) {
338 RC(nxt_app_msg_write_prefixed_upcase(task, wmsg,
339 &prefix, &field->name));
340 NXT_WRITE(&field->value);
257
341
258 } else {
259 ctx->script_name_len = r->header.path.len;
260 }
342 } nxt_list_loop;
261
343
262#if !ABS_MODE
263 ctx->script.len = sizeof(root) - 1 + ctx->script_name_len;
264 ctx->script.data = nxt_mp_nget(r->mem_pool, ctx->script.len + 1);
344 /* end-of-headers mark */
345 NXT_WRITE(&eof);
346 NXT_WRITE(&r->body.preread);
265
347
266 if (nxt_slow_path(ctx->script.data == NULL)) {
348#undef NXT_WRITE
349#undef RC
350
351 return NXT_OK;
352
353fail:
354
355 return NXT_ERROR;
356}
357
358
359static nxt_int_t
360nxt_php_run(nxt_task_t *task,
361 nxt_app_rmsg_t *rmsg, nxt_app_wmsg_t *wmsg)
362{
363 zend_file_handle file_handle;
364 nxt_php_run_ctx_t run_ctx;
365 nxt_app_request_header_t *h;
366
367 if (nxt_php_root.length == 0) {
267 return NXT_ERROR;
268 }
269
368 return NXT_ERROR;
369 }
370
270 p = nxt_cpymem(ctx->script.data, root, sizeof(root) - 1);
271 p = nxt_cpymem(p, r->header.path.data, ctx->script_name_len);
272 *p = '\0';
273#endif
371 nxt_memzero(&run_ctx, sizeof(run_ctx));
274
372
275 SG(server_context) = r;
276 SG(request_info).request_uri = (char *) r->header.path.data;
277 SG(request_info).request_method = (char *) r->header.method.data;
373 run_ctx.task = task;
374 run_ctx.rmsg = rmsg;
375 run_ctx.wmsg = wmsg;
278
376
377 run_ctx.mem_pool = nxt_mp_create(1024, 128, 256, 32);
378
379 h = &run_ctx.r.header;
380
381 nxt_php_read_request(task, rmsg, &run_ctx);
382
383 SG(server_context) = &run_ctx;
384 SG(request_info).request_uri = (char *) h->path.start;
385 SG(request_info).request_method = (char *) h->method.start;
386
279 SG(request_info).proto_num = 1001;
280
387 SG(request_info).proto_num = 1001;
388
281 SG(request_info).query_string = (char *) ctx->query.data;
282 SG(request_info).content_length = ctx->content_length_n;
389 SG(request_info).query_string = (char *) h->query.start;
390 SG(request_info).content_length = h->parsed_content_length;
283
391
284 if (ctx->content_type != NULL) {
285 SG(request_info).content_type = (char *) ctx->content_type->data;
392 if (h->content_type.start != NULL) {
393 SG(request_info).content_type = (char *) h->content_type.start;
286 }
287
288 SG(sapi_headers).http_response_code = 200;
289
290 SG(request_info).path_translated = NULL;
291
292 file_handle.type = ZEND_HANDLE_FILENAME;
394 }
395
396 SG(sapi_headers).http_response_code = 200;
397
398 SG(request_info).path_translated = NULL;
399
400 file_handle.type = ZEND_HANDLE_FILENAME;
293#if ABS_MODE
294 file_handle.filename = (char *) nxt_php_path.data;
295#else
296 file_handle.filename = (char *) ctx->script.data;
297#endif
401 file_handle.filename = (char *) run_ctx.script.start;
298 file_handle.free_filename = 0;
299 file_handle.opened_path = NULL;
300
402 file_handle.free_filename = 0;
403 file_handle.opened_path = NULL;
404
301#if ABS_MODE
302 nxt_log_debug(r->log, "run script %V in absolute mode", &nxt_php_path);
303#else
304 nxt_log_debug(r->log, "run script %V", &ctx->script);
305#endif
405 if (nxt_php_path.start != NULL) {
406 nxt_debug(task, "run script %V in absolute mode", &nxt_php_path);
407 } else {
408 nxt_debug(task, "run script %V", &run_ctx.script);
409 }
306
307 if (nxt_slow_path(php_request_startup() == FAILURE)) {
410
411 if (nxt_slow_path(php_request_startup() == FAILURE)) {
308 return NXT_ERROR;
412 goto fail;
309 }
310
311 php_execute_script(&file_handle TSRMLS_CC);
312 php_request_shutdown(NULL);
313
413 }
414
415 php_execute_script(&file_handle TSRMLS_CC);
416 php_request_shutdown(NULL);
417
418 nxt_app_msg_flush(task, wmsg, 1);
419
420 nxt_mp_destroy(run_ctx.mem_pool);
421
314 return NXT_OK;
422 return NXT_OK;
423
424fail:
425
426 nxt_mp_destroy(run_ctx.mem_pool);
427
428 return NXT_ERROR;
315}
316
317
429}
430
431
432nxt_inline nxt_int_t
433nxt_php_write(nxt_php_run_ctx_t *ctx, const u_char *data, size_t len,
434 nxt_bool_t flush, nxt_bool_t last)
435{
436 nxt_int_t rc;
437
438 rc = nxt_app_msg_write_raw(ctx->task, ctx->wmsg, data, len);
439
440 if (flush || last) {
441 rc = nxt_app_msg_flush(ctx->task, ctx->wmsg, last);
442 }
443
444 return rc;
445}
446
447
318static int
319nxt_php_startup(sapi_module_struct *sapi_module)
320{
321 return php_module_startup(sapi_module, NULL, 0);
322}
323
324
325#ifdef NXT_PHP7
326static size_t
327nxt_php_unbuffered_write(const char *str, size_t str_length TSRMLS_DC)
328#else
329static int
330nxt_php_unbuffered_write(const char *str, uint str_length TSRMLS_DC)
331#endif
332{
448static int
449nxt_php_startup(sapi_module_struct *sapi_module)
450{
451 return php_module_startup(sapi_module, NULL, 0);
452}
453
454
455#ifdef NXT_PHP7
456static size_t
457nxt_php_unbuffered_write(const char *str, size_t str_length TSRMLS_DC)
458#else
459static int
460nxt_php_unbuffered_write(const char *str, uint str_length TSRMLS_DC)
461#endif
462{
333 nxt_app_request_t *r;
463 nxt_php_run_ctx_t *ctx;
334
464
335 r = SG(server_context);
465 ctx = SG(server_context);
336
466
337 nxt_app_write(r, (u_char *) str, str_length);
467 nxt_php_write(ctx, (u_char *) str, str_length, 1, 0);
338
339 return str_length;
340}
341
342
343static int
344nxt_php_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
345{
346 size_t len;
468
469 return str_length;
470}
471
472
473static int
474nxt_php_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
475{
476 size_t len;
347 nxt_app_request_t *r;
348 sapi_header_struct *h;
349 zend_llist_position zpos;
477 sapi_header_struct *h;
478 zend_llist_position zpos;
350 u_char *p, *status, buf[4096];
479 u_char *status, buf[4096];
480 nxt_php_run_ctx_t *ctx;
351
352 static const u_char default_repsonse[]
353 = "HTTP/1.1 200 OK\r\n"
354 "Server: nginext/0.1\r\n"
355 "Content-Type: text/html; charset=UTF-8\r\n"
356 "Connection: close\r\n"
357 "\r\n";
358
359 static const u_char default_headers[]
360 = "Server: nginext/0.1\r\n"
361 "Connection: close\r\n";
362
481
482 static const u_char default_repsonse[]
483 = "HTTP/1.1 200 OK\r\n"
484 "Server: nginext/0.1\r\n"
485 "Content-Type: text/html; charset=UTF-8\r\n"
486 "Connection: close\r\n"
487 "\r\n";
488
489 static const u_char default_headers[]
490 = "Server: nginext/0.1\r\n"
491 "Connection: close\r\n";
492
363 r = SG(server_context);
493 static const u_char http_11[] = "HTTP/1.1 ";
494 static const u_char cr_lf[] = "\r\n";
495 static const u_char _200_ok[] = "200 OK";
364
496
497 ctx = SG(server_context);
498
365 if (SG(request_info).no_headers == 1) {
499 if (SG(request_info).no_headers == 1) {
366 nxt_app_write(r, default_repsonse, sizeof(default_repsonse) - 1);
500 nxt_php_write(ctx, default_repsonse, sizeof(default_repsonse) - 1,
501 1, 0);
367 return SAPI_HEADER_SENT_SUCCESSFULLY;
368 }
369
502 return SAPI_HEADER_SENT_SUCCESSFULLY;
503 }
504
505 nxt_php_write(ctx, http_11, sizeof(http_11) - 1, 0, 0);
506
370 if (SG(sapi_headers).http_status_line) {
371 status = (u_char *) SG(sapi_headers).http_status_line + 9;
372 len = nxt_strlen(status);
373
507 if (SG(sapi_headers).http_status_line) {
508 status = (u_char *) SG(sapi_headers).http_status_line + 9;
509 len = nxt_strlen(status);
510
374 p = nxt_cpymem(buf, "HTTP/1.1 ", sizeof("HTTP/1.1 ") - 1);
375 p = nxt_cpymem(p, status, len);
376 *p++ = '\r'; *p++ = '\n';
511 nxt_php_write(ctx, status, len, 0, 0);
377
378 } else if (SG(sapi_headers).http_response_code) {
512
513 } else if (SG(sapi_headers).http_response_code) {
379 p = nxt_cpymem(buf, "HTTP/1.1 ", sizeof("HTTP/1.1 ") - 1);
380 p = nxt_sprintf(p, buf + sizeof(buf), "%03d",
514 status = nxt_sprintf(buf, buf + sizeof(buf), "%03d",
381 SG(sapi_headers).http_response_code);
515 SG(sapi_headers).http_response_code);
382 *p++ = '\r'; *p++ = '\n';
516 len = status - buf;
383
517
518 nxt_php_write(ctx, buf, len, 0, 0);
519
384 } else {
520 } else {
385 p = nxt_cpymem(buf, "HTTP/1.1 200 OK\r\n",
386 sizeof("HTTP/1.1 200 OK\r\n") - 1);
521 nxt_php_write(ctx, _200_ok, sizeof(_200_ok) - 1, 0, 0);
387 }
388
522 }
523
389 p = nxt_cpymem(p, default_headers, sizeof(default_headers) - 1);
524 nxt_php_write(ctx, cr_lf, sizeof(cr_lf) - 1, 0, 0);
390
525
526 nxt_php_write(ctx, default_headers, sizeof(default_headers) - 1, 0, 0);
527
391 h = zend_llist_get_first_ex(&sapi_headers->headers, &zpos);
392
393 while (h) {
528 h = zend_llist_get_first_ex(&sapi_headers->headers, &zpos);
529
530 while (h) {
394 p = nxt_cpymem(p, h->header, h->header_len);
395 *p++ = '\r'; *p++ = '\n';
531 nxt_php_write(ctx, (u_char *) h->header, h->header_len, 0, 0);
532 nxt_php_write(ctx, cr_lf, sizeof(cr_lf) - 1, 0, 0);
396
397 h = zend_llist_get_next_ex(&sapi_headers->headers, &zpos);
398 }
399
533
534 h = zend_llist_get_next_ex(&sapi_headers->headers, &zpos);
535 }
536
400 *p++ = '\r'; *p++ = '\n';
537 nxt_php_write(ctx, cr_lf, sizeof(cr_lf) - 1, 1, 0);
401
538
402 nxt_app_write(r, buf, p - buf);
403
404 return SAPI_HEADER_SENT_SUCCESSFULLY;
405}
406
407
408#ifdef NXT_PHP7
409static size_t
410nxt_php_read_post(char *buffer, size_t count_bytes TSRMLS_DC)
411#else
412static int
413nxt_php_read_post(char *buffer, uint count_bytes TSRMLS_DC)
414#endif
415{
416 off_t rest;
417 size_t size;
539 return SAPI_HEADER_SENT_SUCCESSFULLY;
540}
541
542
543#ifdef NXT_PHP7
544static size_t
545nxt_php_read_post(char *buffer, size_t count_bytes TSRMLS_DC)
546#else
547static int
548nxt_php_read_post(char *buffer, uint count_bytes TSRMLS_DC)
549#endif
550{
551 off_t rest;
552 size_t size;
553/*
418 ssize_t n;
419 nxt_err_t err;
420 nxt_php_ctx_t *ctx;
421 nxt_app_request_t *r;
554 ssize_t n;
555 nxt_err_t err;
556 nxt_php_ctx_t *ctx;
557 nxt_app_request_t *r;
558*/
559 nxt_php_run_ctx_t *ctx;
560 nxt_app_request_body_t *b;
561 nxt_app_request_header_t *h;
422
562
423 r = SG(server_context);
424 ctx = r->ctx;
563 ctx = SG(server_context);
564 h = &ctx->r.header;
565 b = &ctx->r.body;
425
566
426 rest = ctx->content_length_n - SG(read_post_bytes);
567 rest = h->parsed_content_length - SG(read_post_bytes);
427
568
428 nxt_log_debug(r->log, "nxt_php_read_post %O", rest);
569 nxt_debug(ctx->task, "nxt_php_read_post %O", rest);
429
430 if (rest == 0) {
431 return 0;
432 }
433
434 size = 0;
435#ifdef NXT_PHP7
436 count_bytes = (size_t) nxt_min(rest, (off_t) count_bytes);
437#else
438 count_bytes = (uint) nxt_min(rest, (off_t) count_bytes);
439#endif
440
570
571 if (rest == 0) {
572 return 0;
573 }
574
575 size = 0;
576#ifdef NXT_PHP7
577 count_bytes = (size_t) nxt_min(rest, (off_t) count_bytes);
578#else
579 count_bytes = (uint) nxt_min(rest, (off_t) count_bytes);
580#endif
581
441 if (r->body_preread.len != 0) {
442 size = nxt_min(r->body_preread.len, count_bytes);
582 if (b->preread.length != 0) {
583 size = nxt_min(b->preread.length, count_bytes);
443
584
444 nxt_memcpy(buffer, r->body_preread.data, size);
585 nxt_memcpy(buffer, b->preread.start, size);
445
586
446 r->body_preread.len -= size;
447 r->body_preread.data += size;
587 b->preread.length -= size;
588 b->preread.start += size;
448
449 if (size == count_bytes) {
450 return size;
451 }
452 }
453
589
590 if (size == count_bytes) {
591 return size;
592 }
593 }
594
454 nxt_log_debug(r->log, "recv %z", (size_t) count_bytes - size);
595#if 0
596 nxt_debug(ctx->task, "recv %z", (size_t) count_bytes - size);
455
456 n = recv(r->event_conn->socket.fd, buffer + size, count_bytes - size, 0);
457
458 if (nxt_slow_path(n <= 0)) {
459 err = (n == 0) ? 0 : nxt_socket_errno;
460
461 nxt_log_error(NXT_LOG_ERR, r->log, "recv(%d, %uz) failed %E",
462 r->event_conn->socket.fd, (size_t) count_bytes - size,
463 err);
464
465 return size;
466 }
467
468 return size + n;
597
598 n = recv(r->event_conn->socket.fd, buffer + size, count_bytes - size, 0);
599
600 if (nxt_slow_path(n <= 0)) {
601 err = (n == 0) ? 0 : nxt_socket_errno;
602
603 nxt_log_error(NXT_LOG_ERR, r->log, "recv(%d, %uz) failed %E",
604 r->event_conn->socket.fd, (size_t) count_bytes - size,
605 err);
606
607 return size;
608 }
609
610 return size + n;
611#endif
612 return size;
469}
470
471
472static char *
473nxt_php_read_cookies(TSRMLS_D)
474{
613}
614
615
616static char *
617nxt_php_read_cookies(TSRMLS_D)
618{
475 u_char *p;
476 nxt_php_ctx_t *ctx;
477 nxt_app_request_t *r;
619 nxt_php_run_ctx_t *ctx;
478
620
479 r = SG(server_context);
480 ctx = r->ctx;
621 ctx = SG(server_context);
481
622
482 if (ctx->cookie == NULL) {
483 return NULL;
484 }
485
486 p = ctx->cookie->data;
487 p[ctx->cookie->len] = '\0';
488
489 return (char *) p;
623 return (char *) ctx->r.header.cookie.start;
490}
491
492
493static void
494nxt_php_register_variables(zval *track_vars_array TSRMLS_DC)
495{
624}
625
626
627static void
628nxt_php_register_variables(zval *track_vars_array TSRMLS_DC)
629{
496 u_char *var, *p, ch;
497 nxt_uint_t i, n;
498 nxt_php_ctx_t *ctx;
499 nxt_app_request_t *r;
500 nxt_app_header_field_t *fld;
630 nxt_str_t n, v;
631 nxt_int_t rc;
632 nxt_task_t *task;
633 nxt_php_run_ctx_t *ctx;
634 nxt_app_request_header_t *h;
501
635
502 static const u_char prefix[5] = "HTTP_";
636 ctx = SG(server_context);
503
637
504 r = SG(server_context);
505 ctx = r->ctx;
638 h = &ctx->r.header;
639 task = ctx->task;
506
640
507 nxt_log_debug(r->log, "php register variables");
641 nxt_debug(task, "php register variables");
508
642
509 php_register_variable_safe((char *) "PHP_SELF",
510 (char *) r->header.path.data,
511 ctx->script_name_len, track_vars_array TSRMLS_CC);
512
513 php_register_variable_safe((char *) "SERVER_PROTOCOL",
643 php_register_variable_safe((char *) "SERVER_PROTOCOL",
514 (char *) r->header.version.data,
515 r->header.version.len, track_vars_array TSRMLS_CC);
644 (char *) h->version.start,
645 h->version.length, track_vars_array TSRMLS_CC);
516
646
517#if ABS_MODE
518 php_register_variable_safe((char *) "SCRIPT_NAME",
519 (char *) nxt_php_script.data,
520 nxt_php_script.len, track_vars_array TSRMLS_CC);
647/*
648 * 'SCRIPT_NAME'
649 * Contains the current script's path. This is useful for pages which need to
650 * point to themselves. The __FILE__ constant contains the full path and
651 * filename of the current (i.e. included) file.
652 */
521
653
522 php_register_variable_safe((char *) "SCRIPT_FILENAME",
523 (char *) nxt_php_path.data,
524 nxt_php_path.len, track_vars_array TSRMLS_CC);
654/*
655 * 'SCRIPT_FILENAME'
656 * The absolute pathname of the currently executing script.
657 */
525
658
526 php_register_variable_safe((char *) "DOCUMENT_ROOT",
527 (char *) nxt_php_root.data,
528 nxt_php_root.len, track_vars_array TSRMLS_CC);
529#else
530 php_register_variable_safe((char *) "SCRIPT_NAME",
531 (char *) r->header.path.data,
532 ctx->script_name_len, track_vars_array TSRMLS_CC);
659/*
660 * 'DOCUMENT_ROOT'
661 * The document root directory under which the current script is executing,
662 * as defined in the server's configuration file.
663 */
533
664
665 if (nxt_php_script.start != NULL) {
666 // ABS_MODE
667/*
668 * 'PHP_SELF'
669 * The filename of the currently executing script, relative to the document
670 * root. For instance, $_SERVER['PHP_SELF'] in a script at the address
671 * http://example.com/foo/bar.php would be /foo/bar.php. The __FILE__ constant
672 * contains the full path and filename of the current (i.e. included) file.
673 * If PHP is running as a command-line processor this variable contains the
674 * script name since PHP 4.3.0. Previously it was not available.
675 */
676 php_register_variable_safe((char *) "PHP_SELF",
677 (char *) nxt_php_script.start,
678 nxt_php_script.length,
679 track_vars_array TSRMLS_CC);
680
681 php_register_variable_safe((char *) "SCRIPT_NAME",
682 (char *) nxt_php_script.start,
683 nxt_php_script.length,
684 track_vars_array TSRMLS_CC);
685 } else {
686 php_register_variable_safe((char *) "PHP_SELF",
687 (char *) h->path.start,
688 h->path.length, track_vars_array TSRMLS_CC);
689
690 php_register_variable_safe((char *) "SCRIPT_NAME",
691 (char *) h->path.start,
692 h->path.length, track_vars_array TSRMLS_CC);
693 }
694
534 php_register_variable_safe((char *) "SCRIPT_FILENAME",
695 php_register_variable_safe((char *) "SCRIPT_FILENAME",
535 (char *) ctx->script.data, ctx->script.len,
536 track_vars_array TSRMLS_CC);
696 (char *) ctx->script.start,
697 ctx->script.length,
698 track_vars_array TSRMLS_CC);
537
699
538 php_register_variable_safe((char *) "DOCUMENT_ROOT", (char *) root,
539 sizeof(root) - 1, track_vars_array TSRMLS_CC);
540#endif
700 php_register_variable_safe((char *) "DOCUMENT_ROOT",
701 (char *) nxt_php_root.start,
702 nxt_php_root.length,
703 track_vars_array TSRMLS_CC);
541
542 php_register_variable_safe((char *) "REQUEST_METHOD",
704
705 php_register_variable_safe((char *) "REQUEST_METHOD",
543 (char *) r->header.method.data,
544 r->header.method.len, track_vars_array TSRMLS_CC);
706 (char *) h->method.start,
707 h->method.length, track_vars_array TSRMLS_CC);
545
546 php_register_variable_safe((char *) "REQUEST_URI",
708
709 php_register_variable_safe((char *) "REQUEST_URI",
547 (char *) r->header.path.data,
548 r->header.path.len, track_vars_array TSRMLS_CC);
710 (char *) h->path.start,
711 h->path.length, track_vars_array TSRMLS_CC);
549
712
550 if (ctx->query.data != NULL) {
713 if (h->query.start != NULL) {
551 php_register_variable_safe((char *) "QUERY_STRING",
714 php_register_variable_safe((char *) "QUERY_STRING",
552 (char *) ctx->query.data,
553 ctx->query.len, track_vars_array TSRMLS_CC);
715 (char *) h->query.start,
716 h->query.length, track_vars_array TSRMLS_CC);
554 }
555
717 }
718
556 if (ctx->content_type != NULL) {
719 if (h->content_type.start != NULL) {
557 php_register_variable_safe((char *) "CONTENT_TYPE",
720 php_register_variable_safe((char *) "CONTENT_TYPE",
558 (char *) ctx->content_type->data,
559 ctx->content_type->len, track_vars_array TSRMLS_CC);
721 (char *) h->content_type.start,
722 h->content_type.length, track_vars_array TSRMLS_CC);
560 }
561
723 }
724
562 if (ctx->content_length != NULL) {
725 if (h->content_length.start != NULL) {
563 php_register_variable_safe((char *) "CONTENT_LENGTH",
726 php_register_variable_safe((char *) "CONTENT_LENGTH",
564 (char *) ctx->content_length->data,
565 ctx->content_length->len, track_vars_array TSRMLS_CC);
727 (char *) h->content_length.start,
728 h->content_length.length,
729 track_vars_array TSRMLS_CC);
566 }
567
730 }
731
568 var = nxt_mp_nget(r->mem_pool, sizeof(prefix) + ctx->max_name + 1);
569
570 if (nxt_slow_path(var == NULL)) {
571 return;
572 }
573
574 nxt_memcpy(var, prefix, sizeof(prefix));
575
576 for (i = 0; i < r->header.fields_num; i++) {
577 fld = &r->header.fields[i];
578 p = var + sizeof(prefix);
579
580 for (n = 0; n < fld->name.len; n++, p++) {
581
582 ch = fld->name.data[n];
583
584 if (ch >= 'a' && ch <= 'z') {
585 *p = ch & ~0x20;
586 continue;
587 }
588
589 if (ch == '-') {
590 *p = '_';
591 continue;
592 }
593
594 *p = ch;
732 while ( (rc = nxt_app_msg_read_nvp(task, ctx->rmsg, &n, &v)) == NXT_OK) {
733 if (nxt_slow_path(n.length == 0)) {
734 break;
595 }
596
735 }
736
597 *p = '\0';
598
599 php_register_variable_safe((char *) var, (char *) fld->value.data,
600 fld->value.len, track_vars_array TSRMLS_CC);
737 php_register_variable_safe((char *) n.start,
738 (char *) n.start,
739 v.length,
740 track_vars_array TSRMLS_CC);
601 }
602
741 }
742
603 return;
743 ctx->r.body.preread = v;
604}
605
606
607static void
744}
745
746
747static void
608nxt_php_log_message(char *message TSRMLS_DC)
748nxt_php_log_message(char *message
749#ifdef NXT_HAVE_PHP_LOG_MESSAGE_WITH_SYSLOG_TYPE
750 , int syslog_type_int
751#endif
752)
609{
610 return;
611}
753{
754 return;
755}