add population of _POST and _FILES for non-POST requests; release 2.0.0dev9
[m6w6/ext-http] / php_http_env.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: http |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accomp395anying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2004-2011, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 #include "php_http_api.h"
14 #include "php_variables.h"
15
16 PHP_RINIT_FUNCTION(http_env)
17 {
18 PHP_HTTP_G->env.request.time = sapi_get_request_time(TSRMLS_C);
19
20 /* populate form data on non-POST requests */
21 if (SG(request_info).request_method && strcasecmp(SG(request_info).request_method, "POST") && SG(request_info).content_type && *SG(request_info).content_type) {
22 uint ct_len = strlen(SG(request_info).content_type);
23 char *ct_str = estrndup(SG(request_info).content_type, ct_len);
24 php_http_params_opts_t opts;
25 HashTable params;
26
27 php_http_params_opts_default_get(&opts);
28 opts.input.str = ct_str;
29 opts.input.len = ct_len;
30
31 SG(request_info).content_type_dup = ct_str;
32
33 ZEND_INIT_SYMTABLE(&params);
34 if (php_http_params_parse(&params, &opts TSRMLS_CC)) {
35 zval **zct;
36 char *key_str;
37 uint key_len;
38 ulong key_num;
39
40 if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(&params, &key_str, &key_len, &key_num, 0, NULL)) {
41 sapi_post_entry *post_entry = NULL;
42
43 if (SUCCESS == zend_hash_find(&SG(known_post_content_types), key_str, key_len, (void *) &post_entry)) {
44 zval *files = PG(http_globals)[TRACK_VARS_FILES];
45
46 zend_is_auto_global(ZEND_STRL("_POST") TSRMLS_CC);
47
48 if (post_entry) {
49 SG(request_info).post_entry = post_entry;
50
51 if (post_entry->post_reader) {
52 post_entry->post_reader(TSRMLS_C);
53 }
54 }
55
56 if (sapi_module.default_post_reader) {
57 sapi_module.default_post_reader(TSRMLS_C);
58 }
59
60 sapi_handle_post(PG(http_globals)[TRACK_VARS_POST] TSRMLS_CC);
61
62 /*
63 * the rfc1867 handler is an awkward buddy
64 */
65 if (files != PG(http_globals)[TRACK_VARS_FILES] && PG(http_globals)[TRACK_VARS_FILES]) {
66 Z_ADDREF_P(PG(http_globals)[TRACK_VARS_FILES]);
67 zend_hash_update(&EG(symbol_table), "_FILES", sizeof("_FILES"), &PG(http_globals)[TRACK_VARS_FILES], sizeof(zval *), NULL);
68 if (files) {
69 zval_ptr_dtor(&files);
70 }
71 }
72 }
73 }
74 zend_hash_destroy(&params);
75 }
76 }
77
78 STR_SET(SG(request_info).content_type_dup, NULL);
79
80 return SUCCESS;
81 }
82
83 PHP_RSHUTDOWN_FUNCTION(http_env)
84 {
85 if (PHP_HTTP_G->env.request.headers) {
86 zend_hash_destroy(PHP_HTTP_G->env.request.headers);
87 FREE_HASHTABLE(PHP_HTTP_G->env.request.headers);
88 PHP_HTTP_G->env.request.headers = NULL;
89 }
90 if (PHP_HTTP_G->env.request.body) {
91 php_http_message_body_free(&PHP_HTTP_G->env.request.body);
92 }
93
94 if (PHP_HTTP_G->env.server_var) {
95 zval_ptr_dtor(&PHP_HTTP_G->env.server_var);
96 PHP_HTTP_G->env.server_var = NULL;
97 }
98
99 return SUCCESS;
100 }
101
102 PHP_HTTP_API void php_http_env_get_request_headers(HashTable *headers TSRMLS_DC)
103 {
104 php_http_array_hashkey_t key = php_http_array_hashkey_init(0);
105 zval **hsv, **header;
106 HashPosition pos;
107
108 if (!PHP_HTTP_G->env.request.headers) {
109 ALLOC_HASHTABLE(PHP_HTTP_G->env.request.headers);
110 zend_hash_init(PHP_HTTP_G->env.request.headers, 0, NULL, ZVAL_PTR_DTOR, 0);
111
112 zend_is_auto_global("_SERVER", lenof("_SERVER") TSRMLS_CC);
113
114 if (SUCCESS == zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void *) &hsv) && Z_TYPE_PP(hsv) == IS_ARRAY) {
115 FOREACH_KEY(pos, *hsv, key) {
116 if (key.type == HASH_KEY_IS_STRING && key.len > 6 && *key.str == 'H' && !strncmp(key.str, "HTTP_", 5)) {
117 key.len -= 5;
118 key.str = php_http_pretty_key(estrndup(key.str + 5, key.len - 1), key.len - 1, 1, 1);
119
120 zend_hash_get_current_data_ex(Z_ARRVAL_PP(hsv), (void *) &header, &pos);
121 Z_ADDREF_P(*header);
122 zend_symtable_update(PHP_HTTP_G->env.request.headers, key.str, key.len, (void *) header, sizeof(zval *), NULL);
123
124 efree(key.str);
125 } else if (key.type == HASH_KEY_IS_STRING && key.len > 9 && *key.str == 'C' && !strncmp(key.str, "CONTENT_", 8)) {
126 key.str = php_http_pretty_key(estrndup(key.str, key.len - 1), key.len - 1, 1, 1);
127
128 zend_hash_get_current_data_ex(Z_ARRVAL_PP(hsv), (void *) &header, &pos);
129 Z_ADDREF_P(*header);
130 zend_symtable_update(PHP_HTTP_G->env.request.headers, key.str, key.len, (void *) header, sizeof(zval *), NULL);
131
132 efree(key.str);
133 }
134 }
135 }
136 }
137
138 if (headers) {
139 zend_hash_copy(headers, PHP_HTTP_G->env.request.headers, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
140 }
141 }
142
143 PHP_HTTP_API char *php_http_env_get_request_header(const char *name_str, size_t name_len, size_t *len TSRMLS_DC)
144 {
145 zval **zvalue;
146 char *val = NULL, *key = php_http_pretty_key(estrndup(name_str, name_len), name_len, 1, 1);
147
148 php_http_env_get_request_headers(NULL TSRMLS_CC);
149
150 if (SUCCESS == zend_symtable_find(PHP_HTTP_G->env.request.headers, key, name_len + 1, (void *) &zvalue)) {
151 zval *zcopy = php_http_ztyp(IS_STRING, *zvalue);
152
153 val = estrndup(Z_STRVAL_P(zcopy), Z_STRLEN_P(zcopy));
154 if (len) {
155 *len = Z_STRLEN_P(zcopy);
156 }
157 zval_ptr_dtor(&zcopy);
158 }
159
160 efree(key);
161
162 return val;
163 }
164
165 PHP_HTTP_API int php_http_env_got_request_header(const char *name_str, size_t name_len TSRMLS_DC)
166 {
167 char *key = php_http_pretty_key(estrndup(name_str, name_len), name_len, 1, 1);
168 int got;
169
170 php_http_env_get_request_headers(NULL TSRMLS_CC);
171 got = zend_symtable_exists(PHP_HTTP_G->env.request.headers, key, name_len + 1);
172 efree(key);
173
174 return got;
175 }
176
177 PHP_HTTP_API zval *php_http_env_get_superglobal(const char *key, size_t key_len TSRMLS_DC)
178 {
179 zval **hsv;
180
181 zend_is_auto_global(key, key_len TSRMLS_CC);
182
183 if ((SUCCESS != zend_hash_find(&EG(symbol_table), key, key_len + 1, (void *) &hsv)) || (Z_TYPE_PP(hsv) != IS_ARRAY)) {
184 return NULL;
185 }
186
187 return *hsv;
188 }
189
190 PHP_HTTP_API zval *php_http_env_get_server_var(const char *key, size_t key_len, zend_bool check TSRMLS_DC)
191 {
192 zval *hsv, **var;
193 char *env;
194
195 /* if available, this is a lot faster than accessing $_SERVER */
196 if (sapi_module.getenv) {
197 if ((!(env = sapi_module.getenv((char *) key, key_len TSRMLS_CC))) || (check && !*env)) {
198 return NULL;
199 }
200 if (PHP_HTTP_G->env.server_var) {
201 zval_ptr_dtor(&PHP_HTTP_G->env.server_var);
202 }
203 MAKE_STD_ZVAL(PHP_HTTP_G->env.server_var);
204 ZVAL_STRING(PHP_HTTP_G->env.server_var, env, 1);
205 return PHP_HTTP_G->env.server_var;
206 }
207
208 if (!(hsv = php_http_env_get_superglobal(ZEND_STRL("_SERVER") TSRMLS_CC))) {
209 return NULL;
210 }
211 if ((SUCCESS != zend_symtable_find(Z_ARRVAL_P(hsv), key, key_len + 1, (void *) &var))) {
212 return NULL;
213 }
214 if (check && !((Z_TYPE_PP(var) == IS_STRING) && Z_STRVAL_PP(var) && Z_STRLEN_PP(var))) {
215 return NULL;
216 }
217 return *var;
218 }
219
220 PHP_HTTP_API php_http_message_body_t *php_http_env_get_request_body(TSRMLS_D)
221 {
222 if (!PHP_HTTP_G->env.request.body) {
223 php_stream *s = NULL;
224
225 if (SG(request_info).post_data || SG(request_info).raw_post_data) {
226 if ((s = php_stream_temp_new())) {
227 /* php://input does not support seek() */
228 if (SG(request_info).raw_post_data) {
229 php_stream_write(s, SG(request_info).raw_post_data, SG(request_info).raw_post_data_length);
230 } else {
231 php_stream_write(s, SG(request_info).post_data, SG(request_info).post_data_length);
232 }
233 php_stream_rewind(s);
234 }
235 } else if (sapi_module.read_post && !SG(read_post_bytes)) {
236 if ((s = php_stream_temp_new())) {
237 char *buf = emalloc(4096);
238 int len;
239
240 while (0 < (len = sapi_module.read_post(buf, 4096 TSRMLS_CC))) {
241 SG(read_post_bytes) += len;
242 php_stream_write(s, buf, len);
243
244 if (len < 4096) {
245 break;
246 }
247 }
248 efree(buf);
249
250 php_stream_rewind(s);
251 }
252 }
253 PHP_HTTP_G->env.request.body = php_http_message_body_init(NULL, s TSRMLS_CC);
254 }
255
256 return PHP_HTTP_G->env.request.body;
257 }
258
259 PHP_HTTP_API php_http_range_status_t php_http_env_get_request_ranges(HashTable *ranges, size_t length TSRMLS_DC)
260 {
261 zval *zentry;
262 char *range, *rp, c;
263 long begin = -1, end = -1, *ptr;
264
265 if (!(range = php_http_env_get_request_header(ZEND_STRL("Range"), NULL TSRMLS_CC))) {
266 return PHP_HTTP_RANGE_NO;
267 }
268 if (strncmp(range, "bytes=", lenof("bytes="))) {
269 STR_FREE(range);
270 return PHP_HTTP_RANGE_NO;
271 }
272
273 rp = range + lenof("bytes=");
274 ptr = &begin;
275
276 do {
277 switch (c = *(rp++)) {
278 case '0':
279 /* allow 000... - shall we? */
280 if (*ptr != -10) {
281 *ptr *= 10;
282 }
283 break;
284
285 case '1': case '2': case '3':
286 case '4': case '5': case '6':
287 case '7': case '8': case '9':
288 /*
289 * If the value of the pointer is already set (non-negative)
290 * then multiply its value by ten and add the current value,
291 * else initialise the pointers value with the current value
292 * --
293 * This let us recognize empty fields when validating the
294 * ranges, i.e. a "-10" for begin and "12345" for the end
295 * was the following range request: "Range: bytes=0-12345";
296 * While a "-1" for begin and "12345" for the end would
297 * have been: "Range: bytes=-12345".
298 */
299 if (*ptr > 0) {
300 *ptr *= 10;
301 *ptr += c - '0';
302 } else {
303 *ptr = c - '0';
304 }
305 break;
306
307 case '-':
308 ptr = &end;
309 break;
310
311 case ' ':
312 break;
313
314 case 0:
315 case ',':
316
317 if (length) {
318 /* validate ranges */
319 switch (begin) {
320 /* "0-12345" */
321 case -10:
322 switch (end) {
323 /* "0-" */
324 case -1:
325 STR_FREE(range);
326 return PHP_HTTP_RANGE_NO;
327
328 /* "0-0" */
329 case -10:
330 end = 0;
331 break;
332
333 default:
334 if (length <= (size_t) end) {
335 end = length - 1;
336 }
337 break;
338 }
339 begin = 0;
340 break;
341
342 /* "-12345" */
343 case -1:
344 /* "-", "-0" */
345 if (end == -1 || end == -10) {
346 STR_FREE(range);
347 return PHP_HTTP_RANGE_ERR;
348 }
349 begin = length - end;
350 end = length - 1;
351 break;
352
353 /* "12345-(NNN)" */
354 default:
355 if (length <= (size_t) begin) {
356 STR_FREE(range);
357 return PHP_HTTP_RANGE_ERR;
358 }
359 switch (end) {
360 /* "12345-0" */
361 case -10:
362 STR_FREE(range);
363 return PHP_HTTP_RANGE_ERR;
364
365 /* "12345-" */
366 case -1:
367 end = length - 1;
368 break;
369
370 /* "12345-67890" */
371 default:
372 if (length <= (size_t) end) {
373 end = length - 1;
374 } else if (end < begin) {
375 STR_FREE(range);
376 return PHP_HTTP_RANGE_ERR;
377 }
378 break;
379 }
380 break;
381 }
382 }
383
384 MAKE_STD_ZVAL(zentry);
385 array_init(zentry);
386 add_index_long(zentry, 0, begin);
387 add_index_long(zentry, 1, end);
388 zend_hash_next_index_insert(ranges, &zentry, sizeof(zval *), NULL);
389
390 begin = -1;
391 end = -1;
392 ptr = &begin;
393
394 break;
395
396 default:
397 STR_FREE(range);
398 return PHP_HTTP_RANGE_NO;
399 }
400 } while (c != 0);
401
402 STR_FREE(range);
403 return PHP_HTTP_RANGE_OK;
404 }
405
406 static void grab_headers(void *data, void *arg TSRMLS_DC)
407 {
408 php_http_buffer_appendl(PHP_HTTP_BUFFER(arg), ((sapi_header_struct *)data)->header);
409 php_http_buffer_appends(PHP_HTTP_BUFFER(arg), PHP_HTTP_CRLF);
410 }
411
412 PHP_HTTP_API STATUS php_http_env_get_response_headers(HashTable *headers_ht TSRMLS_DC)
413 {
414 STATUS status;
415 php_http_buffer_t headers;
416
417 php_http_buffer_init(&headers);
418 zend_llist_apply_with_argument(&SG(sapi_headers).headers, grab_headers, &headers TSRMLS_CC);
419 php_http_buffer_fix(&headers);
420
421 status = php_http_headers_parse(PHP_HTTP_BUFFER_VAL(&headers), PHP_HTTP_BUFFER_LEN(&headers), headers_ht, NULL, NULL TSRMLS_CC);
422 php_http_buffer_dtor(&headers);
423
424 return status;
425 }
426
427 PHP_HTTP_API char *php_http_env_get_response_header(const char *name_str, size_t name_len TSRMLS_DC)
428 {
429 char *val = NULL;
430 HashTable headers;
431
432 zend_hash_init(&headers, 0, NULL, ZVAL_PTR_DTOR, 0);
433 if (SUCCESS == php_http_env_get_response_headers(&headers TSRMLS_CC)) {
434 zval **zvalue;
435 char *key = php_http_pretty_key(estrndup(name_str, name_len), name_len, 1, 1);
436
437 if (SUCCESS == zend_symtable_find(&headers, key, name_len + 1, (void *) &zvalue)) {
438 zval *zcopy = php_http_ztyp(IS_STRING, *zvalue);
439
440 val = estrndup(Z_STRVAL_P(zcopy), Z_STRLEN_P(zcopy));
441 zval_ptr_dtor(&zcopy);
442 }
443
444 efree(key);
445 }
446 zend_hash_destroy(&headers);
447
448 return val;
449 }
450
451 PHP_HTTP_API long php_http_env_get_response_code(TSRMLS_D)
452 {
453 long code = SG(sapi_headers).http_response_code;
454 return code ? code : 200;
455 }
456
457 PHP_HTTP_API STATUS php_http_env_set_response_code(long http_code TSRMLS_DC)
458 {
459 return sapi_header_op(SAPI_HEADER_SET_STATUS, (void *) http_code TSRMLS_CC);
460 }
461
462 PHP_HTTP_API STATUS php_http_env_set_response_status_line(long code, php_http_version_t *v TSRMLS_DC)
463 {
464 sapi_header_line h = {NULL, 0, 0};
465 STATUS ret;
466
467 h.line_len = spprintf(&h.line, 0, "HTTP/%u.%u %ld %s", v->major, v->minor, code, php_http_env_get_response_status_for_code(code));
468 ret = sapi_header_op(SAPI_HEADER_REPLACE, (void *) &h TSRMLS_CC);
469 efree(h.line);
470
471 return ret;
472 }
473
474 PHP_HTTP_API STATUS php_http_env_set_response_protocol_version(php_http_version_t *v TSRMLS_DC)
475 {
476 return php_http_env_set_response_status_line(php_http_env_get_response_code(TSRMLS_C), v TSRMLS_CC);
477 }
478
479 PHP_HTTP_API STATUS php_http_env_set_response_header(long http_code, const char *header_str, size_t header_len, zend_bool replace TSRMLS_DC)
480 {
481 sapi_header_line h = {estrndup(header_str, header_len), header_len, http_code};
482 STATUS ret = sapi_header_op(replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD, (void *) &h TSRMLS_CC);
483 efree(h.line);
484 return ret;
485 }
486
487 PHP_HTTP_API STATUS php_http_env_set_response_header_format(long http_code, zend_bool replace TSRMLS_DC, const char *fmt, ...)
488 {
489 va_list args;
490 STATUS ret = FAILURE;
491 sapi_header_line h = {NULL, 0, http_code};
492
493 va_start(args, fmt);
494 h.line_len = vspprintf(&h.line, 0, fmt, args);
495 va_end(args);
496
497 if (h.line) {
498 if (h.line_len) {
499 ret = sapi_header_op(replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD, (void *) &h TSRMLS_CC);
500 }
501 efree(h.line);
502 }
503 return ret;
504 }
505
506 PHP_HTTP_API STATUS php_http_env_set_response_header_value(long http_code, const char *name_str, size_t name_len, zval *value, zend_bool replace TSRMLS_DC)
507 {
508 if (!value) {
509 sapi_header_line h = {(char *) name_str, name_len, http_code};
510
511 return sapi_header_op(SAPI_HEADER_DELETE, (void *) &h TSRMLS_CC);
512 }
513
514 if(Z_TYPE_P(value) == IS_ARRAY || Z_TYPE_P(value) == IS_OBJECT) {
515 HashPosition pos;
516 int first = replace;
517 zval **data_ptr;
518
519 FOREACH_HASH_VAL(pos, HASH_OF(value), data_ptr) {
520 if (SUCCESS != php_http_env_set_response_header_value(http_code, name_str, name_len, *data_ptr, first TSRMLS_CC)) {
521 return FAILURE;
522 }
523 first = 0;
524 }
525
526 return SUCCESS;
527 } else {
528 zval *data = php_http_ztyp(IS_STRING, value);
529
530 if (!Z_STRLEN_P(data)) {
531 zval_ptr_dtor(&data);
532 return php_http_env_set_response_header_value(http_code, name_str, name_len, NULL, replace TSRMLS_CC);
533 } else {
534 sapi_header_line h;
535 STATUS ret;
536
537 if (name_len > INT_MAX) {
538 name_len = INT_MAX;
539 }
540 h.response_code = http_code;
541 h.line_len = spprintf(&h.line, 0, "%.*s: %.*s", (int) name_len, name_str, Z_STRLEN_P(data), Z_STRVAL_P(data));
542
543 ret = sapi_header_op(replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD, (void *) &h TSRMLS_CC);
544
545 zval_ptr_dtor(&data);
546 STR_FREE(h.line);
547
548 return ret;
549 }
550 }
551 }
552
553
554 static PHP_HTTP_STRLIST(php_http_env_response_status) =
555 PHP_HTTP_STRLIST_ITEM("Continue")
556 PHP_HTTP_STRLIST_ITEM("Switching Protocols")
557 PHP_HTTP_STRLIST_NEXT
558 PHP_HTTP_STRLIST_ITEM("OK")
559 PHP_HTTP_STRLIST_ITEM("Created")
560 PHP_HTTP_STRLIST_ITEM("Accepted")
561 PHP_HTTP_STRLIST_ITEM("Non-Authoritative Information")
562 PHP_HTTP_STRLIST_ITEM("No Content")
563 PHP_HTTP_STRLIST_ITEM("Reset Content")
564 PHP_HTTP_STRLIST_ITEM("Partial Content")
565 PHP_HTTP_STRLIST_NEXT
566 PHP_HTTP_STRLIST_ITEM("Multiple Choices")
567 PHP_HTTP_STRLIST_ITEM("Moved Permanently")
568 PHP_HTTP_STRLIST_ITEM("Found")
569 PHP_HTTP_STRLIST_ITEM("See Other")
570 PHP_HTTP_STRLIST_ITEM("Not Modified")
571 PHP_HTTP_STRLIST_ITEM("Use Proxy")
572 PHP_HTTP_STRLIST_ITEM("(Unused)")
573 PHP_HTTP_STRLIST_ITEM("Temporary Redirect")
574 PHP_HTTP_STRLIST_NEXT
575 PHP_HTTP_STRLIST_ITEM("Bad Request")
576 PHP_HTTP_STRLIST_ITEM("Unauthorized")
577 PHP_HTTP_STRLIST_ITEM("Payment Required")
578 PHP_HTTP_STRLIST_ITEM("Forbidden")
579 PHP_HTTP_STRLIST_ITEM("Not Found")
580 PHP_HTTP_STRLIST_ITEM("Method Not Allowed")
581 PHP_HTTP_STRLIST_ITEM("Not Acceptable")
582 PHP_HTTP_STRLIST_ITEM("Proxy Authentication Required")
583 PHP_HTTP_STRLIST_ITEM("Request Timeout")
584 PHP_HTTP_STRLIST_ITEM("Conflict")
585 PHP_HTTP_STRLIST_ITEM("Gone")
586 PHP_HTTP_STRLIST_ITEM("Length Required")
587 PHP_HTTP_STRLIST_ITEM("Precondition Failed")
588 PHP_HTTP_STRLIST_ITEM("Request Entity Too Large")
589 PHP_HTTP_STRLIST_ITEM("Request URI Too Long")
590 PHP_HTTP_STRLIST_ITEM("Unsupported Media Type")
591 PHP_HTTP_STRLIST_ITEM("Requested Range Not Satisfiable")
592 PHP_HTTP_STRLIST_ITEM("Expectation Failed")
593 PHP_HTTP_STRLIST_NEXT
594 PHP_HTTP_STRLIST_ITEM("Internal Server Error")
595 PHP_HTTP_STRLIST_ITEM("Not Implemented")
596 PHP_HTTP_STRLIST_ITEM("Bad Gateway")
597 PHP_HTTP_STRLIST_ITEM("Service Unavailable")
598 PHP_HTTP_STRLIST_ITEM("Gateway Timeout")
599 PHP_HTTP_STRLIST_ITEM("HTTP Version Not Supported")
600 PHP_HTTP_STRLIST_STOP
601 ;
602
603 PHP_HTTP_API const char *php_http_env_get_response_status_for_code(unsigned code)
604 {
605 return php_http_strlist_find(php_http_env_response_status, 100, code);
606 }
607
608 zend_class_entry *php_http_env_class_entry;
609
610 #define PHP_HTTP_BEGIN_ARGS(method, req_args) PHP_HTTP_BEGIN_ARGS_EX(HttpEnv, method, 0, req_args)
611 #define PHP_HTTP_EMPTY_ARGS(method) PHP_HTTP_EMPTY_ARGS_EX(HttpEnv, method, 0)
612 #define PHP_HTTP_ENV_ME(method) PHP_ME(HttpEnv, method, PHP_HTTP_ARGS(HttpEnv, method), ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
613
614 PHP_HTTP_BEGIN_ARGS(getRequestHeader, 0)
615 PHP_HTTP_ARG_VAL(header_name, 0)
616 PHP_HTTP_END_ARGS;
617
618 PHP_HTTP_BEGIN_ARGS(getRequestBody, 0)
619 PHP_HTTP_ARG_VAL(body_class_name, 0)
620 PHP_HTTP_END_ARGS;
621
622 PHP_HTTP_BEGIN_ARGS(getResponseStatusForCode, 1)
623 PHP_HTTP_ARG_VAL(code, 0)
624 PHP_HTTP_END_ARGS;
625
626 PHP_HTTP_BEGIN_ARGS(getResponseHeader, 0)
627 PHP_HTTP_ARG_VAL(header_name, 0)
628 PHP_HTTP_END_ARGS;
629
630 PHP_HTTP_EMPTY_ARGS(getResponseCode);
631
632 PHP_HTTP_BEGIN_ARGS(setResponseHeader, 1)
633 PHP_HTTP_ARG_VAL(header_name, 0)
634 PHP_HTTP_ARG_VAL(header_value, 0)
635 PHP_HTTP_ARG_VAL(response_code, 0)
636 PHP_HTTP_ARG_VAL(replace_header, 0)
637 PHP_HTTP_END_ARGS;
638
639 PHP_HTTP_BEGIN_ARGS(setResponseCode, 1)
640 PHP_HTTP_ARG_VAL(code, 0)
641 PHP_HTTP_END_ARGS;
642
643 PHP_HTTP_BEGIN_ARGS(negotiateLanguage, 1)
644 PHP_HTTP_ARG_VAL(supported, 0)
645 PHP_HTTP_ARG_VAL(result_array, 1)
646 PHP_HTTP_END_ARGS;
647
648 PHP_HTTP_BEGIN_ARGS(negotiateContentType, 1)
649 PHP_HTTP_ARG_VAL(supported, 0)
650 PHP_HTTP_ARG_VAL(result_array, 1)
651 PHP_HTTP_END_ARGS;
652
653 PHP_HTTP_BEGIN_ARGS(negotiateCharset, 1)
654 PHP_HTTP_ARG_VAL(supported, 0)
655 PHP_HTTP_ARG_VAL(result_array, 1)
656 PHP_HTTP_END_ARGS;
657
658 PHP_HTTP_BEGIN_ARGS(negotiateEncoding, 1)
659 PHP_HTTP_ARG_VAL(supported, 0)
660 PHP_HTTP_ARG_VAL(result_array, 1)
661 PHP_HTTP_END_ARGS;
662
663 PHP_HTTP_BEGIN_ARGS(negotiate, 2)
664 PHP_HTTP_ARG_VAL(value, 0)
665 PHP_HTTP_ARG_VAL(supported, 0)
666 PHP_HTTP_ARG_VAL(primary_type_separator, 0)
667 PHP_HTTP_ARG_VAL(result_array, 1)
668 PHP_HTTP_END_ARGS;
669
670 PHP_HTTP_EMPTY_ARGS(statPersistentHandles);
671
672 PHP_HTTP_BEGIN_ARGS(cleanPersistentHandles, 0)
673 PHP_HTTP_ARG_VAL(name, 0)
674 PHP_HTTP_ARG_VAL(ident, 0)
675 PHP_HTTP_END_ARGS;
676
677 zend_function_entry php_http_env_method_entry[] = {
678 PHP_HTTP_ENV_ME(getRequestHeader)
679 PHP_HTTP_ENV_ME(getRequestBody)
680
681 PHP_HTTP_ENV_ME(getResponseStatusForCode)
682
683 PHP_HTTP_ENV_ME(getResponseHeader)
684 PHP_HTTP_ENV_ME(getResponseCode)
685 PHP_HTTP_ENV_ME(setResponseHeader)
686 PHP_HTTP_ENV_ME(setResponseCode)
687
688 PHP_HTTP_ENV_ME(negotiateLanguage)
689 PHP_HTTP_ENV_ME(negotiateContentType)
690 PHP_HTTP_ENV_ME(negotiateEncoding)
691 PHP_HTTP_ENV_ME(negotiateCharset)
692 PHP_HTTP_ENV_ME(negotiate)
693
694 PHP_HTTP_ENV_ME(statPersistentHandles)
695 PHP_HTTP_ENV_ME(cleanPersistentHandles)
696
697 EMPTY_FUNCTION_ENTRY
698 };
699
700 PHP_METHOD(HttpEnv, getRequestHeader)
701 {
702 char *header_name_str = NULL;
703 int header_name_len = 0;
704
705 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!", &header_name_str, &header_name_len)) {
706 if (header_name_str && header_name_len) {
707 size_t header_length;
708 char *header_value = php_http_env_get_request_header(header_name_str, header_name_len, &header_length TSRMLS_CC);
709
710 if (header_value) {
711 RETURN_STRINGL(header_value, header_length, 0);
712 }
713 RETURN_NULL();
714 } else {
715 array_init(return_value);
716 php_http_env_get_request_headers(Z_ARRVAL_P(return_value) TSRMLS_CC);
717 return;
718 }
719 }
720 RETURN_FALSE;
721 }
722
723 PHP_METHOD(HttpEnv, getRequestBody)
724 {
725 with_error_handling(EH_THROW, php_http_exception_class_entry) {
726 zend_class_entry *class_entry = php_http_message_body_class_entry;
727
728 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|C", &class_entry)) {
729 zend_object_value ov;
730 php_http_message_body_t *body = php_http_env_get_request_body(TSRMLS_C);
731
732 if (SUCCESS == php_http_new(&ov, class_entry, (php_http_new_t) php_http_message_body_object_new_ex, php_http_message_body_class_entry, php_http_message_body_copy(body, NULL, 0), NULL TSRMLS_CC)) {
733 RETVAL_OBJVAL(ov, 0);
734 }
735 }
736 } end_error_handling();
737 }
738
739 PHP_METHOD(HttpEnv, getResponseStatusForCode)
740 {
741 long code;
742
743 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code)) {
744 RETURN_STRING(php_http_env_get_response_status_for_code(code), 1);
745 }
746 RETURN_FALSE;
747 }
748
749 PHP_METHOD(HttpEnv, getResponseHeader)
750 {
751 char *header_name_str = NULL;
752 int header_name_len = 0;
753
754 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!", &header_name_str, &header_name_len)) {
755 if (header_name_str && header_name_len) {
756 char *header_value = php_http_env_get_response_header(header_name_str, header_name_len TSRMLS_CC);
757
758 if (header_value) {
759 RETURN_STRING(header_value, 0);
760 }
761 RETURN_NULL();
762 } else {
763 array_init(return_value);
764 php_http_env_get_response_headers(Z_ARRVAL_P(return_value) TSRMLS_CC);
765 return;
766 }
767 }
768 RETURN_FALSE;
769 }
770
771 PHP_METHOD(HttpEnv, getResponseCode)
772 {
773 if (SUCCESS == zend_parse_parameters_none()) {
774 RETURN_LONG(php_http_env_get_response_code(TSRMLS_C));
775 }
776 RETURN_FALSE;
777 }
778
779 PHP_METHOD(HttpEnv, setResponseHeader)
780 {
781 char *header_name_str;
782 int header_name_len;
783 zval *header_value = NULL;
784 long code = 0;
785 zend_bool replace_header = 1;
786
787 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z!lb", &header_name_str, &header_name_len, &header_value, &code, &replace_header)) {
788 RETURN_SUCCESS(php_http_env_set_response_header_value(code, header_name_str, header_name_len, header_value, replace_header TSRMLS_CC));
789 }
790 RETURN_FALSE;
791 }
792
793 PHP_METHOD(HttpEnv, setResponseCode)
794 {
795 long code;
796
797 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code)) {
798 RETURN_SUCCESS(php_http_env_set_response_code(code TSRMLS_CC));
799 }
800 RETURN_FALSE;
801 }
802
803 PHP_METHOD(HttpEnv, negotiateLanguage)
804 {
805 HashTable *supported;
806 zval *rs_array = NULL;
807
808 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H|z", &supported, &rs_array)) {
809 if (rs_array) {
810 zval_dtor(rs_array);
811 array_init(rs_array);
812 }
813
814 PHP_HTTP_DO_NEGOTIATE(language, supported, rs_array);
815 } else {
816 RETURN_FALSE;
817 }
818 }
819
820 PHP_METHOD(HttpEnv, negotiateCharset)
821 {
822 HashTable *supported;
823 zval *rs_array = NULL;
824
825 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H|z", &supported, &rs_array)) {
826 if (rs_array) {
827 zval_dtor(rs_array);
828 array_init(rs_array);
829 }
830 PHP_HTTP_DO_NEGOTIATE(charset, supported, rs_array);
831 } else {
832 RETURN_FALSE;
833 }
834 }
835
836 PHP_METHOD(HttpEnv, negotiateEncoding)
837 {
838 HashTable *supported;
839 zval *rs_array = NULL;
840
841 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H|z", &supported, &rs_array)) {
842 if (rs_array) {
843 zval_dtor(rs_array);
844 array_init(rs_array);
845 }
846 PHP_HTTP_DO_NEGOTIATE(encoding, supported, rs_array);
847 } else {
848 RETURN_FALSE;
849 }
850 }
851
852 PHP_METHOD(HttpEnv, negotiateContentType)
853 {
854 HashTable *supported;
855 zval *rs_array = NULL;
856
857 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "H|z", &supported, &rs_array)) {
858 if (rs_array) {
859 zval_dtor(rs_array);
860 array_init(rs_array);
861 }
862 PHP_HTTP_DO_NEGOTIATE(content_type, supported, rs_array);
863 } else {
864 RETURN_FALSE;
865 }
866 }
867
868 PHP_METHOD(HttpEnv, negotiate)
869 {
870 HashTable *supported;
871 zval *rs_array = NULL;
872 char *value_str, *sep_str = NULL;
873 int value_len, sep_len = 0;
874
875 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sH|s!z", &value_str, &value_len, &supported, &sep_str, &sep_len, &rs_array)) {
876 HashTable *rs;
877
878 if (rs_array) {
879 zval_dtor(rs_array);
880 array_init(rs_array);
881 }
882
883 if ((rs = php_http_negotiate(value_str, value_len, supported, sep_str, sep_len TSRMLS_CC))) {
884 PHP_HTTP_DO_NEGOTIATE_HANDLE_RESULT(rs, supported, rs_array);
885 } else {
886 PHP_HTTP_DO_NEGOTIATE_HANDLE_DEFAULT(supported, rs_array);
887 }
888 } else {
889 RETURN_FALSE;
890 }
891 }
892
893 PHP_METHOD(HttpEnv, statPersistentHandles)
894 {
895 if (SUCCESS == zend_parse_parameters_none()) {
896 object_init(return_value);
897 if (php_http_persistent_handle_statall(HASH_OF(return_value) TSRMLS_CC)) {
898 return;
899 }
900 zval_dtor(return_value);
901 }
902 RETURN_FALSE;
903 }
904
905 PHP_METHOD(HttpEnv, cleanPersistentHandles)
906 {
907 char *name_str = NULL, *ident_str = NULL;
908 int name_len = 0, ident_len = 0;
909
910 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!s!", &name_str, &name_len, &ident_str, &ident_len)) {
911 php_http_persistent_handle_cleanup(name_str, name_len, ident_str, ident_len TSRMLS_CC);
912 }
913 }
914
915 PHP_MINIT_FUNCTION(http_env)
916 {
917 PHP_HTTP_REGISTER_CLASS(http, Env, http_env, NULL, 0);
918
919 return SUCCESS;
920 }
921
922
923 /*
924 * Local variables:
925 * tab-width: 4
926 * c-basic-offset: 4
927 * End:
928 * vim600: noet sw=4 ts=4 fdm=marker
929 * vim<600: noet sw=4 ts=4
930 */