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