Back to index

php5  5.3.10
php_functions.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Author: Sascha Schumann <sascha@schumann.cx>                         |
00016    +----------------------------------------------------------------------+
00017  */
00018 
00019 /* $Id: php_functions.c 321634 2012-01-01 13:15:04Z felipe $ */
00020 
00021 #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
00022 
00023 #include "php.h"
00024 #include "ext/standard/php_smart_str.h"
00025 #include "ext/standard/info.h"
00026 #include "ext/standard/head.h"
00027 #include "php_ini.h"
00028 #include "SAPI.h"
00029 
00030 #define CORE_PRIVATE
00031 #include "apr_strings.h"
00032 #include "apr_time.h"
00033 #include "ap_config.h"
00034 #include "util_filter.h"
00035 #include "httpd.h"
00036 #include "http_config.h"
00037 #include "http_request.h"
00038 #include "http_core.h"
00039 #include "http_protocol.h"
00040 #include "http_log.h"
00041 #include "http_main.h"
00042 #include "util_script.h"
00043 #include "http_core.h"
00044 #include "ap_mpm.h"
00045 #if !defined(WIN32) && !defined(WINNT) && !defined(NETWARE)
00046 #include "unixd.h"
00047 #endif
00048 
00049 #include "php_apache.h"
00050 
00051 #ifdef ZTS
00052 int php_apache2_info_id;
00053 #else
00054 php_apache2_info_struct php_apache2_info;
00055 #endif
00056 
00057 #define SECTION(name)  PUTS("<h2>" name "</h2>\n")
00058 
00059 static request_rec *php_apache_lookup_uri(char *filename TSRMLS_DC)
00060 {
00061        php_struct *ctx = SG(server_context);
00062        
00063        if (!filename || !ctx || !ctx->r) {
00064               return NULL;
00065        }
00066 
00067        return ap_sub_req_lookup_uri(filename, ctx->r, ctx->r->output_filters);
00068 }
00069 
00070 /* {{{ proto bool virtual(string uri)
00071  Perform an apache sub-request */
00072 PHP_FUNCTION(virtual)
00073 {
00074        char *filename;
00075        int filename_len;
00076        request_rec *rr;
00077 
00078        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
00079               return;
00080        }
00081 
00082        if (!(rr = php_apache_lookup_uri(filename TSRMLS_CC))) {
00083               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - URI lookup failed", filename);
00084               RETURN_FALSE;
00085        }
00086 
00087        if (rr->status != HTTP_OK) {
00088               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - error finding URI", filename);
00089               ap_destroy_sub_req(rr);
00090               RETURN_FALSE;
00091        }
00092 
00093        /* Flush everything. */
00094        php_end_ob_buffers(1 TSRMLS_CC);
00095        php_header(TSRMLS_C);
00096 
00097        /* Ensure that the ap_r* layer for the main request is flushed, to
00098         * work around http://issues.apache.org/bugzilla/show_bug.cgi?id=17629 */
00099        ap_rflush(rr->main);
00100 
00101        if (ap_run_sub_req(rr)) {
00102               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - request execution failed", filename);
00103               ap_destroy_sub_req(rr);
00104               RETURN_FALSE;
00105        }
00106        ap_destroy_sub_req(rr);
00107        RETURN_TRUE;
00108 }
00109 /* }}} */
00110 
00111 #define ADD_LONG(name) \
00112               add_property_long(return_value, #name, rr->name)
00113 #define ADD_TIME(name) \
00114               add_property_long(return_value, #name, apr_time_sec(rr->name));
00115 #define ADD_STRING(name) \
00116               if (rr->name) add_property_string(return_value, #name, (char *) rr->name, 1)
00117 
00118 PHP_FUNCTION(apache_lookup_uri)
00119 {
00120        request_rec *rr;
00121        char *filename;
00122        int filename_len;
00123 
00124        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
00125               return;
00126        }
00127 
00128        if (!(rr = php_apache_lookup_uri(filename TSRMLS_CC))) {
00129               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - URI lookup failed", filename);
00130               RETURN_FALSE;
00131        }
00132        
00133        if (rr->status == HTTP_OK) {
00134               object_init(return_value);
00135 
00136               ADD_LONG(status);
00137               ADD_STRING(the_request);
00138               ADD_STRING(status_line);
00139               ADD_STRING(method);
00140               ADD_TIME(mtime);
00141               ADD_LONG(clength);
00142 #if MODULE_MAGIC_NUMBER < 20020506
00143               ADD_STRING(boundary);
00144 #endif
00145               ADD_STRING(range);
00146               ADD_LONG(chunked);
00147               ADD_STRING(content_type);
00148               ADD_STRING(handler);
00149               ADD_LONG(no_cache);
00150               ADD_LONG(no_local_copy);
00151               ADD_STRING(unparsed_uri);
00152               ADD_STRING(uri);
00153               ADD_STRING(filename);
00154               ADD_STRING(path_info);
00155               ADD_STRING(args);
00156               ADD_LONG(allowed);
00157               ADD_LONG(sent_bodyct);
00158               ADD_LONG(bytes_sent);
00159               ADD_LONG(mtime);
00160               ADD_TIME(request_time);
00161 
00162               ap_destroy_sub_req(rr);
00163               return;
00164        }
00165        
00166        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to include '%s' - error finding URI", filename);
00167        ap_destroy_sub_req(rr);
00168        RETURN_FALSE;
00169 }
00170 
00171 /* {{{ proto array getallheaders(void)
00172    Fetch all HTTP request headers */
00173 PHP_FUNCTION(apache_request_headers)
00174 {
00175        php_struct *ctx;
00176        const apr_array_header_t *arr;
00177        char *key, *val;
00178 
00179        if (zend_parse_parameters_none() == FAILURE) {
00180               return;
00181        }
00182 
00183        array_init(return_value);
00184        
00185        ctx = SG(server_context);
00186        arr = apr_table_elts(ctx->r->headers_in);
00187 
00188        APR_ARRAY_FOREACH_OPEN(arr, key, val)
00189               if (!val) val = "";
00190               add_assoc_string(return_value, key, val, 1);
00191        APR_ARRAY_FOREACH_CLOSE()
00192 }
00193 /* }}} */
00194 
00195 /* {{{ proto array apache_response_headers(void)
00196    Fetch all HTTP response headers */
00197 PHP_FUNCTION(apache_response_headers)
00198 {
00199        php_struct *ctx;
00200        const apr_array_header_t *arr;
00201        char *key, *val;
00202 
00203        if (zend_parse_parameters_none() == FAILURE) {
00204               return;
00205        }
00206 
00207        array_init(return_value);
00208        
00209        ctx = SG(server_context);
00210        arr = apr_table_elts(ctx->r->headers_out);
00211 
00212        APR_ARRAY_FOREACH_OPEN(arr, key, val)
00213               if (!val) val = "";
00214               add_assoc_string(return_value, key, val, 1);
00215        APR_ARRAY_FOREACH_CLOSE()
00216 }
00217 /* }}} */
00218 
00219 /* {{{ proto string apache_note(string note_name [, string note_value])
00220    Get and set Apache request notes */
00221 PHP_FUNCTION(apache_note)
00222 {
00223        php_struct *ctx;
00224        char *note_name, *note_val = NULL;
00225        int note_name_len, note_val_len;
00226        char *old_note_val=NULL;
00227 
00228        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &note_name, &note_name_len, &note_val, &note_val_len) == FAILURE) {
00229               return;
00230        }
00231 
00232        ctx = SG(server_context);
00233 
00234        old_note_val = (char *) apr_table_get(ctx->r->notes, note_name);
00235 
00236        if (note_val) {
00237               apr_table_set(ctx->r->notes, note_name, note_val);
00238        }
00239 
00240        if (old_note_val) {
00241               RETURN_STRING(old_note_val, 1);
00242        }
00243 
00244        RETURN_FALSE;
00245 }
00246 /* }}} */
00247 
00248 
00249 /* {{{ proto bool apache_setenv(string variable, string value [, bool walk_to_top])
00250    Set an Apache subprocess_env variable */
00251 /*
00252  * XXX this doesn't look right. shouldn't it be the parent ?*/
00253 PHP_FUNCTION(apache_setenv)
00254 {
00255        php_struct *ctx;
00256        char *variable=NULL, *string_val=NULL;
00257        int variable_len, string_val_len;
00258        zend_bool walk_to_top = 0;
00259        int arg_count = ZEND_NUM_ARGS();
00260        request_rec *r;
00261 
00262        if (zend_parse_parameters(arg_count TSRMLS_CC, "ss|b", &variable, &variable_len, &string_val, &string_val_len, &walk_to_top) == FAILURE) {
00263               return;
00264        }
00265 
00266        ctx = SG(server_context);
00267 
00268        r = ctx->r;
00269        if (arg_count == 3) {
00270               if (walk_to_top) {
00271                      while(r->prev) {
00272                             r = r->prev;
00273                      }
00274               }
00275        }
00276 
00277        apr_table_set(r->subprocess_env, variable, string_val);
00278 
00279        RETURN_TRUE;
00280 }
00281 /* }}} */
00282 
00283 /* {{{ proto bool apache_getenv(string variable [, bool walk_to_top])
00284    Get an Apache subprocess_env variable */
00285 /*
00286  * XXX: shouldn't this be the parent not the 'prev'
00287  */
00288 PHP_FUNCTION(apache_getenv)
00289 {
00290        php_struct *ctx;
00291        char *variable=NULL;
00292        int variable_len;
00293        zend_bool walk_to_top = 0;
00294        int arg_count = ZEND_NUM_ARGS();
00295        char *env_val=NULL;
00296        request_rec *r;
00297 
00298        if (zend_parse_parameters(arg_count TSRMLS_CC, "s|b", &variable, &variable_len, &walk_to_top) == FAILURE) {
00299               return;
00300        }
00301 
00302        ctx = SG(server_context);
00303 
00304        r = ctx->r;
00305        if (arg_count == 2) {
00306               if (walk_to_top) {
00307                      while(r->prev) {
00308                             r = r->prev;
00309                      }
00310               }
00311        }
00312 
00313        env_val = (char*) apr_table_get(r->subprocess_env, variable);
00314 
00315        if (env_val != NULL) {
00316               RETURN_STRING(env_val, 1);
00317        }
00318 
00319        RETURN_FALSE;
00320 }
00321 /* }}} */
00322 
00323 static char *php_apache_get_version()
00324 {
00325 #if MODULE_MAGIC_NUMBER_MAJOR >= 20060905
00326        return (char *) ap_get_server_banner();
00327 #else
00328        return (char *) ap_get_server_version();
00329 #endif
00330 }
00331 
00332 /* {{{ proto string apache_get_version(void)
00333    Fetch Apache version */
00334 PHP_FUNCTION(apache_get_version)
00335 {
00336        char *apv = php_apache_get_version();
00337 
00338        if (apv && *apv) {
00339               RETURN_STRING(apv, 1);
00340        } else {
00341               RETURN_FALSE;
00342        }
00343 }
00344 /* }}} */
00345 
00346 /* {{{ proto array apache_get_modules(void)
00347    Get a list of loaded Apache modules */
00348 PHP_FUNCTION(apache_get_modules)
00349 {
00350        int n;
00351        char *p;
00352        
00353        array_init(return_value);
00354        
00355        for (n = 0; ap_loaded_modules[n]; ++n) {
00356               char *s = (char *) ap_loaded_modules[n]->name;
00357               if ((p = strchr(s, '.'))) {
00358                      add_next_index_stringl(return_value, s, (p - s), 1);
00359               } else {
00360                      add_next_index_string(return_value, s, 1);
00361               }
00362        }
00363 }
00364 /* }}} */
00365 
00366 PHP_MINFO_FUNCTION(apache)
00367 {
00368        char *apv = php_apache_get_version();
00369        smart_str tmp1 = {0};
00370        char tmp[1024];
00371        int n, max_requests;
00372        char *p;
00373        server_rec *serv = ((php_struct *) SG(server_context))->r->server;
00374 #if !defined(WIN32) && !defined(WINNT) && !defined(NETWARE)
00375 #if MODULE_MAGIC_NUMBER_MAJOR >= 20081201
00376        AP_DECLARE_DATA extern unixd_config_rec ap_unixd_config;
00377 #else
00378        AP_DECLARE_DATA extern unixd_config_rec unixd_config;
00379 #endif
00380 #endif
00381        
00382        for (n = 0; ap_loaded_modules[n]; ++n) {
00383               char *s = (char *) ap_loaded_modules[n]->name;
00384               if ((p = strchr(s, '.'))) {
00385                      smart_str_appendl(&tmp1, s, (p - s));
00386               } else {
00387                      smart_str_appends(&tmp1, s);
00388               }
00389               smart_str_appendc(&tmp1, ' ');
00390        }
00391        if ((tmp1.len - 1) >= 0) {
00392               tmp1.c[tmp1.len - 1] = '\0';
00393        }
00394             
00395        php_info_print_table_start();
00396        if (apv && *apv) {
00397               php_info_print_table_row(2, "Apache Version", apv);
00398        }
00399        snprintf(tmp, sizeof(tmp), "%d", MODULE_MAGIC_NUMBER);
00400        php_info_print_table_row(2, "Apache API Version", tmp);
00401        
00402        if (serv->server_admin && *(serv->server_admin)) {
00403               php_info_print_table_row(2, "Server Administrator", serv->server_admin);
00404        }
00405        
00406        snprintf(tmp, sizeof(tmp), "%s:%u", serv->server_hostname, serv->port);
00407        php_info_print_table_row(2, "Hostname:Port", tmp);
00408        
00409 #if !defined(WIN32) && !defined(WINNT) && !defined(NETWARE)
00410 #if MODULE_MAGIC_NUMBER_MAJOR >= 20081201
00411        snprintf(tmp, sizeof(tmp), "%s(%d)/%d", ap_unixd_config.user_name, ap_unixd_config.user_id, ap_unixd_config.group_id);
00412 #else
00413        snprintf(tmp, sizeof(tmp), "%s(%d)/%d", unixd_config.user_name, unixd_config.user_id, unixd_config.group_id);
00414 #endif
00415        php_info_print_table_row(2, "User/Group", tmp);
00416 #endif
00417 
00418        ap_mpm_query(AP_MPMQ_MAX_REQUESTS_DAEMON, &max_requests);
00419        snprintf(tmp, sizeof(tmp), "Per Child: %d - Keep Alive: %s - Max Per Connection: %d", max_requests, (serv->keep_alive ? "on":"off"), serv->keep_alive_max);
00420        php_info_print_table_row(2, "Max Requests", tmp);
00421 
00422        apr_snprintf(tmp, sizeof tmp,
00423                              "Connection: %" APR_TIME_T_FMT " - Keep-Alive: %" APR_TIME_T_FMT, 
00424                              apr_time_sec(serv->timeout), apr_time_sec(serv->keep_alive_timeout));
00425        php_info_print_table_row(2, "Timeouts", tmp);
00426        
00427        php_info_print_table_row(2, "Virtual Server", (serv->is_virtual ? "Yes" : "No"));
00428        php_info_print_table_row(2, "Server Root", ap_server_root);
00429        php_info_print_table_row(2, "Loaded Modules", tmp1.c);
00430 
00431        smart_str_free(&tmp1);
00432        php_info_print_table_end();
00433        
00434        DISPLAY_INI_ENTRIES();
00435 
00436        {
00437               const apr_array_header_t *arr = apr_table_elts(((php_struct *) SG(server_context))->r->subprocess_env);
00438               char *key, *val;
00439               
00440               SECTION("Apache Environment");
00441               php_info_print_table_start();      
00442               php_info_print_table_header(2, "Variable", "Value");
00443               APR_ARRAY_FOREACH_OPEN(arr, key, val)
00444                      if (!val) {
00445                             val = "";
00446                      }
00447                      php_info_print_table_row(2, key, val);
00448               APR_ARRAY_FOREACH_CLOSE()
00449                                                               
00450               php_info_print_table_end(); 
00451               
00452               SECTION("HTTP Headers Information");
00453               php_info_print_table_start();
00454               php_info_print_table_colspan_header(2, "HTTP Request Headers");
00455               php_info_print_table_row(2, "HTTP Request", ((php_struct *) SG(server_context))->r->the_request);
00456               
00457               arr = apr_table_elts(((php_struct *) SG(server_context))->r->headers_in);
00458               APR_ARRAY_FOREACH_OPEN(arr, key, val)
00459                      if (!val) {
00460                             val = "";
00461                      }
00462                       php_info_print_table_row(2, key, val);
00463               APR_ARRAY_FOREACH_CLOSE()
00464 
00465               php_info_print_table_colspan_header(2, "HTTP Response Headers");
00466               arr = apr_table_elts(((php_struct *) SG(server_context))->r->headers_out);
00467               APR_ARRAY_FOREACH_OPEN(arr, key, val)
00468                      if (!val) {
00469                             val = "";
00470                      }
00471                       php_info_print_table_row(2, key, val);
00472               APR_ARRAY_FOREACH_CLOSE()
00473               
00474               php_info_print_table_end();
00475        }
00476 }
00477 
00478 /* {{{ arginfo */
00479 ZEND_BEGIN_ARG_INFO_EX(arginfo_apache2handler_lookup_uri, 0, 0, 1)
00480        ZEND_ARG_INFO(0, filename)
00481 ZEND_END_ARG_INFO()
00482 
00483 ZEND_BEGIN_ARG_INFO_EX(arginfo_apache2handler_virtual, 0, 0, 1)
00484        ZEND_ARG_INFO(0, uri)
00485 ZEND_END_ARG_INFO()
00486 
00487 ZEND_BEGIN_ARG_INFO(arginfo_apache2handler_response_headers, 0)
00488 ZEND_END_ARG_INFO()
00489 
00490 ZEND_BEGIN_ARG_INFO(arginfo_apache2handler_getallheaders, 0)
00491 ZEND_END_ARG_INFO()
00492 
00493 ZEND_BEGIN_ARG_INFO_EX(arginfo_apache2handler_note, 0, 0, 1)
00494        ZEND_ARG_INFO(0, note_name)
00495        ZEND_ARG_INFO(0, note_value)
00496 ZEND_END_ARG_INFO()
00497 
00498 ZEND_BEGIN_ARG_INFO_EX(arginfo_apache2handler_setenv, 0, 0, 2)
00499        ZEND_ARG_INFO(0, variable)
00500        ZEND_ARG_INFO(0, value)
00501        ZEND_ARG_INFO(0, walk_to_top)
00502 ZEND_END_ARG_INFO()
00503 
00504 ZEND_BEGIN_ARG_INFO_EX(arginfo_apache2handler_getenv, 0, 0, 1)
00505        ZEND_ARG_INFO(0, variable)
00506        ZEND_ARG_INFO(0, walk_to_top)
00507 ZEND_END_ARG_INFO()
00508 
00509 ZEND_BEGIN_ARG_INFO(arginfo_apache2handler_get_version, 0)
00510 ZEND_END_ARG_INFO()
00511 
00512 ZEND_BEGIN_ARG_INFO(arginfo_apache2handler_get_modules, 0)
00513 ZEND_END_ARG_INFO()
00514 /* }}} */
00515 
00516 static const zend_function_entry apache_functions[] = {
00517        PHP_FE(apache_lookup_uri,          arginfo_apache2handler_lookup_uri)
00518        PHP_FE(virtual,                           arginfo_apache2handler_virtual) 
00519        PHP_FE(apache_request_headers,     arginfo_apache2handler_getallheaders)
00520        PHP_FE(apache_response_headers, arginfo_apache2handler_response_headers)
00521        PHP_FE(apache_setenv,              arginfo_apache2handler_setenv)
00522        PHP_FE(apache_getenv,              arginfo_apache2handler_getenv)
00523        PHP_FE(apache_note,         arginfo_apache2handler_note)
00524        PHP_FE(apache_get_version,  arginfo_apache2handler_get_version)
00525        PHP_FE(apache_get_modules,  arginfo_apache2handler_get_modules)
00526        PHP_FALIAS(getallheaders,   apache_request_headers, arginfo_apache2handler_getallheaders)
00527        {NULL, NULL, NULL}
00528 };
00529 
00530 PHP_INI_BEGIN()
00531        STD_PHP_INI_ENTRY("xbithack",             "0",   PHP_INI_ALL,  OnUpdateLong, xbithack,     php_apache2_info_struct, php_apache2_info)
00532        STD_PHP_INI_ENTRY("engine",        "1",   PHP_INI_ALL,  OnUpdateLong, engine,       php_apache2_info_struct, php_apache2_info)
00533        STD_PHP_INI_ENTRY("last_modified", "0",   PHP_INI_ALL,  OnUpdateLong, last_modified,       php_apache2_info_struct, php_apache2_info)
00534 PHP_INI_END()
00535 
00536 static PHP_MINIT_FUNCTION(apache)
00537 {
00538 #ifdef ZTS
00539        ts_allocate_id(&php_apache2_info_id, sizeof(php_apache2_info_struct), (ts_allocate_ctor) NULL, NULL);
00540 #endif
00541        REGISTER_INI_ENTRIES();
00542        return SUCCESS;
00543 }
00544 
00545 static PHP_MSHUTDOWN_FUNCTION(apache)
00546 {
00547        UNREGISTER_INI_ENTRIES();
00548        return SUCCESS;
00549 }
00550 
00551 zend_module_entry php_apache_module = {
00552        STANDARD_MODULE_HEADER,
00553        "apache2handler",
00554        apache_functions,
00555        PHP_MINIT(apache),
00556        PHP_MSHUTDOWN(apache),
00557        NULL,
00558        NULL, 
00559        PHP_MINFO(apache),
00560        NULL,
00561        STANDARD_MODULE_PROPERTIES
00562 };
00563 
00564 /*
00565  * Local variables:
00566  * tab-width: 4
00567  * c-basic-offset: 4
00568  * End:
00569  * vim600: sw=4 ts=4 fdm=marker
00570  * vim<600: sw=4 ts=4
00571  */