xref: /PHP-5.6/sapi/apache_hooks/php_apache.c (revision 49493a2d)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 5                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2016 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
32 int php_apache_info_id;
33 #else
34 php_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 
42 extern module *top_module;
43 extern module **ap_loaded_modules;
44 static int le_apachereq;
45 static zend_class_entry *apacherequest_class_entry;
46 
47 static void apache_table_to_zval(table *, zval *return_value);
48 
49 PHP_FUNCTION(virtual);
50 PHP_FUNCTION(apache_request_headers);
51 PHP_FUNCTION(apache_response_headers);
52 PHP_FUNCTION(apachelog);
53 PHP_FUNCTION(apache_note);
54 PHP_FUNCTION(apache_lookup_uri);
55 PHP_FUNCTION(apache_child_terminate);
56 PHP_FUNCTION(apache_setenv);
57 PHP_FUNCTION(apache_get_version);
58 PHP_FUNCTION(apache_get_modules);
59 
60 PHP_MINFO_FUNCTION(apache);
61 
62 ZEND_BEGIN_ARG_INFO_EX(arginfo_apachehooks_virtual, 0, 0, 1)
63 	ZEND_ARG_INFO(0, filename)
64 ZEND_END_ARG_INFO()
65 
66 ZEND_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)
70 ZEND_END_ARG_INFO()
71 
72 ZEND_BEGIN_ARG_INFO_EX(arginfo_apachehooks_lookup_uri, 0, 0, 1)
73 	ZEND_ARG_INFO(0, uri)
74 ZEND_END_ARG_INFO()
75 
76 ZEND_BEGIN_ARG_INFO(arginfo_apachehooks__void, 0)
77 ZEND_END_ARG_INFO()
78 
79 ZEND_BEGIN_ARG_INFO_EX(arginfo_apachehooks_note, 0, 0, 1)
80 	ZEND_ARG_INFO(0, note_name)
81 	ZEND_ARG_INFO(0, note_value)
82 ZEND_END_ARG_INFO()
83 
84 const 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  */
100 PHP_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)
PHP_INI_END()105 PHP_INI_END()
106 /* }}} */
107 
108 static 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 
php_apache_request_free(zend_rsrc_list_entry * rsrc TSRMLS_DC)122 static 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 
get_apache_request(zval * z TSRMLS_DC)129 static 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  */
php_apache_request_new(request_rec * r)161 zval *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  */
apache_request_read_string_slot(int offset,INTERNAL_FUNCTION_PARAMETERS)182 static 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  */
apache_request_string_slot(int offset,INTERNAL_FUNCTION_PARAMETERS)207 static 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  */
apache_request_read_int_slot(int offset,INTERNAL_FUNCTION_PARAMETERS)238 static 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  */
apache_request_int_slot(int offset,INTERNAL_FUNCTION_PARAMETERS)258 static 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  */
PHP_FUNCTION(apache_request_filename)295 PHP_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  */
PHP_FUNCTION(apache_request_uri)303 PHP_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  */
PHP_FUNCTION(apache_request_unparsed_uri)311 PHP_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  */
PHP_FUNCTION(apache_request_path_info)319 PHP_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  */
PHP_FUNCTION(apache_request_args)327 PHP_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  */
PHP_FUNCTION(apache_request_boundary)335 PHP_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  */
PHP_FUNCTION(apache_request_content_type)344 PHP_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  */
PHP_FUNCTION(apache_request_content_encoding)352 PHP_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  */
PHP_FUNCTION(apache_request_handler)360 PHP_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  */
PHP_FUNCTION(apache_request_the_request)368 PHP_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  */
PHP_FUNCTION(apache_request_protocol)376 PHP_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  */
PHP_FUNCTION(apache_request_hostname)384 PHP_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  */
PHP_FUNCTION(apache_request_status_line)392 PHP_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  */
PHP_FUNCTION(apache_request_method)400 PHP_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  */
PHP_FUNCTION(apache_request_proto_num)413 PHP_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  */
PHP_FUNCTION(apache_request_assbackwards)421 PHP_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  */
PHP_FUNCTION(apache_request_proxyreq)430 PHP_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  */
PHP_FUNCTION(apache_request_chunked)438 PHP_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  */
PHP_FUNCTION(apache_request_header_only)447 PHP_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  */
PHP_FUNCTION(apache_request_request_time)455 PHP_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  */
PHP_FUNCTION(apache_request_status)463 PHP_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  */
PHP_FUNCTION(apache_request_method_number)471 PHP_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  */
PHP_FUNCTION(apache_request_allowed)479 PHP_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  */
PHP_FUNCTION(apache_request_bytes_sent)487 PHP_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  */
PHP_FUNCTION(apache_request_mtime)495 PHP_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  */
PHP_FUNCTION(apache_request_content_length)503 PHP_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  */
PHP_FUNCTION(apache_request_remaining)526 PHP_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  */
PHP_FUNCTION(apache_request_no_cache)534 PHP_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  */
PHP_FUNCTION(apache_request_no_local_copy)542 PHP_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  */
PHP_FUNCTION(apache_request_read_body)550 PHP_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  */
PHP_FUNCTION(apache_request_headers_in)563 PHP_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 */
add_header_to_table(table * t,INTERNAL_FUNCTION_PARAMETERS)577 static 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  */
PHP_FUNCTION(apache_request_headers_out)656 PHP_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  */
PHP_FUNCTION(apache_request_err_headers_out)675 PHP_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  */
PHP_FUNCTION(apache_request_server_port)696 PHP_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  */
PHP_FUNCTION(apache_request_remote_host)713 PHP_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  */
PHP_FUNCTION(apache_request_update_mtime)742 PHP_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  */
PHP_FUNCTION(apache_request_set_etag)761 PHP_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  */
PHP_FUNCTION(apache_request_set_last_modified)779 PHP_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  */
PHP_FUNCTION(apache_request_meets_conditions)797 PHP_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  */
PHP_FUNCTION(apache_request_discard_request_body)814 PHP_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  */
PHP_FUNCTION(apache_request_satisfies)831 PHP_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  */
PHP_FUNCTION(apache_request_is_initial_req)849 PHP_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  */
PHP_FUNCTION(apache_request_some_auth_required)866 PHP_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  */
PHP_FUNCTION(apache_request_auth_type)883 PHP_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  */
PHP_FUNCTION(apache_request_auth_name)906 PHP_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  */
PHP_FUNCTION(apache_request_basic_auth_pw)929 PHP_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 
PHP_FUNCTION(apache_request_send_http_header)961 PHP_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 
PHP_FUNCTION(apache_request_basic_http_header)982 PHP_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 
PHP_FUNCTION(apache_request_send_http_trace)999 PHP_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 
PHP_FUNCTION(apache_request_send_http_options)1016 PHP_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 
PHP_FUNCTION(apache_request_send_error_response)1033 PHP_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 
PHP_FUNCTION(apache_request_set_content_length)1048 PHP_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 
PHP_FUNCTION(apache_request_set_keepalive)1064 PHP_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 
1080 PHP_FUNCTION(apache_request_send_fd)
1081 {
1082 }
1083 
1084 PHP_FUNCTION(apache_request_send_fd_length)
1085 {
1086 }
1087 */
1088 
1089 /* These are for overriding default output behaviour */
PHP_FUNCTION(apache_request_rputs)1090 PHP_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 
1112 PHP_FUNCTION(apache_request_setup_client_block)
1113 {
1114 }
1115 
1116 PHP_FUNCTION(apache_request_should_client_block)
1117 {
1118 }
1119 
1120 PHP_FUNCTION(apache_request_get_client_block)
1121 {
1122 }
1123 
1124 PHP_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  */
PHP_FUNCTION(apache_request_log_error)1133 PHP_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 */
PHP_FUNCTION(apache_request_sub_req_lookup_uri)1156 PHP_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 */
PHP_FUNCTION(apache_request_sub_req_lookup_file)1181 PHP_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 */
PHP_FUNCTION(apache_request_sub_req_method_uri)1207 PHP_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 */
PHP_FUNCTION(apache_request_run)1233 PHP_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 
PHP_FUNCTION(apache_request_internal_redirect)1253 PHP_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 
PHP_FUNCTION(apache_request_send_header_field)1269 PHP_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  */
1293 const 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 
PHP_MINIT_FUNCTION(apache)1392 static 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 
PHP_MSHUTDOWN_FUNCTION(apache)1510 static PHP_MSHUTDOWN_FUNCTION(apache)
1511 {
1512 	UNREGISTER_INI_ENTRIES();
1513 	return SUCCESS;
1514 }
1515 
1516 zend_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 */
PHP_FUNCTION(apache_child_terminate)1531 PHP_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 */
PHP_FUNCTION(apache_note)1550 PHP_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  */
PHP_MINFO_FUNCTION(apache)1576 PHP_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  */
PHP_FUNCTION(virtual)1713 PHP_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 */
apache_table_to_zval(table * t,zval * return_value)1756 static 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 */
PHP_FUNCTION(apache_request_headers)1785 PHP_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 */
PHP_FUNCTION(apache_response_headers)1797 PHP_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 */
PHP_FUNCTION(apache_setenv)1809 PHP_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 */
PHP_FUNCTION(apache_lookup_uri)1834 PHP_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 /*
1909 This function is most likely a bad idea.  Just playing with it for now.
1910 */
1911 
1912 PHP_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 */
PHP_FUNCTION(apache_get_version)1933 PHP_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 */
PHP_FUNCTION(apache_get_modules)1947 PHP_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