1/* 2 +----------------------------------------------------------------------+ 3 | PHP Version 5 | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 1997-2013 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 46static 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 */ 60PHP_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, "s", &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 98PHP_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, "s", &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 */ 153PHP_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 */ 173PHP_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 */ 193PHP_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 */ 223PHP_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 */ 251PHP_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 281static 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 */ 292PHP_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 */ 306PHP_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 324PHP_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 */ 354ZEND_BEGIN_ARG_INFO_EX(arginfo_apache2filter_lookup_uri, 0, 0, 1) 355 ZEND_ARG_INFO(0, filename) 356ZEND_END_ARG_INFO() 357 358ZEND_BEGIN_ARG_INFO_EX(arginfo_apache2filter_virtual, 0, 0, 1) 359 ZEND_ARG_INFO(0, uri) 360ZEND_END_ARG_INFO() 361 362ZEND_BEGIN_ARG_INFO(arginfo_apache2filter_getallheaders, 0) 363ZEND_END_ARG_INFO() 364 365ZEND_BEGIN_ARG_INFO(arginfo_apache2filter_response_headers, 0) 366ZEND_END_ARG_INFO() 367 368ZEND_BEGIN_ARG_INFO_EX(arginfo_apache2filter_note, 0, 0, 1) 369 ZEND_ARG_INFO(0, note_name) 370 ZEND_ARG_INFO(0, note_value) 371ZEND_END_ARG_INFO() 372 373ZEND_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) 377ZEND_END_ARG_INFO() 378 379ZEND_BEGIN_ARG_INFO_EX(arginfo_apache2filter_getenv, 0, 0, 1) 380 ZEND_ARG_INFO(0, variable) 381 ZEND_ARG_INFO(0, walk_to_top) 382ZEND_END_ARG_INFO() 383 384ZEND_BEGIN_ARG_INFO(arginfo_apache2filter_get_version, 0) 385ZEND_END_ARG_INFO() 386 387ZEND_BEGIN_ARG_INFO(arginfo_apache2filter_get_modules, 0) 388ZEND_END_ARG_INFO() 389/* }}} */ 390 391static 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 405zend_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