1/*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2014 The PHP Group                                |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 3.01 of the PHP license,      |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.php.net/license/3_01.txt                                  |
11   | If you did not receive a copy of the PHP license and are unable to   |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@php.net so we can mail you a copy immediately.               |
14   +----------------------------------------------------------------------+
15   | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca>                       |
16   |          Stig S�ther Bakken <ssb@php.net>                            |
17   |          David Sklar <sklar@student.net>                             |
18   +----------------------------------------------------------------------+
19 */
20/* $Id$ */
21
22#include "php_apache_http.h"
23
24#if defined(PHP_WIN32) || defined(NETWARE)
25#include "zend.h"
26#include "ap_compat.h"
27#else
28#include <build-defs.h>
29#endif
30
31#ifdef ZTS
32int php_apache_info_id;
33#else
34php_apache_info_struct php_apache_info;
35#endif
36
37#define SECTION(name)  PUTS("<H2 align=\"center\">" name "</H2>\n")
38
39#undef offsetof
40#define offsetof(s_type,field) ((size_t)&(((s_type*)0)->field))
41
42extern module *top_module;
43extern module **ap_loaded_modules;
44static int le_apachereq;
45static zend_class_entry *apacherequest_class_entry;
46
47static void apache_table_to_zval(table *, zval *return_value);
48
49PHP_FUNCTION(virtual);
50PHP_FUNCTION(apache_request_headers);
51PHP_FUNCTION(apache_response_headers);
52PHP_FUNCTION(apachelog);
53PHP_FUNCTION(apache_note);
54PHP_FUNCTION(apache_lookup_uri);
55PHP_FUNCTION(apache_child_terminate);
56PHP_FUNCTION(apache_setenv);
57PHP_FUNCTION(apache_get_version);
58PHP_FUNCTION(apache_get_modules);
59
60PHP_MINFO_FUNCTION(apache);
61
62ZEND_BEGIN_ARG_INFO_EX(arginfo_apachehooks_virtual, 0, 0, 1)
63    ZEND_ARG_INFO(0, filename)
64ZEND_END_ARG_INFO()
65
66ZEND_BEGIN_ARG_INFO_EX(arginfo_apachehooks_setenv, 0, 0, 2)
67    ZEND_ARG_INFO(0, variable)
68    ZEND_ARG_INFO(0, value)
69    ZEND_ARG_INFO(0, walk_to_top)
70ZEND_END_ARG_INFO()
71
72ZEND_BEGIN_ARG_INFO_EX(arginfo_apachehooks_lookup_uri, 0, 0, 1)
73    ZEND_ARG_INFO(0, uri)
74ZEND_END_ARG_INFO()
75
76ZEND_BEGIN_ARG_INFO(arginfo_apachehooks__void, 0)
77ZEND_END_ARG_INFO()
78
79ZEND_BEGIN_ARG_INFO_EX(arginfo_apachehooks_note, 0, 0, 1)
80    ZEND_ARG_INFO(0, note_name)
81    ZEND_ARG_INFO(0, note_value)
82ZEND_END_ARG_INFO()
83
84const zend_function_entry apache_functions[] = {
85    PHP_FE(virtual,                                 arginfo_apachehooks_virtual)
86    PHP_FE(apache_request_headers,                  arginfo_apachehooks__void)
87    PHP_FE(apache_note,                             arginfo_apachehooks_note)
88    PHP_FE(apache_lookup_uri,                       arginfo_apachehooks_lookup_uri)
89    PHP_FE(apache_child_terminate,                  arginfo_apachehooks__void)
90    PHP_FE(apache_setenv,                           arginfo_apachehooks_setenv)
91    PHP_FE(apache_response_headers,                 arginfo_apachehooks__void)
92    PHP_FE(apache_get_version,                      arginfo_apachehooks__void)
93    PHP_FE(apache_get_modules,                      arginfo_apachehooks__void)
94    PHP_FALIAS(getallheaders, apache_request_headers, arginfo_apachehooks__void)
95    {NULL, NULL, NULL}
96};
97
98/* {{{ php_apache ini entries
99 */
100PHP_INI_BEGIN()
101    STD_PHP_INI_ENTRY("xbithack",           "0",                PHP_INI_ALL,        OnUpdateLong,       xbithack, php_apache_info_struct, php_apache_info)
102    STD_PHP_INI_ENTRY("engine",             "1",                PHP_INI_ALL,        OnUpdateLong,       engine, php_apache_info_struct, php_apache_info)
103    STD_PHP_INI_ENTRY("last_modified",      "0",                PHP_INI_ALL,        OnUpdateLong,       last_modified, php_apache_info_struct, php_apache_info)
104    STD_PHP_INI_ENTRY("child_terminate",    "0",                PHP_INI_ALL,        OnUpdateLong,       terminate_child, php_apache_info_struct, php_apache_info)
105PHP_INI_END()
106/* }}} */
107
108static void php_apache_globals_ctor(php_apache_info_struct *apache_globals TSRMLS_DC)
109{
110    apache_globals->in_request = 0;
111}
112
113
114#define APREQ_GET_THIS(ZVAL)        if (NULL == (ZVAL = getThis())) { \
115                                        php_error(E_WARNING, "%s(): underlying ApacheRequest object missing", \
116                                            get_active_function_name(TSRMLS_C)); \
117                                        RETURN_FALSE; \
118                                    }
119#define APREQ_GET_REQUEST(ZVAL, R)  APREQ_GET_THIS(ZVAL); \
120                                    R = get_apache_request(ZVAL TSRMLS_CC)
121
122static void php_apache_request_free(zend_rsrc_list_entry *rsrc TSRMLS_DC)
123{
124    zval *z = (zval *)rsrc->ptr;
125/*  fprintf(stderr, "%s() %p\n", __FUNCTION__, z); */
126    zval_ptr_dtor(&z);
127}
128
129static request_rec *get_apache_request(zval *z TSRMLS_DC)
130{
131    request_rec *r;
132    zval **addr;
133
134    if (NULL == z) {
135        php_error(E_WARNING, "get_apache_request() invalid wrapper passed");
136        return NULL;
137    }
138
139    if (Z_TYPE_P(z) != IS_OBJECT) {
140        php_error(E_WARNING, "%s(): wrapper is not an object", get_active_function_name(TSRMLS_C));
141        return NULL;
142    }
143
144    if (zend_hash_index_find(Z_OBJPROP_P(z), 0, (void **)&addr) == FAILURE) {
145        php_error(E_WARNING, "%s(): underlying object missing", get_active_function_name(TSRMLS_C));
146        return NULL;
147    }
148
149    r = (request_rec *)Z_LVAL_PP(addr);
150    if (!r) {
151        php_error(E_WARNING, "%s(): request_rec invalid", get_active_function_name(TSRMLS_C));
152        return NULL;
153    }
154
155    return r;
156}
157
158/* {{{ php_apache_request_new(request_rec *r TSRMLS_DC)
159 * create a new zval-instance for ApacheRequest that wraps request_rec
160 */
161zval *php_apache_request_new(request_rec *r TSRMLS_DC)
162{
163    zval *req;
164    zval *addr;
165
166    MAKE_STD_ZVAL(addr);
167    Z_TYPE_P(addr) = IS_LONG;
168    Z_LVAL_P(addr) = (int) r;
169
170    MAKE_STD_ZVAL(req);
171    object_init_ex(req, apacherequest_class_entry);
172    zend_hash_index_update(Z_OBJPROP_P(req), 0, &addr, sizeof(zval *), NULL);
173
174    return req;
175}
176/* }}} */
177
178/* {{{ apache_request_read_string_slot()
179 */
180static void apache_request_read_string_slot(int offset, INTERNAL_FUNCTION_PARAMETERS)
181{
182    zval *id;
183    request_rec *r;
184    char *s;
185
186    if (zend_parse_parameters_none() == FAILURE) {
187        return;
188    }
189
190    APREQ_GET_REQUEST(id, r);
191
192    s = *(char **)((char*)r + offset);
193
194    if (s) {
195        RETURN_STRING(s, 1);
196    }
197
198    RETURN_EMPTY_STRING();
199}
200/* }}} */
201
202
203/* {{{ apache_request_string_slot()
204 */
205static void apache_request_string_slot(int offset, INTERNAL_FUNCTION_PARAMETERS)
206{
207    zval *id;
208    request_rec *r;
209    char *old_value, *new_value = NULL;
210    int new_value_len;
211    char **target;
212
213    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &new_value, &new_value_len) == FAILURE) {
214        return;
215    }
216
217    APREQ_GET_REQUEST(id, r);
218
219    target = (char **)((char*)r + offset);
220    old_value = *target;
221
222    if (new_value) {
223        *target = ap_pstrdup(r->pool, new_value);
224    }
225
226    if (old_value) {
227        RETURN_STRING(old_value, 1);
228    }
229
230    RETURN_EMPTY_STRING();
231}
232/* }}} */
233
234/* {{{ apache_request_read_int_slot()
235 */
236static void apache_request_read_int_slot(int offset, INTERNAL_FUNCTION_PARAMETERS)
237{
238    zval *id;
239    request_rec *r;
240    long l;
241
242    if (zend_parse_parameters_none() == FAILURE) {
243        return;
244    }
245
246    APREQ_GET_REQUEST(id, r);
247
248    l = *(long *)((char*)r + offset);
249
250    RETURN_LONG(l);
251}
252/* }}} */
253
254/* {{{ apache_request_int_slot()
255 */
256static void apache_request_int_slot(int offset, INTERNAL_FUNCTION_PARAMETERS)
257{
258    zval *id;
259    request_rec *r;
260    long old_value, new_value;
261    long *target;
262
263    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &new_value) == FAILURE) {
264        return;
265    }
266
267    APREQ_GET_REQUEST(id, r);
268
269    target = (long *)((char*)r + offset);
270    old_value = *target;
271
272    switch (ZEND_NUM_ARGS()) {
273        case 0:
274            break;
275        case 1:
276            *target = new_value;
277            break;
278        default:
279            WRONG_PARAM_COUNT;
280            break;
281    }
282
283    RETURN_LONG(old_value);
284}
285/* }}} */
286
287
288/* {{{ access string slots of request rec
289 */
290
291/* {{{ proto string ApacheRequest::filename([string new_filename])
292 */
293PHP_FUNCTION(apache_request_filename)
294{
295    apache_request_string_slot(offsetof(request_rec, filename), INTERNAL_FUNCTION_PARAM_PASSTHRU);
296}
297/* }}} */
298
299/* {{{ proto string ApacheRequest::uri([string new_uri])
300 */
301PHP_FUNCTION(apache_request_uri)
302{
303    apache_request_string_slot(offsetof(request_rec, uri), INTERNAL_FUNCTION_PARAM_PASSTHRU);
304}
305/* }}} */
306
307/* {{{ proto string ApacheRequest::unparsed_uri([string new_unparsed_uri])
308 */
309PHP_FUNCTION(apache_request_unparsed_uri)
310{
311    apache_request_string_slot(offsetof(request_rec, unparsed_uri), INTERNAL_FUNCTION_PARAM_PASSTHRU);
312}
313/* }}} */
314
315/* {{{ proto string ApacheRequest::path_info([string new_path_info])
316 */
317PHP_FUNCTION(apache_request_path_info)
318{
319    apache_request_string_slot(offsetof(request_rec, path_info), INTERNAL_FUNCTION_PARAM_PASSTHRU);
320}
321/* }}} */
322
323/* {{{ proto string ApacheRequest::args([string new_args])
324 */
325PHP_FUNCTION(apache_request_args)
326{
327    apache_request_string_slot(offsetof(request_rec, args), INTERNAL_FUNCTION_PARAM_PASSTHRU);
328}
329/* }}} */
330
331/* {{{ proto string ApacheRequest::boundary()
332 */
333PHP_FUNCTION(apache_request_boundary)
334{
335    apache_request_read_string_slot(offsetof(request_rec, boundary), INTERNAL_FUNCTION_PARAM_PASSTHRU);
336}
337/* }}} */
338
339
340/* {{{ proto string ApacheRequest::content_type([string new_type])
341 */
342PHP_FUNCTION(apache_request_content_type)
343{
344    apache_request_string_slot(offsetof(request_rec, content_type), INTERNAL_FUNCTION_PARAM_PASSTHRU);
345}
346/* }}} */
347
348/* {{{ proto string ApacheRequest::content_encoding([string new_encoding])
349 */
350PHP_FUNCTION(apache_request_content_encoding)
351{
352    apache_request_string_slot(offsetof(request_rec, content_encoding), INTERNAL_FUNCTION_PARAM_PASSTHRU);
353}
354/* }}} */
355
356/* {{{ proto string ApacheRequest::handler([string new_handler])
357 */
358PHP_FUNCTION(apache_request_handler)
359{
360    apache_request_string_slot(offsetof(request_rec, handler), INTERNAL_FUNCTION_PARAM_PASSTHRU);
361}
362/* }}} */
363
364/* {{{ proto string ApacheRequest::the_request()
365 */
366PHP_FUNCTION(apache_request_the_request)
367{
368    apache_request_read_string_slot(offsetof(request_rec, the_request), INTERNAL_FUNCTION_PARAM_PASSTHRU);
369}
370/* }}} */
371
372/* {{{ proto string ApacheRequest::protocol()
373 */
374PHP_FUNCTION(apache_request_protocol)
375{
376    apache_request_read_string_slot(offsetof(request_rec, protocol), INTERNAL_FUNCTION_PARAM_PASSTHRU);
377}
378/* }}} */
379
380/* {{{ proto string ApacheRequest::hostname()
381 */
382PHP_FUNCTION(apache_request_hostname)
383{
384    apache_request_read_string_slot(offsetof(request_rec, hostname), INTERNAL_FUNCTION_PARAM_PASSTHRU);
385}
386/* }}} */
387
388/* {{{ proto string ApacheRequest::status_line([string new_status_line])
389 */
390PHP_FUNCTION(apache_request_status_line)
391{
392    apache_request_string_slot(offsetof(request_rec, status_line), INTERNAL_FUNCTION_PARAM_PASSTHRU);
393}
394/* }}} */
395
396/* {{{ proto string ApacheRequest::method()
397 */
398PHP_FUNCTION(apache_request_method)
399{
400    apache_request_read_string_slot(offsetof(request_rec, method), INTERNAL_FUNCTION_PARAM_PASSTHRU);
401}
402/* }}} */
403
404/* }}} access string slots of request rec */
405
406/* {{{ access int slots of request_rec
407 */
408
409/* {{{ proto int ApacheRequest::proto_num()
410 */
411PHP_FUNCTION(apache_request_proto_num)
412{
413    apache_request_read_int_slot(offsetof(request_rec, proto_num), INTERNAL_FUNCTION_PARAM_PASSTHRU);
414}
415/* }}} */
416
417/* {{{ proto int ApacheRequest::assbackwards()
418 */
419PHP_FUNCTION(apache_request_assbackwards)
420{
421    apache_request_read_int_slot(offsetof(request_rec, assbackwards), INTERNAL_FUNCTION_PARAM_PASSTHRU);
422}
423/* }}} */
424
425
426/* {{{ proto int ApacheRequest::proxyreq([int new_proxyreq])
427 */
428PHP_FUNCTION(apache_request_proxyreq)
429{
430    apache_request_int_slot(offsetof(request_rec, proxyreq), INTERNAL_FUNCTION_PARAM_PASSTHRU);
431}
432/* }}} */
433
434/* {{{ proto int ApacheRequest::chunked()
435 */
436PHP_FUNCTION(apache_request_chunked)
437{
438    apache_request_read_int_slot(offsetof(request_rec, chunked), INTERNAL_FUNCTION_PARAM_PASSTHRU);
439}
440/* }}} */
441
442
443/* {{{ proto int ApacheRequest::header_only()
444 */
445PHP_FUNCTION(apache_request_header_only)
446{
447    apache_request_read_int_slot(offsetof(request_rec, header_only), INTERNAL_FUNCTION_PARAM_PASSTHRU);
448}
449/* }}} */
450
451/* {{{ proto int ApacheRequest::request_time()
452 */
453PHP_FUNCTION(apache_request_request_time)
454{
455    apache_request_read_int_slot(offsetof(request_rec, request_time), INTERNAL_FUNCTION_PARAM_PASSTHRU);
456}
457/* }}} */
458
459/* {{{ proto int ApacheRequest::status([int new_status])
460 */
461PHP_FUNCTION(apache_request_status)
462{
463    apache_request_int_slot(offsetof(request_rec, status), INTERNAL_FUNCTION_PARAM_PASSTHRU);
464}
465/* }}} */
466
467/* {{{ proto int ApacheRequest::method_number([int method_number])
468 */
469PHP_FUNCTION(apache_request_method_number)
470{
471    apache_request_read_int_slot(offsetof(request_rec, method_number), INTERNAL_FUNCTION_PARAM_PASSTHRU);
472}
473/* }}} */
474
475/* {{{ proto int ApacheRequest::allowed([int allowed])
476 */
477PHP_FUNCTION(apache_request_allowed)
478{
479    apache_request_int_slot(offsetof(request_rec, allowed), INTERNAL_FUNCTION_PARAM_PASSTHRU);
480}
481/* }}} */
482
483/* {{{ proto int ApacheRequest::bytes_sent()
484 */
485PHP_FUNCTION(apache_request_bytes_sent)
486{
487    apache_request_read_int_slot(offsetof(request_rec, bytes_sent), INTERNAL_FUNCTION_PARAM_PASSTHRU);
488}
489/* }}} */
490
491/* {{{ proto int ApacheRequest::mtime()
492 */
493PHP_FUNCTION(apache_request_mtime)
494{
495    apache_request_read_int_slot(offsetof(request_rec, mtime), INTERNAL_FUNCTION_PARAM_PASSTHRU);
496}
497/* }}} */
498
499/* {{{ proto int ApacheRequest::content_length([int new_content_length])
500 */
501PHP_FUNCTION(apache_request_content_length)
502{
503    zval *id;
504    long zlen;
505    request_rec *r;
506
507    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &zlen) == FAILURE) {
508        return;
509    }
510
511    if (ZEND_NUM_ARGS() == 0) {
512        apache_request_read_int_slot(offsetof(request_rec, clength), INTERNAL_FUNCTION_PARAM_PASSTHRU);
513    } else {
514        APREQ_GET_REQUEST(id, r);
515
516        (void)ap_set_content_length(r, zlen);
517        RETURN_TRUE;
518    }
519}
520/* }}} */
521
522/* {{{ proto int ApacheRequest::remaining()
523 */
524PHP_FUNCTION(apache_request_remaining)
525{
526    apache_request_read_int_slot(offsetof(request_rec, remaining), INTERNAL_FUNCTION_PARAM_PASSTHRU);
527}
528/* }}} */
529
530/* {{{ proto int ApacheRequest::no_cache()
531 */
532PHP_FUNCTION(apache_request_no_cache)
533{
534    apache_request_int_slot(offsetof(request_rec, no_cache), INTERNAL_FUNCTION_PARAM_PASSTHRU);
535}
536/* }}} */
537
538/* {{{ proto int ApacheRequest::no_local_copy()
539 */
540PHP_FUNCTION(apache_request_no_local_copy)
541{
542    apache_request_int_slot(offsetof(request_rec, no_local_copy), INTERNAL_FUNCTION_PARAM_PASSTHRU);
543}
544/* }}} */
545
546/* {{{ proto int ApacheRequest::read_body()
547 */
548PHP_FUNCTION(apache_request_read_body)
549{
550    apache_request_int_slot(offsetof(request_rec, read_body), INTERNAL_FUNCTION_PARAM_PASSTHRU);
551}
552/* }}} */
553
554
555/* }}} access int slots of request_rec */
556
557
558/* {{{ proto array apache_request_headers_in()
559 * fetch all incoming request headers
560 */
561PHP_FUNCTION(apache_request_headers_in)
562{
563    zval *id;
564    request_rec *r;
565
566    APREQ_GET_REQUEST(id, r);
567
568    apache_table_to_zval(r->headers_in, return_value);
569}
570/* }}} */
571
572
573/* {{{ add_header_to_table
574*/
575static void add_header_to_table(table *t, INTERNAL_FUNCTION_PARAMETERS)
576{
577    zval *first = NULL;
578    zval *second = NULL;
579    zval **entry, **value;
580    char *string_key;
581    uint string_key_len;
582    ulong num_key;
583
584    zend_bool replace = 0;
585    HashPosition pos;
586
587    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|zb", &first, &second, &replace) == FAILURE) {
588        RETURN_FALSE;
589    }
590
591    if (Z_TYPE_P(first) == IS_ARRAY) {
592        switch(ZEND_NUM_ARGS()) {
593            case 1:
594            case 3:
595                zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(first), &pos);
596                while (zend_hash_get_current_data_ex(Z_ARRVAL_P(first), (void **)&entry, &pos) == SUCCESS) {
597                    switch(zend_hash_get_current_key_ex(Z_ARRVAL_P(first), &string_key, &string_key_len, &num_key, 0, &pos)) {
598                        case HASH_KEY_IS_STRING:
599                            if (zend_hash_find(Z_ARRVAL_P(first), string_key, string_key_len, (void **)&value) == FAILURE) {
600                                zend_hash_move_forward_ex(Z_ARRVAL_P(first), &pos);
601                                continue;
602                            }
603                            if (!value) {
604                                zend_hash_move_forward_ex(Z_ARRVAL_P(first), &pos);
605                                continue;
606                            }
607
608                            convert_to_string_ex(value);
609                            if (replace) {
610                                ap_table_set(t, string_key, Z_STRVAL_PP(value));
611                            } else {
612                                ap_table_merge(t, string_key, Z_STRVAL_PP(value));
613                            }
614                            break;
615                        case HASH_KEY_IS_LONG:
616                        default:
617                            php_error(E_WARNING, "%s(): Can only add STRING keys to headers!", get_active_function_name(TSRMLS_C));
618                            break;
619                    }
620
621                    zend_hash_move_forward_ex(Z_ARRVAL_P(first), &pos);
622                }
623                break;
624            default:
625                WRONG_PARAM_COUNT;
626                break;
627        }
628    } else if (Z_TYPE_P(first) == IS_STRING) {
629        switch(ZEND_NUM_ARGS()) {
630            case 2:
631            case 3:
632                convert_to_string_ex(&second);
633                if (replace) {
634                    ap_table_set(t, Z_STRVAL_P(first), Z_STRVAL_P(second));
635                } else {
636                    ap_table_merge(t, Z_STRVAL_P(first), Z_STRVAL_P(second));
637                }
638                break;
639            default:
640                WRONG_PARAM_COUNT;
641                break;
642        }
643    } else {
644        RETURN_FALSE;
645    }
646}
647
648/* }}} */
649
650
651/* {{{ proto array apache_request_headers_out([{string name|array list} [, string value [, bool replace = false]]])
652 * fetch all outgoing request headers
653 */
654PHP_FUNCTION(apache_request_headers_out)
655{
656    zval *id;
657    request_rec *r;
658
659    APREQ_GET_REQUEST(id, r);
660
661    if (ZEND_NUM_ARGS() > 0) {
662        add_header_to_table(r->headers_out, INTERNAL_FUNCTION_PARAM_PASSTHRU);
663    }
664
665    apache_table_to_zval(r->headers_out, return_value);
666}
667/* }}} */
668
669
670/* {{{ proto array apache_request_err_headers_out([{string name|array list} [, string value [, bool replace = false]]])
671 * fetch all headers that go out in case of an error or a subrequest
672 */
673PHP_FUNCTION(apache_request_err_headers_out)
674{
675    zval *id;
676    request_rec *r;
677
678    APREQ_GET_REQUEST(id, r);
679
680    if (ZEND_NUM_ARGS() > 0) {
681        add_header_to_table(r->err_headers_out, INTERNAL_FUNCTION_PARAM_PASSTHRU);
682    }
683
684    apache_table_to_zval(r->err_headers_out, return_value);
685}
686/* }}} */
687
688
689/* {{{ proxy functions for the ap_* functions family
690 */
691
692/* {{{ proto int apache_request_server_port()
693 */
694PHP_FUNCTION(apache_request_server_port)
695{
696    zval *id;
697    request_rec *r;
698
699    if (zend_parse_parameters_none() == FAILURE) {
700        return;
701    }
702
703    APREQ_GET_REQUEST(id, r);
704
705    RETURN_LONG(ap_get_server_port(r));
706}
707/* }}} */
708
709/* {{{ proto int apache_request_remote_host([int type])
710 */
711PHP_FUNCTION(apache_request_remote_host)
712{
713    zval *id;
714    long type = 0;
715    request_rec *r;
716    char *res;
717
718    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &type) == FAILURE) {
719        return;
720    }
721
722    if (!type) {
723        type = REMOTE_NAME;
724    }
725
726    APREQ_GET_REQUEST(id, r);
727
728    res = (char *)ap_get_remote_host(r->connection, r->per_dir_config, (int)type);
729
730    if (res) {
731        RETURN_STRING(res, 1);
732    }
733
734    RETURN_EMPTY_STRING();
735}
736/* }}} */
737
738/* {{{ proto long apache_request_update_mtime([int dependency_mtime])
739 */
740PHP_FUNCTION(apache_request_update_mtime)
741{
742    zval *id;
743    request_rec *r;
744    long mtime = 0;
745
746    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &mtime) == FAILURE) {
747        return;
748    }
749
750    APREQ_GET_REQUEST(id, r);
751
752    RETURN_LONG(ap_update_mtime(r, (int) mtime));
753}
754/* }}} */
755
756
757/* {{{ proto void apache_request_set_etag()
758 */
759PHP_FUNCTION(apache_request_set_etag)
760{
761    zval *id;
762    request_rec *r;
763
764    if (zend_parse_parameters_none() == FAILURE) {
765        return;
766    }
767
768    APREQ_GET_REQUEST(id, r);
769
770    ap_set_etag(r);
771    RETURN_TRUE;
772}
773/* }}} */
774
775/* {{{ proto void apache_request_set_last_modified()
776 */
777PHP_FUNCTION(apache_request_set_last_modified)
778{
779    zval *id;
780    request_rec *r;
781
782    if (zend_parse_parameters_none() == FAILURE) {
783        return;
784    }
785
786    APREQ_GET_REQUEST(id, r);
787
788    ap_set_last_modified(r);
789    RETURN_TRUE;
790}
791/* }}} */
792
793/* {{{ proto long apache_request_meets_conditions()
794 */
795PHP_FUNCTION(apache_request_meets_conditions)
796{
797    zval *id;
798    request_rec *r;
799
800    if (zend_parse_parameters_none() == FAILURE) {
801        return;
802    }
803
804    APREQ_GET_REQUEST(id, r);
805
806    RETURN_LONG(ap_meets_conditions(r));
807}
808/* }}} */
809
810/* {{{ proto long apache_request_discard_request_body()
811 */
812PHP_FUNCTION(apache_request_discard_request_body)
813{
814    zval *id;
815    request_rec *r;
816
817    if (zend_parse_parameters_none() == FAILURE) {
818        return;
819    }
820
821    APREQ_GET_REQUEST(id, r);
822
823    RETURN_LONG(ap_discard_request_body(r));
824}
825/* }}} */
826
827/* {{{ proto long apache_request_satisfies()
828 */
829PHP_FUNCTION(apache_request_satisfies)
830{
831    zval *id;
832    request_rec *r;
833
834    if (zend_parse_parameters_none() == FAILURE) {
835        return;
836    }
837
838    APREQ_GET_REQUEST(id, r);
839
840    RETURN_LONG(ap_satisfies(r));
841}
842/* }}} */
843
844
845/* {{{ proto bool apache_request_is_initial_req()
846 */
847PHP_FUNCTION(apache_request_is_initial_req)
848{
849    zval *id;
850    request_rec *r;
851
852    if (zend_parse_parameters_none() == FAILURE) {
853        return;
854    }
855
856    APREQ_GET_REQUEST(id, r);
857
858    RETURN_BOOL(ap_is_initial_req(r));
859}
860/* }}} */
861
862/* {{{ proto bool apache_request_some_auth_required()
863 */
864PHP_FUNCTION(apache_request_some_auth_required)
865{
866    zval *id;
867    request_rec *r;
868
869    if (zend_parse_parameters_none() == FAILURE) {
870        return;
871    }
872
873    APREQ_GET_REQUEST(id, r);
874
875    RETURN_BOOL(ap_some_auth_required(r));
876}
877/* }}} */
878
879/* {{{ proto string apache_request_auth_type()
880 */
881PHP_FUNCTION(apache_request_auth_type)
882{
883    zval *id;
884    request_rec *r;
885    char *t;
886
887    if (zend_parse_parameters_none() == FAILURE) {
888        return;
889    }
890
891    APREQ_GET_REQUEST(id, r);
892
893    t = (char *)ap_auth_type(r);
894    if (!t) {
895        RETURN_NULL();
896    }
897
898    RETURN_STRING(t, 1);
899}
900/* }}} */
901
902/* {{{ proto string apache_request_auth_name()
903 */
904PHP_FUNCTION(apache_request_auth_name)
905{
906    zval *id;
907    request_rec *r;
908    char *t;
909
910    if (zend_parse_parameters_none() == FAILURE) {
911        return;
912    }
913
914    APREQ_GET_REQUEST(id, r);
915
916    t = (char *)ap_auth_name(r);
917    if (!t) {
918        RETURN_NULL();
919    }
920
921    RETURN_STRING(t, 1);
922}
923/* }}} */
924
925/* {{{ proto apache_request_basic_auth_pw()
926 */
927PHP_FUNCTION(apache_request_basic_auth_pw)
928{
929    zval *id, *zpw;
930    request_rec *r;
931    const char *pw;
932    long status;
933
934    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zpw) == FAILURE) {
935        return;
936    }
937
938    if (!PZVAL_IS_REF(zpw)) {
939        zend_error(E_WARNING, "Parameter wasn't passed by reference");
940        RETURN_NULL();
941    }
942
943    APREQ_GET_REQUEST(id, r);
944
945    pw = NULL;
946    status = ap_get_basic_auth_pw(r, &pw);
947    if (status == OK && pw) {
948        ZVAL_STRING(zpw, (char *)pw, 1);
949    } else {
950        ZVAL_NULL(zpw);
951    }
952    RETURN_LONG(status);
953}
954/* }}} */
955
956
957/* http_protocol.h */
958
959PHP_FUNCTION(apache_request_send_http_header)
960{
961    zval *id;
962    request_rec *r;
963    char *type = NULL;
964    int typelen;
965
966    if (zend_parse_parameters(ZEND_NUM_ARGS()  TSRMLS_CC, "|s", &type, &typelen) == FAILURE) {
967        return;
968    }
969
970    APREQ_GET_REQUEST(id, r);
971    if(type) {
972        r->content_type = pstrdup(r->pool, type);
973    }
974    ap_send_http_header(r);
975    SG(headers_sent) = 1;
976    AP(headers_sent) = 1;
977    RETURN_TRUE;
978}
979
980PHP_FUNCTION(apache_request_basic_http_header)
981{
982    zval *id;
983    request_rec *r;
984
985    if (zend_parse_parameters_none() == FAILURE) {
986        return;
987    }
988
989    APREQ_GET_REQUEST(id, r);
990
991    ap_basic_http_header((request_rec *)SG(server_context));
992    SG(headers_sent) = 1;
993    AP(headers_sent) = 1;
994    RETURN_TRUE;
995}
996
997PHP_FUNCTION(apache_request_send_http_trace)
998{
999    zval *id;
1000    request_rec *r;
1001
1002    if (zend_parse_parameters_none() == FAILURE) {
1003        return;
1004    }
1005
1006    APREQ_GET_REQUEST(id, r);
1007
1008    ap_send_http_trace((request_rec *)SG(server_context));
1009    SG(headers_sent) = 1;
1010    AP(headers_sent) = 1;
1011    RETURN_TRUE;
1012}
1013
1014PHP_FUNCTION(apache_request_send_http_options)
1015{
1016    zval *id;
1017    request_rec *r;
1018
1019    if (zend_parse_parameters_none() == FAILURE) {
1020        return;
1021    }
1022
1023    APREQ_GET_REQUEST(id, r);
1024
1025    ap_send_http_options((request_rec *)SG(server_context));
1026    SG(headers_sent) = 1;
1027    AP(headers_sent) = 1;
1028    RETURN_TRUE;
1029}
1030
1031PHP_FUNCTION(apache_request_send_error_response)
1032{
1033    zval *id;
1034    request_rec *r;
1035    long rec = 0;
1036
1037    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &rec) == FAILURE) {
1038        return;
1039    }
1040
1041    APREQ_GET_REQUEST(id, r);
1042    ap_send_error_response(r, (int) rec);
1043    RETURN_TRUE;
1044}
1045
1046PHP_FUNCTION(apache_request_set_content_length)
1047{
1048    long length;
1049    zval *id;
1050    request_rec *r;
1051
1052    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &length) == FAILURE) {
1053        return;
1054    }
1055
1056    APREQ_GET_REQUEST(id, r);
1057
1058    ap_set_content_length(r, length);
1059    RETURN_TRUE;
1060}
1061
1062PHP_FUNCTION(apache_request_set_keepalive)
1063{
1064    zval *id;
1065    request_rec *r;
1066
1067    if (zend_parse_parameters_none() == FAILURE) {
1068        return;
1069    }
1070
1071    APREQ_GET_REQUEST(id, r);
1072    ap_set_keepalive(r);
1073    RETURN_TRUE;
1074}
1075
1076/* This stuff should use streams or however this is implemented now
1077
1078PHP_FUNCTION(apache_request_send_fd)
1079{
1080}
1081
1082PHP_FUNCTION(apache_request_send_fd_length)
1083{
1084}
1085*/
1086
1087/* These are for overriding default output behaviour */
1088PHP_FUNCTION(apache_request_rputs)
1089{
1090    char *buffer;
1091    int buffer_len;
1092    zval *id;
1093    request_rec *r;
1094
1095    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buffer, &buffer_len) == FAILURE) {
1096        return;
1097    }
1098
1099    APREQ_GET_REQUEST(id, r);
1100    ap_rwrite(buffer, buffer_len, (request_rec*)SG(server_context));
1101}
1102
1103/* This stuff would be useful for custom POST handlers,
1104   which should be supported.  Probably by not using
1105   sapi_activate at all inside a phpResponseHandler
1106   and instead using a builtin composed of the below
1107   calls as a apache_read_request_body() and allow
1108   people to custom craft their own.
1109
1110PHP_FUNCTION(apache_request_setup_client_block)
1111{
1112}
1113
1114PHP_FUNCTION(apache_request_should_client_block)
1115{
1116}
1117
1118PHP_FUNCTION(apache_request_get_client_block)
1119{
1120}
1121
1122PHP_FUNCTION(apache_request_discard_request_body)
1123{
1124}
1125*/
1126
1127/* http_log.h */
1128
1129/* {{{ proto boolean apache_request_log_error(string message, [long facility])
1130 */
1131PHP_FUNCTION(apache_request_log_error)
1132{
1133    zval *id;
1134    char *z_errstr;
1135    int z_errstr_len;
1136    long facility = APLOG_ERR;
1137    request_rec *r;
1138
1139    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &z_errstr, &z_errstr_len, &facility) == FAILURE) {
1140        return;
1141    }
1142
1143    APREQ_GET_REQUEST(id, r);
1144    ap_log_error(APLOG_MARK, (int) facility, r->server, "%s", z_errstr);
1145    RETURN_TRUE;
1146}
1147/* }}} */
1148/* http_main.h */
1149
1150/* {{{ proto object apache_request_sub_req_lookup_uri(string uri)
1151    Returns sub-request for the specified uri.  You would
1152    need to run it yourself with run()
1153*/
1154PHP_FUNCTION(apache_request_sub_req_lookup_uri)
1155{
1156    zval *id;
1157    char *file;
1158    int file_len;
1159    request_rec *r, *sub_r;
1160
1161    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &file_len) == FAILURE) {
1162        return;
1163    }
1164
1165    APREQ_GET_REQUEST(id, r);
1166    sub_r = ap_sub_req_lookup_uri(file, r);
1167
1168    if (!sub_r) {
1169        RETURN_FALSE;
1170    }
1171    return_value = php_apache_request_new(sub_r TSRMLS_CC);
1172}
1173/* }}} */
1174
1175/* {{{ proto object apache_request_sub_req_lookup_file(string file)
1176    Returns sub-request for the specified file.  You would
1177    need to run it yourself with run().
1178*/
1179PHP_FUNCTION(apache_request_sub_req_lookup_file)
1180{
1181    zval *id;
1182    char *file;
1183    int file_len;
1184    request_rec *r, *sub_r;
1185
1186    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &file_len) == FAILURE) {
1187        return;
1188    }
1189
1190    APREQ_GET_REQUEST(id, r);
1191
1192    sub_r = ap_sub_req_lookup_file(file, r);
1193
1194    if (!sub_r) {
1195        RETURN_FALSE;
1196    }
1197    return_value = php_apache_request_new(sub_r TSRMLS_CC);
1198}
1199/* }}} */
1200
1201/* {{{ proto object apache_request_sub_req_method_uri(string method, string uri)
1202    Returns sub-request for the specified file.  You would
1203    need to run it yourself with run().
1204*/
1205PHP_FUNCTION(apache_request_sub_req_method_uri)
1206{
1207    zval *id;
1208    char *file, *method;
1209    int file_len, method_len;
1210    request_rec *r, *sub_r;
1211
1212    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &method, &method_len, &file, &file_len) == FAILURE) {
1213        return;
1214    }
1215
1216    APREQ_GET_REQUEST(id, r);
1217
1218    sub_r = ap_sub_req_method_uri(method, file, r);
1219
1220    if (!sub_r) {
1221        RETURN_FALSE;
1222    }
1223    return_value = php_apache_request_new(sub_r TSRMLS_CC);
1224}
1225/* }}} */
1226
1227/* {{{ proto long apache_request_run()
1228    This is a wrapper for ap_sub_run_req and ap_destory_sub_req.  It takes
1229    sub_request, runs it, destroys it, and returns it's status.
1230*/
1231PHP_FUNCTION(apache_request_run)
1232{
1233    zval *id;
1234    request_rec *r;
1235    int status;
1236
1237    if (zend_parse_parameters_none() == FAILURE) {
1238        return;
1239    }
1240
1241    APREQ_GET_REQUEST(id, r);
1242    if (!r || ap_is_initial_req(r)) {
1243        RETURN_FALSE;
1244    }
1245    status = ap_run_sub_req(r);
1246    ap_destroy_sub_req(r);
1247    RETURN_LONG(status);
1248}
1249/* }}} */
1250
1251PHP_FUNCTION(apache_request_internal_redirect)
1252{
1253    zval *id;
1254    char *new_uri;
1255    int new_uri_len;
1256    request_rec *r;
1257
1258    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &new_uri, &new_uri_len) == FAILURE) {
1259        return;
1260    }
1261
1262    APREQ_GET_REQUEST(id, r);
1263
1264    ap_internal_redirect(new_uri, r);
1265}
1266
1267PHP_FUNCTION(apache_request_send_header_field)
1268{
1269    char *fieldname, *fieldval;
1270    int fieldname_len, fieldval_len;
1271    zval *id;
1272    request_rec *r;
1273
1274    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &fieldname, &fieldname_len, &fieldval, &fieldval_len) == FAILURE) {
1275        return;
1276    }
1277
1278    APREQ_GET_REQUEST(id, r);
1279
1280    ap_send_header_field(r, fieldname, fieldval);
1281    SG(headers_sent) = 1;
1282    AP(headers_sent) = 1;
1283}
1284
1285
1286
1287/* }}} */
1288
1289/* {{{ php_apache_request_class_functions
1290 */
1291const static zend_function_entry php_apache_request_class_functions[] = {
1292    /* string slots */
1293    PHP_FALIAS(args,                        apache_request_args,                NULL)
1294    PHP_FALIAS(boundary,                    apache_request_boundary,            NULL)
1295    PHP_FALIAS(content_encoding,            apache_request_content_encoding,    NULL)
1296    PHP_FALIAS(content_type,                apache_request_content_type,        NULL)
1297    PHP_FALIAS(filename,                    apache_request_filename,            NULL)
1298    PHP_FALIAS(handler,                     apache_request_handler,             NULL)
1299    PHP_FALIAS(hostname,                    apache_request_hostname,            NULL)
1300    PHP_FALIAS(method,                      apache_request_method,              NULL)
1301    PHP_FALIAS(path_info,                   apache_request_path_info,           NULL)
1302    PHP_FALIAS(protocol,                    apache_request_protocol,            NULL)
1303    PHP_FALIAS(status_line,                 apache_request_status_line,         NULL)
1304    PHP_FALIAS(the_request,                 apache_request_the_request,         NULL)
1305    PHP_FALIAS(unparsed_uri,                apache_request_unparsed_uri,        NULL)
1306    PHP_FALIAS(uri,                         apache_request_uri,                 NULL)
1307
1308    /* int slots */
1309    PHP_FALIAS(allowed,                     apache_request_allowed,             NULL)
1310    PHP_FALIAS(bytes_sent,                  apache_request_bytes_sent,          NULL)
1311    PHP_FALIAS(chunked,                     apache_request_chunked,             NULL)
1312    PHP_FALIAS(content_length,              apache_request_content_length,      NULL)
1313    PHP_FALIAS(header_only,                 apache_request_header_only,         NULL)
1314    PHP_FALIAS(method_number,               apache_request_method_number,       NULL)
1315    PHP_FALIAS(mtime,                       apache_request_mtime,               NULL)
1316    PHP_FALIAS(no_cache,                    apache_request_no_cache,            NULL)
1317    PHP_FALIAS(no_local_copy,               apache_request_no_local_copy,       NULL)
1318    PHP_FALIAS(proto_num,                   apache_request_proto_num,           NULL)
1319    PHP_FALIAS(proxyreq,                    apache_request_proxyreq,            NULL)
1320    PHP_FALIAS(read_body,                   apache_request_read_body,           NULL)
1321    PHP_FALIAS(remaining,                   apache_request_remaining,           NULL)
1322    PHP_FALIAS(request_time,                apache_request_request_time,        NULL)
1323    PHP_FALIAS(status,                      apache_request_status,              NULL)
1324
1325    /* tables & arrays */
1326    PHP_FALIAS(headers_in,                  apache_request_headers_in,          NULL)
1327    PHP_FALIAS(headers_out,                 apache_request_headers_out,         NULL)
1328    PHP_FALIAS(err_headers_out,             apache_request_err_headers_out,         NULL)
1329
1330
1331    /* proxy functions for the ap_* functions family */
1332#undef auth_name
1333#undef auth_type
1334#undef discard_request_body
1335#undef is_initial_req
1336#undef meets_conditions
1337#undef satisfies
1338#undef set_etag
1339#undef set_last_modified
1340#undef some_auth_required
1341#undef update_mtime
1342#undef send_http_header
1343#undef send_header_field
1344#undef basic_http_header
1345#undef send_http_trace
1346#undef send_http_options
1347#undef send_error_response
1348#undef set_content_length
1349#undef set_keepalive
1350#undef rputs
1351#undef log_error
1352#undef lookup_uri
1353#undef lookup_file
1354#undef method_uri
1355#undef run
1356#undef internal_redirect
1357    PHP_FALIAS(auth_name,                   apache_request_auth_name,               NULL)
1358    PHP_FALIAS(auth_type,                   apache_request_auth_type,               NULL)
1359    PHP_FALIAS(basic_auth_pw,               apache_request_basic_auth_pw,           NULL)
1360    PHP_FALIAS(discard_request_body,        apache_request_discard_request_body,    NULL)
1361    PHP_FALIAS(is_initial_req,              apache_request_is_initial_req,          NULL)
1362    PHP_FALIAS(meets_conditions,            apache_request_meets_conditions,        NULL)
1363    PHP_FALIAS(remote_host,                 apache_request_remote_host,             NULL)
1364    PHP_FALIAS(satisfies,                   apache_request_satisfies,               NULL)
1365    PHP_FALIAS(server_port,                 apache_request_server_port,             NULL)
1366    PHP_FALIAS(set_etag,                    apache_request_set_etag,                NULL)
1367    PHP_FALIAS(set_last_modified,           apache_request_set_last_modified,       NULL)
1368    PHP_FALIAS(some_auth_required,          apache_request_some_auth_required,      NULL)
1369    PHP_FALIAS(update_mtime,                apache_request_update_mtime,            NULL)
1370    PHP_FALIAS(send_http_header,            apache_request_send_http_header,        NULL)
1371    PHP_FALIAS(basic_http_header,           apache_request_basic_http_header,       NULL)
1372    PHP_FALIAS(send_header_field,           apache_request_send_header_field,       NULL)
1373    PHP_FALIAS(send_http_trace,             apache_request_send_http_trace,         NULL)
1374    PHP_FALIAS(send_http_options,           apache_request_send_http_trace,         NULL)
1375    PHP_FALIAS(send_error_response,         apache_request_send_error_response,     NULL)
1376    PHP_FALIAS(set_content_length,          apache_request_set_content_length,      NULL)
1377    PHP_FALIAS(set_keepalive,               apache_request_set_keepalive,           NULL)
1378    PHP_FALIAS(rputs,                       apache_request_rputs,                   NULL)
1379    PHP_FALIAS(log_error,                   apache_request_log_error,               NULL)
1380    PHP_FALIAS(lookup_uri,                  apache_request_sub_req_lookup_uri,      NULL)
1381    PHP_FALIAS(lookup_file,                 apache_request_sub_req_lookup_file,     NULL)
1382    PHP_FALIAS(method_uri,                  apache_request_sub_req_method_uri,      NULL)
1383    PHP_FALIAS(run,                         apache_request_run,                     NULL)
1384    PHP_FALIAS(internal_redirect,           apache_request_internal_redirect,       NULL)
1385    PHP_FE_END
1386};
1387/* }}} */
1388
1389
1390static PHP_MINIT_FUNCTION(apache)
1391{
1392    zend_class_entry ce;
1393
1394#ifdef ZTS
1395    ts_allocate_id(&php_apache_info_id, sizeof(php_apache_info_struct), (ts_allocate_ctor) php_apache_globals_ctor, NULL);
1396#else
1397    php_apache_globals_ctor(&php_apache_info TSRMLS_CC);
1398#endif
1399    REGISTER_INI_ENTRIES();
1400
1401
1402    le_apachereq = zend_register_list_destructors_ex(php_apache_request_free, NULL, "ApacheRequest", module_number);
1403    INIT_OVERLOADED_CLASS_ENTRY(ce, "ApacheRequest", php_apache_request_class_functions, NULL, NULL, NULL);
1404    apacherequest_class_entry = zend_register_internal_class_ex(&ce, NULL TSRMLS_CC);
1405
1406    REGISTER_LONG_CONSTANT("OK",                OK,                 CONST_CS | CONST_PERSISTENT);
1407    REGISTER_LONG_CONSTANT("DECLINED",          DECLINED,           CONST_CS | CONST_PERSISTENT);
1408    REGISTER_LONG_CONSTANT("FORBIDDEN",         FORBIDDEN,          CONST_CS | CONST_PERSISTENT);
1409    REGISTER_LONG_CONSTANT("AUTH_REQUIRED",     AUTH_REQUIRED,      CONST_CS | CONST_PERSISTENT);
1410    REGISTER_LONG_CONSTANT("DONE",              DONE,               CONST_CS | CONST_PERSISTENT);
1411    REGISTER_LONG_CONSTANT("SERVER_ERROR",      SERVER_ERROR,       CONST_CS | CONST_PERSISTENT);
1412    REGISTER_LONG_CONSTANT("REDIRECT",          REDIRECT,           CONST_CS | CONST_PERSISTENT);
1413    REGISTER_LONG_CONSTANT("BAD_REQUEST",       BAD_REQUEST,        CONST_CS | CONST_PERSISTENT);
1414    REGISTER_LONG_CONSTANT("NOT_FOUND",         NOT_FOUND,          CONST_CS | CONST_PERSISTENT);
1415    REGISTER_LONG_CONSTANT("HTTP_CONTINUE",     HTTP_CONTINUE,   CONST_CS | CONST_PERSISTENT);
1416    REGISTER_LONG_CONSTANT("HTTP_SWITCHING_PROTOCOLS",     HTTP_SWITCHING_PROTOCOLS,   CONST_CS | CONST_PERSISTENT);
1417    REGISTER_LONG_CONSTANT("HTTP_PROCESSING",     HTTP_PROCESSING,   CONST_CS | CONST_PERSISTENT);
1418    REGISTER_LONG_CONSTANT("HTTP_OK",     HTTP_OK,   CONST_CS | CONST_PERSISTENT);
1419    REGISTER_LONG_CONSTANT("HTTP_CREATED",     HTTP_CREATED,   CONST_CS | CONST_PERSISTENT);
1420    REGISTER_LONG_CONSTANT("HTTP_ACCEPTED",     HTTP_ACCEPTED,   CONST_CS | CONST_PERSISTENT);
1421    REGISTER_LONG_CONSTANT("HTTP_NON_AUTHORITATIVE",     HTTP_NON_AUTHORITATIVE,   CONST_CS | CONST_PERSISTENT);
1422    REGISTER_LONG_CONSTANT("HTTP_NO_CONTENT",     HTTP_NO_CONTENT,   CONST_CS | CONST_PERSISTENT);
1423    REGISTER_LONG_CONSTANT("HTTP_RESET_CONTENT",     HTTP_RESET_CONTENT,   CONST_CS | CONST_PERSISTENT);
1424    REGISTER_LONG_CONSTANT("HTTP_PARTIAL_CONTENT",     HTTP_PARTIAL_CONTENT,   CONST_CS | CONST_PERSISTENT);
1425    REGISTER_LONG_CONSTANT("HTTP_MULTI_STATUS",     HTTP_MULTI_STATUS,   CONST_CS | CONST_PERSISTENT);
1426    REGISTER_LONG_CONSTANT("HTTP_MULTIPLE_CHOICES",     HTTP_MULTIPLE_CHOICES,   CONST_CS | CONST_PERSISTENT);
1427    REGISTER_LONG_CONSTANT("HTTP_MOVED_PERMANENTLY",     HTTP_MOVED_PERMANENTLY,   CONST_CS | CONST_PERSISTENT);
1428    REGISTER_LONG_CONSTANT("HTTP_MOVED_TEMPORARILY",     HTTP_MOVED_TEMPORARILY,   CONST_CS | CONST_PERSISTENT);
1429    REGISTER_LONG_CONSTANT("HTTP_SEE_OTHER",     HTTP_SEE_OTHER,   CONST_CS | CONST_PERSISTENT);
1430    REGISTER_LONG_CONSTANT("HTTP_NOT_MODIFIED",     HTTP_NOT_MODIFIED,   CONST_CS | CONST_PERSISTENT);
1431    REGISTER_LONG_CONSTANT("HTTP_USE_PROXY",     HTTP_USE_PROXY,   CONST_CS | CONST_PERSISTENT);
1432    REGISTER_LONG_CONSTANT("HTTP_TEMPORARY_REDIRECT",     HTTP_TEMPORARY_REDIRECT,   CONST_CS | CONST_PERSISTENT);
1433    REGISTER_LONG_CONSTANT("HTTP_BAD_REQUEST",     HTTP_BAD_REQUEST,   CONST_CS | CONST_PERSISTENT);
1434    REGISTER_LONG_CONSTANT("HTTP_UNAUTHORIZED",     HTTP_UNAUTHORIZED,   CONST_CS | CONST_PERSISTENT);
1435    REGISTER_LONG_CONSTANT("HTTP_PAYMENT_REQUIRED",     HTTP_PAYMENT_REQUIRED,   CONST_CS | CONST_PERSISTENT);
1436    REGISTER_LONG_CONSTANT("HTTP_FORBIDDEN",     HTTP_FORBIDDEN,   CONST_CS | CONST_PERSISTENT);
1437    REGISTER_LONG_CONSTANT("HTTP_NOT_FOUND",     HTTP_NOT_FOUND,   CONST_CS | CONST_PERSISTENT);
1438    REGISTER_LONG_CONSTANT("HTTP_METHOD_NOT_ALLOWED",     HTTP_METHOD_NOT_ALLOWED,   CONST_CS | CONST_PERSISTENT);
1439    REGISTER_LONG_CONSTANT("HTTP_NOT_ACCEPTABLE",     HTTP_NOT_ACCEPTABLE,   CONST_CS | CONST_PERSISTENT);
1440    REGISTER_LONG_CONSTANT("HTTP_PROXY_AUTHENTICATION_REQUIRED",     HTTP_PROXY_AUTHENTICATION_REQUIRED,   CONST_CS | CONST_PERSISTENT);
1441    REGISTER_LONG_CONSTANT("HTTP_REQUEST_TIME_OUT",     HTTP_REQUEST_TIME_OUT,   CONST_CS | CONST_PERSISTENT);
1442    REGISTER_LONG_CONSTANT("HTTP_CONFLICT",     HTTP_CONFLICT,   CONST_CS | CONST_PERSISTENT);
1443    REGISTER_LONG_CONSTANT("HTTP_GONE",     HTTP_GONE,   CONST_CS | CONST_PERSISTENT);REGISTER_LONG_CONSTANT("HTTP_LENGTH_REQUIRED",     HTTP_LENGTH_REQUIRED,   CONST_CS | CONST_PERSISTENT);
1444    REGISTER_LONG_CONSTANT("HTTP_PRECONDITION_FAILED",     HTTP_PRECONDITION_FAILED,   CONST_CS | CONST_PERSISTENT);
1445    REGISTER_LONG_CONSTANT("HTTP_REQUEST_ENTITY_TOO_LARGE",     HTTP_REQUEST_ENTITY_TOO_LARGE,   CONST_CS | CONST_PERSISTENT);
1446    REGISTER_LONG_CONSTANT("HTTP_REQUEST_URI_TOO_LARGE",     HTTP_REQUEST_URI_TOO_LARGE,   CONST_CS | CONST_PERSISTENT);
1447    REGISTER_LONG_CONSTANT("HTTP_UNSUPPORTED_MEDIA_TYPE",     HTTP_UNSUPPORTED_MEDIA_TYPE,   CONST_CS | CONST_PERSISTENT);
1448    REGISTER_LONG_CONSTANT("HTTP_RANGE_NOT_SATISFIABLE",     HTTP_RANGE_NOT_SATISFIABLE,   CONST_CS | CONST_PERSISTENT);
1449    REGISTER_LONG_CONSTANT("HTTP_EXPECTATION_FAILED",     HTTP_EXPECTATION_FAILED,   CONST_CS | CONST_PERSISTENT);
1450    REGISTER_LONG_CONSTANT("HTTP_UNPROCESSABLE_ENTITY",     HTTP_UNPROCESSABLE_ENTITY,   CONST_CS | CONST_PERSISTENT);
1451    REGISTER_LONG_CONSTANT("HTTP_LOCKED",     HTTP_LOCKED,   CONST_CS | CONST_PERSISTENT);
1452    REGISTER_LONG_CONSTANT("HTTP_FAILED_DEPENDENCY",     HTTP_FAILED_DEPENDENCY,   CONST_CS | CONST_PERSISTENT);
1453    REGISTER_LONG_CONSTANT("HTTP_INTERNAL_SERVER_ERROR",     HTTP_INTERNAL_SERVER_ERROR,   CONST_CS | CONST_PERSISTENT);
1454    REGISTER_LONG_CONSTANT("HTTP_NOT_IMPLEMENTED",     HTTP_NOT_IMPLEMENTED,   CONST_CS | CONST_PERSISTENT);
1455    REGISTER_LONG_CONSTANT("HTTP_BAD_GATEWAY",     HTTP_BAD_GATEWAY,   CONST_CS | CONST_PERSISTENT);
1456    REGISTER_LONG_CONSTANT("HTTP_SERVICE_UNAVAILABLE",     HTTP_SERVICE_UNAVAILABLE,   CONST_CS | CONST_PERSISTENT);
1457    REGISTER_LONG_CONSTANT("HTTP_GATEWAY_TIME_OUT",     HTTP_GATEWAY_TIME_OUT,   CONST_CS | CONST_PERSISTENT);
1458    REGISTER_LONG_CONSTANT("HTTP_VERSION_NOT_SUPPORTED",     HTTP_VERSION_NOT_SUPPORTED,   CONST_CS | CONST_PERSISTENT);
1459    REGISTER_LONG_CONSTANT("HTTP_VARIANT_ALSO_VARIES",     HTTP_VARIANT_ALSO_VARIES,   CONST_CS | CONST_PERSISTENT);
1460    REGISTER_LONG_CONSTANT("HTTP_INSUFFICIENT_STORAGE",     HTTP_INSUFFICIENT_STORAGE,   CONST_CS | CONST_PERSISTENT);
1461    REGISTER_LONG_CONSTANT("HTTP_NOT_EXTENDED",     HTTP_NOT_EXTENDED,   CONST_CS | CONST_PERSISTENT);
1462    REGISTER_LONG_CONSTANT("APLOG_EMERG",       APLOG_EMERG,        CONST_CS | CONST_PERSISTENT);
1463    REGISTER_LONG_CONSTANT("APLOG_ALERT",       APLOG_ALERT,        CONST_CS | CONST_PERSISTENT);
1464    REGISTER_LONG_CONSTANT("APLOG_CRIT",        APLOG_CRIT,         CONST_CS | CONST_PERSISTENT);
1465    REGISTER_LONG_CONSTANT("APLOG_ERR",         APLOG_ERR,          CONST_CS | CONST_PERSISTENT);
1466    REGISTER_LONG_CONSTANT("APLOG_WARNING",     APLOG_WARNING,      CONST_CS | CONST_PERSISTENT);
1467    REGISTER_LONG_CONSTANT("APLOG_NOTICE",      APLOG_NOTICE,       CONST_CS | CONST_PERSISTENT);
1468    REGISTER_LONG_CONSTANT("APLOG_INFO",        APLOG_INFO,         CONST_CS | CONST_PERSISTENT);
1469    REGISTER_LONG_CONSTANT("APLOG_DEBUG",       APLOG_DEBUG,        CONST_CS | CONST_PERSISTENT);
1470    REGISTER_LONG_CONSTANT("M_GET",             M_GET,              CONST_CS | CONST_PERSISTENT);
1471    REGISTER_LONG_CONSTANT("M_PUT",             M_PUT,              CONST_CS | CONST_PERSISTENT);
1472    REGISTER_LONG_CONSTANT("M_POST",            M_POST,             CONST_CS | CONST_PERSISTENT);
1473    REGISTER_LONG_CONSTANT("M_DELETE",          M_DELETE,           CONST_CS | CONST_PERSISTENT);
1474    REGISTER_LONG_CONSTANT("M_CONNECT",         M_CONNECT,          CONST_CS | CONST_PERSISTENT);
1475    REGISTER_LONG_CONSTANT("M_OPTIONS",         M_OPTIONS,          CONST_CS | CONST_PERSISTENT);
1476    REGISTER_LONG_CONSTANT("M_TRACE",           M_TRACE,            CONST_CS | CONST_PERSISTENT);
1477    REGISTER_LONG_CONSTANT("M_PATCH",           M_PATCH,            CONST_CS | CONST_PERSISTENT);
1478    REGISTER_LONG_CONSTANT("M_PROPFIND",        M_PROPFIND,         CONST_CS | CONST_PERSISTENT);
1479    REGISTER_LONG_CONSTANT("M_PROPPATCH",       M_PROPPATCH,        CONST_CS | CONST_PERSISTENT);
1480    REGISTER_LONG_CONSTANT("M_MKCOL",           M_MKCOL,            CONST_CS | CONST_PERSISTENT);
1481    REGISTER_LONG_CONSTANT("M_COPY",            M_COPY,             CONST_CS | CONST_PERSISTENT);
1482    REGISTER_LONG_CONSTANT("M_MOVE",            M_MOVE,             CONST_CS | CONST_PERSISTENT);
1483    REGISTER_LONG_CONSTANT("M_LOCK",            M_LOCK,             CONST_CS | CONST_PERSISTENT);
1484    REGISTER_LONG_CONSTANT("M_UNLOCK",          M_UNLOCK,           CONST_CS | CONST_PERSISTENT);
1485    REGISTER_LONG_CONSTANT("M_INVALID",         M_INVALID,          CONST_CS | CONST_PERSISTENT);
1486
1487    /* Possible values for request_rec.read_body (set by handling module):
1488     *    REQUEST_NO_BODY          Send 413 error if message has any body
1489     *    REQUEST_CHUNKED_ERROR    Send 411 error if body without Content-Length
1490     *    REQUEST_CHUNKED_DECHUNK  If chunked, remove the chunks for me.
1491     *    REQUEST_CHUNKED_PASS     Pass the chunks to me without removal.
1492     */
1493    REGISTER_LONG_CONSTANT("REQUEST_NO_BODY",           REQUEST_NO_BODY,            CONST_CS | CONST_PERSISTENT);
1494    REGISTER_LONG_CONSTANT("REQUEST_CHUNKED_ERROR",     REQUEST_CHUNKED_ERROR,      CONST_CS | CONST_PERSISTENT);
1495    REGISTER_LONG_CONSTANT("REQUEST_CHUNKED_DECHUNK",   REQUEST_CHUNKED_DECHUNK,    CONST_CS | CONST_PERSISTENT);
1496    REGISTER_LONG_CONSTANT("REQUEST_CHUNKED_PASS",      REQUEST_CHUNKED_PASS,       CONST_CS | CONST_PERSISTENT);
1497
1498    /* resolve types for remote_host() */
1499    REGISTER_LONG_CONSTANT("REMOTE_HOST",           REMOTE_HOST,            CONST_CS | CONST_PERSISTENT);
1500    REGISTER_LONG_CONSTANT("REMOTE_NAME",           REMOTE_NAME,            CONST_CS | CONST_PERSISTENT);
1501    REGISTER_LONG_CONSTANT("REMOTE_NOLOOKUP",       REMOTE_NOLOOKUP,        CONST_CS | CONST_PERSISTENT);
1502    REGISTER_LONG_CONSTANT("REMOTE_DOUBLE_REV",     REMOTE_DOUBLE_REV,      CONST_CS | CONST_PERSISTENT);
1503
1504    return SUCCESS;
1505}
1506
1507
1508static PHP_MSHUTDOWN_FUNCTION(apache)
1509{
1510    UNREGISTER_INI_ENTRIES();
1511    return SUCCESS;
1512}
1513
1514zend_module_entry apache_module_entry = {
1515    STANDARD_MODULE_HEADER,
1516    "apache",
1517    apache_functions,
1518    PHP_MINIT(apache),
1519    PHP_MSHUTDOWN(apache),
1520    NULL,
1521    NULL,
1522    PHP_MINFO(apache),
1523    NO_VERSION_YET,
1524    STANDARD_MODULE_PROPERTIES
1525};
1526
1527/* {{{ proto bool apache_child_terminate(void)
1528   Terminate apache process after this request */
1529PHP_FUNCTION(apache_child_terminate)
1530{
1531#ifndef MULTITHREAD
1532    if (AP(terminate_child)) {
1533        ap_child_terminate( ((request_rec *)SG(server_context)) );
1534        RETURN_TRUE;
1535    } else { /* tell them to get lost! */
1536        php_error(E_WARNING, "apache.child_terminate is disabled");
1537        RETURN_FALSE;
1538    }
1539#else
1540        php_error(E_WARNING, "apache_child_terminate() is not supported in this build");
1541        RETURN_FALSE;
1542#endif
1543}
1544/* }}} */
1545
1546/* {{{ proto string apache_note(string note_name [, string note_value])
1547   Get and set Apache request notes */
1548PHP_FUNCTION(apache_note)
1549{
1550    char *arg_name, *arg_val = NULL;
1551    int arg_name_len, arg_val_len;
1552    char *note_val;
1553
1554    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &arg_name, &arg_name_len, &arg_val, &arg_val_len) == FAILURE) {
1555        return;
1556    }
1557
1558    note_val = (char *) table_get(((request_rec *)SG(server_context))->notes, arg_name);
1559
1560    if (arg_val) {
1561        table_set(((request_rec *)SG(server_context))->notes, arg_name, arg_val);
1562    }
1563
1564    if (!note_val) {
1565        RETURN_FALSE;
1566    }
1567
1568    RETURN_STRING(note_val, 1);
1569}
1570/* }}} */
1571
1572/* {{{ PHP_MINFO_FUNCTION
1573 */
1574PHP_MINFO_FUNCTION(apache)
1575{
1576    module *modp = NULL;
1577    char output_buf[128];
1578#if !defined(WIN32) && !defined(WINNT)
1579    char name[64];
1580    char modulenames[1024];
1581    char *p;
1582#endif
1583    server_rec *serv;
1584    extern char server_root[MAX_STRING_LEN];
1585    extern uid_t user_id;
1586    extern char *user_name;
1587    extern gid_t group_id;
1588    extern int max_requests_per_child;
1589
1590    serv = ((request_rec *) SG(server_context))->server;
1591
1592
1593    php_info_print_table_start();
1594
1595#ifdef PHP_WIN32
1596    php_info_print_table_row(1, "Apache for Windows 95/NT");
1597    php_info_print_table_end();
1598    php_info_print_table_start();
1599#elif defined(NETWARE)
1600    php_info_print_table_row(1, "Apache for NetWare");
1601    php_info_print_table_end();
1602    php_info_print_table_start();
1603#else
1604    php_info_print_table_row(2, "APACHE_INCLUDE", PHP_APACHE_INCLUDE);
1605    php_info_print_table_row(2, "APACHE_TARGET", PHP_APACHE_TARGET);
1606#endif
1607
1608    php_info_print_table_row(2, "Apache Version", SERVER_VERSION);
1609
1610#ifdef APACHE_RELEASE
1611    snprintf(output_buf, sizeof(output_buf), "%d", APACHE_RELEASE);
1612    php_info_print_table_row(2, "Apache Release", output_buf);
1613#endif
1614    snprintf(output_buf, sizeof(output_buf), "%d", MODULE_MAGIC_NUMBER);
1615    php_info_print_table_row(2, "Apache API Version", output_buf);
1616    snprintf(output_buf, sizeof(output_buf), "%s:%u", serv->server_hostname, serv->port);
1617    php_info_print_table_row(2, "Hostname:Port", output_buf);
1618#if !defined(WIN32) && !defined(WINNT)
1619    snprintf(output_buf, sizeof(output_buf), "%s(%d)/%d", user_name, (int)user_id, (int)group_id);
1620    php_info_print_table_row(2, "User/Group", output_buf);
1621    snprintf(output_buf, sizeof(output_buf), "Per Child: %d - Keep Alive: %s - Max Per Connection: %d", max_requests_per_child, serv->keep_alive ? "on":"off", serv->keep_alive_max);
1622    php_info_print_table_row(2, "Max Requests", output_buf);
1623#endif
1624    snprintf(output_buf, sizeof(output_buf), "Connection: %d - Keep-Alive: %d", serv->timeout, serv->keep_alive_timeout);
1625    php_info_print_table_row(2, "Timeouts", output_buf);
1626#if !defined(WIN32) && !defined(WINNT)
1627/*
1628    This block seems to be working on NetWare; But it seems to be showing
1629    all modules instead of just the loaded ones
1630*/
1631    php_info_print_table_row(2, "Server Root", server_root);
1632
1633    strcpy(modulenames, "");
1634    for(modp = top_module; modp; modp = modp->next) {
1635        strlcpy(name, modp->name, sizeof(name));
1636        if ((p = strrchr(name, '.'))) {
1637            *p='\0'; /* Cut off ugly .c extensions on module names */
1638        }
1639        strlcat(modulenames, name, sizeof(modulenames));
1640        if (modp->next) {
1641            strlcat(modulenames, ", ", sizeof(modulenames));
1642        }
1643    }
1644    php_info_print_table_row(2, "Loaded Modules", modulenames);
1645#endif
1646
1647    php_info_print_table_end();
1648
1649    DISPLAY_INI_ENTRIES();
1650
1651    {
1652        register int i;
1653        array_header *arr;
1654        table_entry *elts;
1655        request_rec *r;
1656
1657        r = ((request_rec *) SG(server_context));
1658        arr = table_elts(r->subprocess_env);
1659        elts = (table_entry *)arr->elts;
1660
1661        SECTION("Apache Environment");
1662        php_info_print_table_start();
1663        php_info_print_table_header(2, "Variable", "Value");
1664        for (i=0; i < arr->nelts; i++) {
1665            php_info_print_table_row(2, elts[i].key, elts[i].val);
1666        }
1667        php_info_print_table_end();
1668    }
1669
1670    {
1671        array_header *env_arr;
1672        table_entry *env;
1673        int i;
1674        request_rec *r;
1675
1676        r = ((request_rec *) SG(server_context));
1677        SECTION("HTTP Headers Information");
1678        php_info_print_table_start();
1679        php_info_print_table_colspan_header(2, "HTTP Request Headers");
1680        php_info_print_table_row(2, "HTTP Request", r->the_request);
1681        env_arr = table_elts(r->headers_in);
1682        env = (table_entry *)env_arr->elts;
1683        for (i = 0; i < env_arr->nelts; ++i) {
1684            if (env[i].key) {
1685                php_info_print_table_row(2, env[i].key, env[i].val);
1686            }
1687        }
1688        php_info_print_table_colspan_header(2, "HTTP Response Headers");
1689        env_arr = table_elts(r->headers_out);
1690        env = (table_entry *)env_arr->elts;
1691        for(i = 0; i < env_arr->nelts; ++i) {
1692            if (env[i].key) {
1693                php_info_print_table_row(2, env[i].key, env[i].val);
1694            }
1695        }
1696        php_info_print_table_end();
1697    }
1698}
1699/* }}} */
1700
1701/* {{{ proto bool virtual(string filename)
1702   Perform an Apache sub-request */
1703/* This function is equivalent to <!--#include virtual...-->
1704 * in mod_include. It does an Apache sub-request. It is useful
1705 * for including CGI scripts or .shtml files, or anything else
1706 * that you'd parse through Apache (for .phtml files, you'd probably
1707 * want to use <?Include>. This only works when PHP is compiled
1708 * as an Apache module, since it uses the Apache API for doing
1709 * sub requests.
1710 */
1711PHP_FUNCTION(virtual)
1712{
1713    char *filename;
1714    int filename_len;
1715    request_rec *rr = NULL;
1716
1717    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
1718        return;
1719    }
1720
1721    if (!(rr = sub_req_lookup_uri (filename, ((request_rec *) SG(server_context))))) {
1722        php_error(E_WARNING, "Unable to include '%s' - URI lookup failed", filename);
1723        if (rr)
1724            destroy_sub_req (rr);
1725        RETURN_FALSE;
1726    }
1727
1728    if (rr->status != 200) {
1729        php_error(E_WARNING, "Unable to include '%s' - error finding URI", filename);
1730        if (rr)
1731            destroy_sub_req (rr);
1732        RETURN_FALSE;
1733    }
1734
1735    php_output_end_all(TSRMLS_C);
1736    php_header(TSRMLS_C);
1737
1738    if (run_sub_req(rr)) {
1739        php_error(E_WARNING, "Unable to include '%s' - request execution failed", filename);
1740        if (rr)
1741            destroy_sub_req (rr);
1742        RETURN_FALSE;
1743    }
1744
1745    if (rr)
1746        destroy_sub_req (rr);
1747    RETURN_TRUE;
1748}
1749/* }}} */
1750
1751
1752/* {{{ apache_table_to_zval(table *, zval *return_value)
1753   Fetch all HTTP request headers */
1754static void apache_table_to_zval(table *t, zval *return_value)
1755{
1756    array_header *env_arr;
1757    table_entry *tenv;
1758    int i;
1759
1760    array_init(return_value);
1761    env_arr = table_elts(t);
1762    tenv = (table_entry *)env_arr->elts;
1763    for (i = 0; i < env_arr->nelts; ++i) {
1764        if (!tenv[i].key) {
1765            continue;
1766        }
1767        if (add_assoc_string(return_value, tenv[i].key, (tenv[i].val==NULL) ? "" : tenv[i].val)==FAILURE) {
1768            RETURN_FALSE;
1769        }
1770    }
1771
1772}
1773/* }}} */
1774
1775
1776/* {{{ proto array getallheaders(void)
1777*/
1778/*  Alias for apache_request_headers() */
1779/* }}} */
1780
1781/* {{{ proto array apache_request_headers(void)
1782   Fetch all HTTP request headers */
1783PHP_FUNCTION(apache_request_headers)
1784{
1785    if (zend_parse_parameters_none() == FAILURE) {
1786        return;
1787    }
1788
1789    apache_table_to_zval(((request_rec *)SG(server_context))->headers_in, return_value);
1790}
1791/* }}} */
1792
1793/* {{{ proto array apache_response_headers(void)
1794   Fetch all HTTP response headers */
1795PHP_FUNCTION(apache_response_headers)
1796{
1797    if (zend_parse_parameters_none() == FAILURE) {
1798        return;
1799    }
1800
1801    apache_table_to_zval(((request_rec *) SG(server_context))->headers_out, return_value);
1802}
1803/* }}} */
1804
1805/* {{{ proto bool apache_setenv(string variable, string value [, bool walk_to_top])
1806   Set an Apache subprocess_env variable */
1807PHP_FUNCTION(apache_setenv)
1808{
1809    int var_len, val_len;
1810    zend_bool top=0;
1811    char *var = NULL, *val = NULL;
1812    request_rec *r = (request_rec *) SG(server_context);
1813
1814    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &var, &var_len, &val, &val_len, &top) == FAILURE) {
1815        RETURN_FALSE;
1816    }
1817
1818    while(top) {
1819        if (r->prev) {
1820            r = r->prev;
1821        }
1822        else break;
1823    }
1824
1825    ap_table_setn(r->subprocess_env, ap_pstrndup(r->pool, var, var_len), ap_pstrndup(r->pool, val, val_len));
1826    RETURN_TRUE;
1827}
1828/* }}} */
1829
1830/* {{{ proto object apache_lookup_uri(string URI)
1831   Perform a partial request of the given URI to obtain information about it */
1832PHP_FUNCTION(apache_lookup_uri)
1833{
1834    char *filename;
1835    int filename_len;
1836    request_rec *rr=NULL;
1837
1838    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
1839        return;
1840    }
1841
1842    if(!(rr = sub_req_lookup_uri(filename, ((request_rec *) SG(server_context))))) {
1843        php_error(E_WARNING, "URI lookup failed", filename);
1844        RETURN_FALSE;
1845    }
1846
1847    object_init(return_value);
1848    add_property_long(return_value,"status", rr->status);
1849
1850    if (rr->the_request) {
1851        add_property_string(return_value,"the_request", rr->the_request);
1852    }
1853    if (rr->status_line) {
1854        add_property_string(return_value,"status_line", (char *)rr->status_line);
1855    }
1856    if (rr->method) {
1857        add_property_string(return_value,"method", (char *)rr->method);
1858    }
1859    if (rr->content_type) {
1860        add_property_string(return_value,"content_type", (char *)rr->content_type);
1861    }
1862    if (rr->handler) {
1863        add_property_string(return_value,"handler", (char *)rr->handler);
1864    }
1865    if (rr->uri) {
1866        add_property_string(return_value,"uri", rr->uri);
1867    }
1868    if (rr->filename) {
1869        add_property_string(return_value,"filename", rr->filename);
1870    }
1871    if (rr->path_info) {
1872        add_property_string(return_value,"path_info", rr->path_info);
1873    }
1874    if (rr->args) {
1875        add_property_string(return_value,"args", rr->args);
1876    }
1877    if (rr->boundary) {
1878        add_property_string(return_value,"boundary", rr->boundary);
1879    }
1880    add_property_long(return_value,"no_cache", rr->no_cache);
1881    add_property_long(return_value,"no_local_copy", rr->no_local_copy);
1882    add_property_long(return_value,"allowed", rr->allowed);
1883    add_property_long(return_value,"sent_bodyct", rr->sent_bodyct);
1884    add_property_long(return_value,"bytes_sent", rr->bytes_sent);
1885    add_property_long(return_value,"byterange", rr->byterange);
1886    add_property_long(return_value,"clength", rr->clength);
1887
1888#if MODULE_MAGIC_NUMBER >= 19980324
1889    if (rr->unparsed_uri) {
1890        add_property_string(return_value,"unparsed_uri", rr->unparsed_uri);
1891    }
1892    if(rr->mtime) {
1893        add_property_long(return_value,"mtime", rr->mtime);
1894    }
1895#endif
1896    if(rr->request_time) {
1897        add_property_long(return_value,"request_time", rr->request_time);
1898    }
1899
1900    destroy_sub_req(rr);
1901}
1902/* }}} */
1903
1904
1905#if 0
1906/*
1907This function is most likely a bad idea.  Just playing with it for now.
1908*/
1909
1910PHP_FUNCTION(apache_exec_uri)
1911{
1912    zval **filename;
1913    request_rec *rr=NULL;
1914
1915    if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &filename) == FAILURE) {
1916        WRONG_PARAM_COUNT;
1917    }
1918    convert_to_string_ex(filename);
1919
1920    if(!(rr = ap_sub_req_lookup_uri((*filename)->value.str.val, ((request_rec *) SG(server_context))))) {
1921        php_error(E_WARNING, "URI lookup failed", (*filename)->value.str.val);
1922        RETURN_FALSE;
1923    }
1924    RETVAL_LONG(ap_run_sub_req(rr));
1925    ap_destroy_sub_req(rr);
1926}
1927#endif
1928
1929/* {{{ proto string apache_get_version(void)
1930   Fetch Apache version */
1931PHP_FUNCTION(apache_get_version)
1932{
1933    char *apv = (char *) ap_get_server_version();
1934
1935    if (apv && *apv) {
1936        RETURN_STRING(apv, 1);
1937    } else {
1938        RETURN_FALSE;
1939    }
1940}
1941/* }}} */
1942
1943/* {{{ proto array apache_get_modules(void)
1944   Get a list of loaded Apache modules */
1945PHP_FUNCTION(apache_get_modules)
1946{
1947    int n;
1948    char *p;
1949
1950    array_init(return_value);
1951
1952    for (n = 0; ap_loaded_modules[n]; ++n) {
1953        char *s = (char *) ap_loaded_modules[n]->name;
1954        if ((p = strchr(s, '.'))) {
1955            add_next_index_stringl(return_value, s, (p - s));
1956        } else {
1957            add_next_index_string(return_value, s);
1958        }
1959    }
1960}
1961/* }}} */
1962
1963/*
1964 * Local variables:
1965 * tab-width: 4
1966 * c-basic-offset: 4
1967 * End:
1968 * vim600: sw=4 ts=4 fdm=marker
1969 * vim<600: sw=4 ts=4
1970 */
1971