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 | Author: Sascha Schumann <sascha@schumann.cx> |
16 +----------------------------------------------------------------------+
17 */
18
19 /* $Id$ */
20
21
22 #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
23
24 #include "php.h"
25 #include "ext/standard/php_smart_str.h"
26 #include "ext/standard/info.h"
27 #include "SAPI.h"
28
29 #define CORE_PRIVATE
30 #include "apr_strings.h"
31 #include "apr_time.h"
32 #include "ap_config.h"
33 #include "util_filter.h"
34 #include "httpd.h"
35 #include "http_config.h"
36 #include "http_request.h"
37 #include "http_core.h"
38 #include "http_protocol.h"
39 #include "http_log.h"
40 #include "http_main.h"
41 #include "util_script.h"
42 #include "http_core.h"
43
44 #include "php_apache.h"
45
php_apache_lookup_uri(char * filename TSRMLS_DC)46 static request_rec *php_apache_lookup_uri(char *filename TSRMLS_DC)
47 {
48 php_struct *ctx;
49
50 if (!filename) {
51 return NULL;
52 }
53
54 ctx = SG(server_context);
55 return ap_sub_req_lookup_uri(filename, ctx->f->r, ctx->f->next);
56 }
57
58 /* {{{ proto bool virtual(string uri)
59 Perform an apache sub-request */
PHP_FUNCTION(virtual)60 PHP_FUNCTION(virtual)
61 {
62 char *filename;
63 int filename_len;
64 request_rec *rr;
65
66 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
67 return;
68 }
69
70 if (!(rr = php_apache_lookup_uri(filename TSRMLS_CC))) {
71 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - URI lookup failed", filename);
72 RETURN_FALSE;
73 }
74
75 if (rr->status == HTTP_OK) {
76 if (ap_run_sub_req(rr)) {
77 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - request execution failed", filename);
78 ap_destroy_sub_req(rr);
79 RETURN_FALSE;
80 }
81 ap_destroy_sub_req(rr);
82 RETURN_TRUE;
83 }
84
85 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - error finding URI", filename);
86 ap_destroy_sub_req(rr);
87 RETURN_FALSE;
88 }
89 /* }}} */
90
91 #define ADD_LONG(name) \
92 add_property_long(return_value, #name, rr->name)
93 #define ADD_TIME(name) \
94 add_property_long(return_value, #name, apr_time_sec(rr->name));
95 #define ADD_STRING(name) \
96 if (rr->name) add_property_string(return_value, #name, (char *) rr->name, 1)
97
PHP_FUNCTION(apache_lookup_uri)98 PHP_FUNCTION(apache_lookup_uri)
99 {
100 request_rec *rr;
101 char *filename;
102 int filename_len;
103
104 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
105 return;
106 }
107
108 if (!(rr = php_apache_lookup_uri(filename TSRMLS_CC))) {
109 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - URI lookup failed", filename);
110 RETURN_FALSE;
111 }
112
113 if (rr->status == HTTP_OK) {
114 object_init(return_value);
115
116 ADD_LONG(status);
117 ADD_STRING(the_request);
118 ADD_STRING(status_line);
119 ADD_STRING(method);
120 ADD_TIME(mtime);
121 ADD_LONG(clength);
122 #if MODULE_MAGIC_NUMBER < 20020506
123 ADD_STRING(boundary);
124 #endif
125 ADD_STRING(range);
126 ADD_LONG(chunked);
127 ADD_STRING(content_type);
128 ADD_STRING(handler);
129 ADD_LONG(no_cache);
130 ADD_LONG(no_local_copy);
131 ADD_STRING(unparsed_uri);
132 ADD_STRING(uri);
133 ADD_STRING(filename);
134 ADD_STRING(path_info);
135 ADD_STRING(args);
136 ADD_LONG(allowed);
137 ADD_LONG(sent_bodyct);
138 ADD_LONG(bytes_sent);
139 ADD_LONG(mtime);
140 ADD_TIME(request_time);
141
142 ap_destroy_sub_req(rr);
143 return;
144 }
145
146 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - error finding URI", filename);
147 ap_destroy_sub_req(rr);
148 RETURN_FALSE;
149 }
150
151 /* {{{ proto array getallheaders(void)
152 Fetch all HTTP request headers */
PHP_FUNCTION(apache_request_headers)153 PHP_FUNCTION(apache_request_headers)
154 {
155 php_struct *ctx;
156 const apr_array_header_t *arr;
157 char *key, *val;
158
159 array_init(return_value);
160
161 ctx = SG(server_context);
162 arr = apr_table_elts(ctx->f->r->headers_in);
163
164 APR_ARRAY_FOREACH_OPEN(arr, key, val)
165 if (!val) val = "";
166 add_assoc_string(return_value, key, val, 1);
167 APR_ARRAY_FOREACH_CLOSE()
168 }
169 /* }}} */
170
171 /* {{{ proto array apache_response_headers(void)
172 Fetch all HTTP response headers */
PHP_FUNCTION(apache_response_headers)173 PHP_FUNCTION(apache_response_headers)
174 {
175 php_struct *ctx;
176 const apr_array_header_t *arr;
177 char *key, *val;
178
179 array_init(return_value);
180
181 ctx = SG(server_context);
182 arr = apr_table_elts(ctx->f->r->headers_out);
183
184 APR_ARRAY_FOREACH_OPEN(arr, key, val)
185 if (!val) val = "";
186 add_assoc_string(return_value, key, val, 1);
187 APR_ARRAY_FOREACH_CLOSE()
188 }
189 /* }}} */
190
191 /* {{{ proto string apache_note(string note_name [, string note_value])
192 Get and set Apache request notes */
PHP_FUNCTION(apache_note)193 PHP_FUNCTION(apache_note)
194 {
195 php_struct *ctx;
196 char *note_name, *note_val = NULL;
197 int note_name_len, note_val_len;
198 char *old_note_val=NULL;
199
200 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", ¬e_name, ¬e_name_len, ¬e_val, ¬e_val_len) == FAILURE) {
201 return;
202 }
203
204 ctx = SG(server_context);
205
206 old_note_val = (char *) apr_table_get(ctx->r->notes, note_name);
207
208 if (note_val) {
209 apr_table_set(ctx->r->notes, note_name, note_val);
210 }
211
212 if (old_note_val) {
213 RETURN_STRING(old_note_val, 1);
214 }
215
216 RETURN_FALSE;
217 }
218 /* }}} */
219
220
221 /* {{{ proto bool apache_setenv(string variable, string value [, bool walk_to_top])
222 Set an Apache subprocess_env variable */
PHP_FUNCTION(apache_setenv)223 PHP_FUNCTION(apache_setenv)
224 {
225 php_struct *ctx;
226 char *variable=NULL, *string_val=NULL;
227 int variable_len, string_val_len;
228 zend_bool walk_to_top = 0;
229 int arg_count = ZEND_NUM_ARGS();
230
231 if (zend_parse_parameters(arg_count TSRMLS_CC, "ss|b", &variable, &variable_len, &string_val, &string_val_len, &walk_to_top) == FAILURE) {
232 return;
233 }
234
235 ctx = SG(server_context);
236
237 if (arg_count == 3 && walk_to_top) {
238 while(ctx->f->r->prev) {
239 ctx->f->r = ctx->f->r->prev;
240 }
241 }
242
243 apr_table_set(ctx->r->subprocess_env, variable, string_val);
244
245 RETURN_TRUE;
246 }
247 /* }}} */
248
249 /* {{{ proto bool apache_getenv(string variable [, bool walk_to_top])
250 Get an Apache subprocess_env variable */
PHP_FUNCTION(apache_getenv)251 PHP_FUNCTION(apache_getenv)
252 {
253 php_struct *ctx;
254 char *variable=NULL;
255 int variable_len;
256 zend_bool walk_to_top = 0;
257 int arg_count = ZEND_NUM_ARGS();
258 char *env_val=NULL;
259
260 if (zend_parse_parameters(arg_count TSRMLS_CC, "s|b", &variable, &variable_len, &walk_to_top) == FAILURE) {
261 return;
262 }
263
264 ctx = SG(server_context);
265
266 if (arg_count == 2 && walk_to_top) {
267 while(ctx->f->r->prev) {
268 ctx->f->r = ctx->f->r->prev;
269 }
270 }
271
272 env_val = (char*) apr_table_get(ctx->r->subprocess_env, variable);
273 if (env_val != NULL) {
274 RETURN_STRING(env_val, 1);
275 }
276
277 RETURN_FALSE;
278 }
279 /* }}} */
280
php_apache_get_version()281 static char *php_apache_get_version()
282 {
283 #if MODULE_MAGIC_NUMBER_MAJOR >= 20060905
284 return (char *) ap_get_server_banner();
285 #else
286 return (char *) ap_get_server_version();
287 #endif
288 }
289
290 /* {{{ proto string apache_get_version(void)
291 Fetch Apache version */
PHP_FUNCTION(apache_get_version)292 PHP_FUNCTION(apache_get_version)
293 {
294 char *apv = php_apache_get_version();
295
296 if (apv && *apv) {
297 RETURN_STRING(apv, 1);
298 } else {
299 RETURN_FALSE;
300 }
301 }
302 /* }}} */
303
304 /* {{{ proto array apache_get_modules(void)
305 Get a list of loaded Apache modules */
PHP_FUNCTION(apache_get_modules)306 PHP_FUNCTION(apache_get_modules)
307 {
308 int n;
309 char *p;
310
311 array_init(return_value);
312
313 for (n = 0; ap_loaded_modules[n]; ++n) {
314 char *s = (char *) ap_loaded_modules[n]->name;
315 if ((p = strchr(s, '.'))) {
316 add_next_index_stringl(return_value, s, (p - s), 1);
317 } else {
318 add_next_index_string(return_value, s, 1);
319 }
320 }
321 }
322 /* }}} */
323
PHP_MINFO_FUNCTION(apache)324 PHP_MINFO_FUNCTION(apache)
325 {
326 char *apv = php_apache_get_version();
327 smart_str tmp1 = {0};
328 int n;
329 char *p;
330
331 for (n = 0; ap_loaded_modules[n]; ++n) {
332 char *s = (char *) ap_loaded_modules[n]->name;
333 if ((p = strchr(s, '.'))) {
334 smart_str_appendl(&tmp1, s, (p - s));
335 } else {
336 smart_str_appends(&tmp1, s);
337 }
338 smart_str_appendc(&tmp1, ' ');
339 }
340 if ((tmp1.len - 1) >= 0) {
341 tmp1.c[tmp1.len - 1] = '\0';
342 }
343
344 php_info_print_table_start();
345 if (apv && *apv) {
346 php_info_print_table_row(2, "Apache Version", apv);
347 }
348 php_info_print_table_row(2, "Loaded Modules", tmp1.c);
349 smart_str_free(&tmp1);
350 php_info_print_table_end();
351 }
352
353 /* {{{ arginfo */
354 ZEND_BEGIN_ARG_INFO_EX(arginfo_apache2filter_lookup_uri, 0, 0, 1)
355 ZEND_ARG_INFO(0, filename)
356 ZEND_END_ARG_INFO()
357
358 ZEND_BEGIN_ARG_INFO_EX(arginfo_apache2filter_virtual, 0, 0, 1)
359 ZEND_ARG_INFO(0, uri)
360 ZEND_END_ARG_INFO()
361
362 ZEND_BEGIN_ARG_INFO(arginfo_apache2filter_getallheaders, 0)
363 ZEND_END_ARG_INFO()
364
365 ZEND_BEGIN_ARG_INFO(arginfo_apache2filter_response_headers, 0)
366 ZEND_END_ARG_INFO()
367
368 ZEND_BEGIN_ARG_INFO_EX(arginfo_apache2filter_note, 0, 0, 1)
369 ZEND_ARG_INFO(0, note_name)
370 ZEND_ARG_INFO(0, note_value)
371 ZEND_END_ARG_INFO()
372
373 ZEND_BEGIN_ARG_INFO_EX(arginfo_apache2filter_setenv, 0, 0, 2)
374 ZEND_ARG_INFO(0, variable)
375 ZEND_ARG_INFO(0, value)
376 ZEND_ARG_INFO(0, walk_to_top)
377 ZEND_END_ARG_INFO()
378
379 ZEND_BEGIN_ARG_INFO_EX(arginfo_apache2filter_getenv, 0, 0, 1)
380 ZEND_ARG_INFO(0, variable)
381 ZEND_ARG_INFO(0, walk_to_top)
382 ZEND_END_ARG_INFO()
383
384 ZEND_BEGIN_ARG_INFO(arginfo_apache2filter_get_version, 0)
385 ZEND_END_ARG_INFO()
386
387 ZEND_BEGIN_ARG_INFO(arginfo_apache2filter_get_modules, 0)
388 ZEND_END_ARG_INFO()
389 /* }}} */
390
391 static const zend_function_entry apache_functions[] = {
392 PHP_FE(apache_lookup_uri, arginfo_apache2filter_lookup_uri)
393 PHP_FE(virtual, arginfo_apache2filter_virtual)
394 PHP_FE(apache_request_headers, arginfo_apache2filter_getallheaders)
395 PHP_FE(apache_response_headers, arginfo_apache2filter_response_headers)
396 PHP_FE(apache_setenv, arginfo_apache2filter_setenv)
397 PHP_FE(apache_getenv, arginfo_apache2filter_getenv)
398 PHP_FE(apache_note, arginfo_apache2filter_note)
399 PHP_FE(apache_get_version, arginfo_apache2filter_get_version)
400 PHP_FE(apache_get_modules, arginfo_apache2filter_get_modules)
401 PHP_FALIAS(getallheaders, apache_request_headers, arginfo_apache2filter_getallheaders)
402 {NULL, NULL, NULL}
403 };
404
405 zend_module_entry php_apache_module = {
406 STANDARD_MODULE_HEADER,
407 "apache2filter",
408 apache_functions,
409 NULL,
410 NULL,
411 NULL,
412 NULL,
413 PHP_MINFO(apache),
414 NULL,
415 STANDARD_MODULE_PROPERTIES
416 };
417
418 /*
419 * Local variables:
420 * tab-width: 4
421 * c-basic-offset: 4
422 * End:
423 * vim600: sw=4 ts=4 fdm=marker
424 * vim<600: sw=4 ts=4
425 */
426