summaryrefslogtreecommitdiff
path: root/sapi/cgi/cgi_main.c
diff options
context:
space:
mode:
authorJani Taskinen <jani@php.net>2007-09-28 02:05:10 +0000
committerJani Taskinen <jani@php.net>2007-09-28 02:05:10 +0000
commit09b6f37f20b239dd021c21a1756629c4a64dc2da (patch)
tree635d42eb3591448faedff41f62ce0fff087ea467 /sapi/cgi/cgi_main.c
parent0d3bdf23d24ede05b07d613d030514861ab475e5 (diff)
downloadphp-git-09b6f37f20b239dd021c21a1756629c4a64dc2da.tar.gz
MFH:
- Added ".htaccess" style user-defined php.ini files support for CGI/FastCGI. - Added support for special [PATH=/opt/httpd/www.example.com/] sections in php.ini. All directives set in these sections will not be able to be overridden in user-defined ini-files or during runtime in the specified path. - Improved php.ini handling: . Added better error reporting for syntax errors in php.ini files . Allowed "ini-variables" to be used almost everywhere ini php.ini files . Allowed using alphanumeric/variable indexes in "array" ini options . Fixed get_cfg_var() to be able to return "array" ini options - Fixed bug #27372 (parse error loading browscap.ini at apache startup) - Fixed bug #42069 (parse_ini_file() allows using some non-alpha numeric characters)
Diffstat (limited to 'sapi/cgi/cgi_main.c')
-rw-r--r--sapi/cgi/cgi_main.c116
1 files changed, 112 insertions, 4 deletions
diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c
index 46ac15cfc4..f8c1954bbe 100644
--- a/sapi/cgi/cgi_main.c
+++ b/sapi/cgi/cgi_main.c
@@ -152,8 +152,30 @@ typedef struct _php_cgi_globals_struct {
#ifdef PHP_WIN32
zend_bool impersonate;
#endif
+ HashTable user_config_cache;
} php_cgi_globals_struct;
+/* {{{ user_config_cache
+ *
+ * Key for each cache entry is dirname(PATH_TRANSLATED).
+ *
+ * NOTE: Each cache entry config_hash contains the combination from all user ini files found in
+ * the path starting from doc_root throught to dirname(PATH_TRANSLATED). There is no point
+ * storing per-file entries as it would not be possible to detect added / deleted entries
+ * between separate files.
+ */
+typedef struct _user_config_cache_entry {
+ time_t expires;
+ HashTable *user_config;
+} user_config_cache_entry;
+
+static void user_config_cache_entry_dtor(user_config_cache_entry *entry) /* {{{ */
+{
+ zend_hash_destroy(entry->user_config);
+ free(entry->user_config);
+}
+/* }}} */
+
#ifdef ZTS
static int php_cgi_globals_id;
#define CGIG(v) TSRMG(php_cgi_globals_id, php_cgi_globals_struct *, v)
@@ -566,12 +588,96 @@ static void sapi_cgi_log_message(char *message)
}
}
+/* {{{ php_cgi_ini_activate_user_config
+ */
+static void php_cgi_ini_activate_user_config(char *path, int path_len, int start TSRMLS_DC)
+{
+ char *ptr;
+ user_config_cache_entry *new_entry, *entry;
+ time_t request_time = sapi_get_request_time(TSRMLS_C);
+
+ /* Find cached config entry: If not found, create one */
+ if (zend_hash_find(&CGIG(user_config_cache), path, path_len + 1, (void **) &entry) == FAILURE) {
+ new_entry = pemalloc(sizeof(user_config_cache_entry), 1);
+ new_entry->expires = 0;
+ new_entry->user_config = (HashTable *) pemalloc(sizeof(HashTable), 1);
+ zend_hash_init(new_entry->user_config, 0, NULL, (dtor_func_t) config_zval_dtor, 1);
+ zend_hash_update(&CGIG(user_config_cache), path, path_len + 1, new_entry, sizeof(user_config_cache_entry), (void **) &entry);
+ free(new_entry);
+ }
+
+ /* Check whether cache entry has expired and rescan if it is */
+ if (request_time > entry->expires) {
+
+ /* Clear the expired config */
+ zend_hash_clean(entry->user_config);
+
+ /* Walk through each directory and apply entries to user_config hash */
+ ptr = path + start; /* start is the point where doc_root ends! */
+ while ((ptr = strchr(ptr, DEFAULT_SLASH)) != NULL) {
+ *ptr = 0;
+ php_parse_user_ini_file(path, PG(user_ini_filename), entry->user_config TSRMLS_CC);
+ *ptr = '/';
+ ptr++;
+ }
+ entry->expires = request_time + PG(user_ini_cache_ttl);
+ }
+
+ /* Activate ini entries with values from the user config hash */
+ php_ini_activate_config(entry->user_config, PHP_INI_PERDIR, PHP_INI_STAGE_HTACCESS TSRMLS_CC);
+}
+/* }}} */
+
+static int sapi_cgi_activate(TSRMLS_D)
+{
+ char *path, *doc_root;
+ uint path_len, doc_root_len;
+
+ /* PATH_TRANSLATED should be defined at this stage but better safe than sorry :) */
+ if (!SG(request_info).path_translated) {
+ return FAILURE;
+ }
+
+ doc_root = sapi_cgibin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT") - 1 TSRMLS_CC);
+
+ /* DOCUMENT_ROOT should also be defined at this stage..but better check it anyway */
+ if (!doc_root) {
+ return FAILURE;
+ }
+ doc_root_len = strlen(doc_root);
+ if (doc_root[doc_root_len - 1] == '/') {
+ --doc_root_len;
+ }
+
+ /* Prepare search path */
+ path_len = strlen(SG(request_info).path_translated);
+ path = zend_strndup(SG(request_info).path_translated, path_len);
+ php_dirname(path, path_len);
+ path_len = strlen(path);
+
+ /* Make sure we have trailing slash! */
+ if (!IS_SLASH(path[path_len])) {
+ path[path_len++] = DEFAULT_SLASH;
+ }
+ path[path_len] = 0;
+
+ /* Activate per-dir-system-configuration defined in php.ini and stored into configuration_hash during startup */
+ php_ini_activate_per_dir_config(path, path_len TSRMLS_CC); /* Note: for global settings sake we check from root to path */
+
+ /* Load and activate user ini files in path starting from DOCUMENT_ROOT */
+ if (strlen(PG(user_ini_filename))) {
+ php_cgi_ini_activate_user_config(path, path_len, doc_root_len - 1 TSRMLS_CC);
+ }
+
+ free(path);
+ return SUCCESS;
+}
+
static int sapi_cgi_deactivate(TSRMLS_D)
{
/* flush only when SAPI was started. The reasons are:
1. SAPI Deactivate is called from two places: module init and request shutdown
- 2. When the first call occurs and the request is not set up, flush fails on
- FastCGI.
+ 2. When the first call occurs and the request is not set up, flush fails on FastCGI.
*/
if (SG(sapi_started)) {
sapi_cgibin_flush(SG(server_context));
@@ -587,7 +693,6 @@ static int php_cgi_startup(sapi_module_struct *sapi_module)
return SUCCESS;
}
-
/* {{{ sapi_module_struct cgi_sapi_module
*/
static sapi_module_struct cgi_sapi_module = {
@@ -597,7 +702,7 @@ static sapi_module_struct cgi_sapi_module = {
php_cgi_startup, /* startup */
php_module_shutdown_wrapper, /* shutdown */
- NULL, /* activate */
+ sapi_cgi_activate, /* activate */
sapi_cgi_deactivate, /* deactivate */
sapi_cgibin_ub_write, /* unbuffered write */
@@ -1072,6 +1177,7 @@ static void php_cgi_globals_ctor(php_cgi_globals_struct *php_cgi_globals TSRMLS_
#ifdef PHP_WIN32
php_cgi_globals->impersonate = 0;
#endif
+ zend_hash_init(&php_cgi_globals->user_config_cache, 0, NULL, (dtor_func_t) user_config_cache_entry_dtor, 1);
}
/* }}} */
@@ -1093,6 +1199,8 @@ static PHP_MINIT_FUNCTION(cgi)
*/
static PHP_MSHUTDOWN_FUNCTION(cgi)
{
+ zend_hash_destroy(&CGIG(user_config_cache));
+
UNREGISTER_INI_ENTRIES();
return SUCCESS;
}