Back to index

php5  5.3.10
php_ini.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: Zeev Suraski <zeev@zend.com>                                 |
00016    +----------------------------------------------------------------------+
00017  */
00018 
00019 /* $Id: php_ini.c 321634 2012-01-01 13:15:04Z felipe $ */
00020 
00021 #include "php.h"
00022 #include "ext/standard/info.h"
00023 #include "zend_ini.h"
00024 #include "zend_ini_scanner.h"
00025 #include "php_ini.h"
00026 #include "ext/standard/dl.h"
00027 #include "zend_extensions.h"
00028 #include "zend_highlight.h"
00029 #include "SAPI.h"
00030 #include "php_main.h"
00031 #include "php_scandir.h"
00032 #ifdef PHP_WIN32
00033 #include "win32/php_registry.h"
00034 #endif
00035 
00036 #if HAVE_SCANDIR && HAVE_ALPHASORT && HAVE_DIRENT_H
00037 #include <dirent.h>
00038 #endif
00039 
00040 #ifndef S_ISREG
00041 #define S_ISREG(mode)   (((mode) & S_IFMT) == S_IFREG)
00042 #endif
00043 
00044 #ifdef PHP_WIN32
00045 #define TRANSLATE_SLASHES_LOWER(path) \
00046        { \
00047               char *tmp = path; \
00048               while (*tmp) { \
00049                      if (*tmp == '\\') *tmp = '/'; \
00050                      else *tmp = tolower(*tmp); \
00051                             tmp++; \
00052               } \
00053        }
00054 #else
00055 #define TRANSLATE_SLASHES_LOWER(path)
00056 #endif
00057 
00058 
00059 typedef struct _php_extension_lists {
00060        zend_llist engine;
00061        zend_llist functions;
00062 } php_extension_lists;
00063 
00064 /* True globals */
00065 static int is_special_section = 0;
00066 static HashTable *active_ini_hash;
00067 static HashTable configuration_hash;
00068 static int has_per_dir_config = 0;
00069 static int has_per_host_config = 0;
00070 PHPAPI char *php_ini_opened_path=NULL;
00071 static php_extension_lists extension_lists;
00072 PHPAPI char *php_ini_scanned_path=NULL;
00073 PHPAPI char *php_ini_scanned_files=NULL;
00074 
00075 /* {{{ php_ini_displayer_cb
00076  */
00077 static void php_ini_displayer_cb(zend_ini_entry *ini_entry, int type TSRMLS_DC)
00078 {
00079        if (ini_entry->displayer) {
00080               ini_entry->displayer(ini_entry, type);
00081        } else {
00082               char *display_string;
00083               uint display_string_length, esc_html=0;
00084 
00085               if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
00086                      if (ini_entry->orig_value && ini_entry->orig_value[0]) {
00087                             display_string = ini_entry->orig_value;
00088                             display_string_length = ini_entry->orig_value_length;
00089                             esc_html = !sapi_module.phpinfo_as_text;
00090                      } else {
00091                             if (!sapi_module.phpinfo_as_text) {
00092                                    display_string = "<i>no value</i>";
00093                                    display_string_length = sizeof("<i>no value</i>") - 1;
00094                             } else {
00095                                    display_string = "no value";
00096                                    display_string_length = sizeof("no value") - 1;
00097                             }
00098                      }
00099               } else if (ini_entry->value && ini_entry->value[0]) {
00100                      display_string = ini_entry->value;
00101                      display_string_length = ini_entry->value_length;
00102                      esc_html = !sapi_module.phpinfo_as_text;
00103               } else {
00104                      if (!sapi_module.phpinfo_as_text) {
00105                             display_string = "<i>no value</i>";
00106                             display_string_length = sizeof("<i>no value</i>") - 1;
00107                      } else {
00108                             display_string = "no value";
00109                             display_string_length = sizeof("no value") - 1;
00110                      }
00111               }
00112 
00113               if (esc_html) {
00114                      php_html_puts(display_string, display_string_length TSRMLS_CC);
00115               } else {
00116                      PHPWRITE(display_string, display_string_length);
00117               }
00118        }
00119 }
00120 /* }}} */
00121 
00122 /* {{{ php_ini_displayer
00123  */
00124 static int php_ini_displayer(zend_ini_entry *ini_entry, int module_number TSRMLS_DC)
00125 {
00126        if (ini_entry->module_number != module_number) {
00127               return 0;
00128        }
00129        if (!sapi_module.phpinfo_as_text) {
00130               PUTS("<tr>");
00131               PUTS("<td class=\"e\">");
00132               PHPWRITE(ini_entry->name, ini_entry->name_length - 1);
00133               PUTS("</td><td class=\"v\">");
00134               php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ACTIVE TSRMLS_CC);
00135               PUTS("</td><td class=\"v\">");
00136               php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ORIG TSRMLS_CC);
00137               PUTS("</td></tr>\n");
00138        } else {
00139               PHPWRITE(ini_entry->name, ini_entry->name_length - 1);
00140               PUTS(" => ");
00141               php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ACTIVE TSRMLS_CC);
00142               PUTS(" => ");
00143               php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ORIG TSRMLS_CC);
00144               PUTS("\n");
00145        }
00146        return 0;
00147 }
00148 /* }}} */
00149 
00150 /* {{{ php_ini_available
00151  */
00152 static int php_ini_available(zend_ini_entry *ini_entry, int *module_number_available TSRMLS_DC)
00153 {
00154        if (ini_entry->module_number == *module_number_available) {
00155               *module_number_available = -1;
00156               return ZEND_HASH_APPLY_STOP;
00157        } else {
00158               return ZEND_HASH_APPLY_KEEP;
00159        }
00160 }
00161 /* }}} */
00162 
00163 /* {{{ display_ini_entries
00164  */
00165 PHPAPI void display_ini_entries(zend_module_entry *module)
00166 {
00167        int module_number, module_number_available;
00168        TSRMLS_FETCH();
00169 
00170        if (module) {
00171               module_number = module->module_number;
00172        } else {
00173               module_number = 0;
00174        }
00175        module_number_available = module_number;
00176        zend_hash_apply_with_argument(EG(ini_directives), (apply_func_arg_t) php_ini_available, &module_number_available TSRMLS_CC);
00177        if (module_number_available == -1) {
00178               php_info_print_table_start();
00179               php_info_print_table_header(3, "Directive", "Local Value", "Master Value");
00180               zend_hash_apply_with_argument(EG(ini_directives), (apply_func_arg_t) php_ini_displayer, (void *) (zend_intptr_t) module_number TSRMLS_CC);
00181               php_info_print_table_end();
00182        }
00183 }
00184 /* }}} */
00185 
00186 /* php.ini support */
00187 #define PHP_EXTENSION_TOKEN        "extension"
00188 #define ZEND_EXTENSION_TOKEN       "zend_extension"
00189 
00190 /* {{{ config_zval_dtor
00191  */
00192 PHPAPI void config_zval_dtor(zval *zvalue)
00193 {
00194        if (Z_TYPE_P(zvalue) == IS_ARRAY) {
00195               zend_hash_destroy(Z_ARRVAL_P(zvalue));
00196               free(Z_ARRVAL_P(zvalue));
00197        } else if (Z_TYPE_P(zvalue) == IS_STRING) {
00198               free(Z_STRVAL_P(zvalue));
00199        }
00200 }
00201 /* Reset / free active_ini_sectin global */
00202 #define RESET_ACTIVE_INI_HASH() do { \
00203        active_ini_hash = NULL;          \
00204        is_special_section = 0;          \
00205 } while (0)
00206 /* }}} */
00207 
00208 /* {{{ php_ini_parser_cb
00209  */
00210 static void php_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callback_type, HashTable *target_hash)
00211 {
00212        zval *entry;
00213        HashTable *active_hash;
00214        char *extension_name;
00215 
00216        if (active_ini_hash) {
00217               active_hash = active_ini_hash;
00218        } else {
00219               active_hash = target_hash;
00220        }
00221 
00222        switch (callback_type) {
00223               case ZEND_INI_PARSER_ENTRY: {
00224                             if (!arg2) {
00225                                    /* bare string - nothing to do */
00226                                    break;
00227                             }
00228 
00229                             /* PHP and Zend extensions are not added into configuration hash! */
00230                             if (!is_special_section && !strcasecmp(Z_STRVAL_P(arg1), PHP_EXTENSION_TOKEN)) { /* load PHP extension */
00231                                    extension_name = estrndup(Z_STRVAL_P(arg2), Z_STRLEN_P(arg2));
00232                                    zend_llist_add_element(&extension_lists.functions, &extension_name);
00233                             } else if (!is_special_section && !strcasecmp(Z_STRVAL_P(arg1), ZEND_EXTENSION_TOKEN)) { /* load Zend extension */
00234                                    extension_name = estrndup(Z_STRVAL_P(arg2), Z_STRLEN_P(arg2));
00235                                    zend_llist_add_element(&extension_lists.engine, &extension_name);
00236 
00237                             /* All other entries are added into either configuration_hash or active ini section array */
00238                             } else {
00239                                    /* Store in active hash */
00240                                    zend_hash_update(active_hash, Z_STRVAL_P(arg1), Z_STRLEN_P(arg1) + 1, arg2, sizeof(zval), (void **) &entry);
00241                                    Z_STRVAL_P(entry) = zend_strndup(Z_STRVAL_P(entry), Z_STRLEN_P(entry));
00242                             }
00243                      }
00244                      break;
00245 
00246               case ZEND_INI_PARSER_POP_ENTRY: {
00247                             zval *option_arr;
00248                             zval *find_arr;
00249 
00250                             if (!arg2) {
00251                                    /* bare string - nothing to do */
00252                                    break;
00253                             }
00254 
00255 /* fprintf(stdout, "ZEND_INI_PARSER_POP_ENTRY: %s[%s] = %s\n",Z_STRVAL_P(arg1), Z_STRVAL_P(arg3), Z_STRVAL_P(arg2)); */
00256 
00257                             /* If option not found in hash or is not an array -> create array, otherwise add to existing array */
00258                             if (zend_hash_find(active_hash, Z_STRVAL_P(arg1), Z_STRLEN_P(arg1) + 1, (void **) &find_arr) == FAILURE || Z_TYPE_P(find_arr) != IS_ARRAY) {
00259                                    option_arr = (zval *) pemalloc(sizeof(zval), 1);
00260                                    INIT_PZVAL(option_arr);
00261                                    Z_TYPE_P(option_arr) = IS_ARRAY;
00262                                    Z_ARRVAL_P(option_arr) = (HashTable *) pemalloc(sizeof(HashTable), 1);
00263                                    zend_hash_init(Z_ARRVAL_P(option_arr), 0, NULL, (dtor_func_t) config_zval_dtor, 1);
00264                                    zend_hash_update(active_hash, Z_STRVAL_P(arg1), Z_STRLEN_P(arg1) + 1, option_arr, sizeof(zval), (void **) &find_arr);
00265                                    free(option_arr);
00266                             }
00267 
00268                             /* arg3 is possible option offset name */
00269                             if (arg3 && Z_STRLEN_P(arg3) > 0) {
00270                                    zend_symtable_update(Z_ARRVAL_P(find_arr), Z_STRVAL_P(arg3), Z_STRLEN_P(arg3) + 1, arg2, sizeof(zval), (void **) &entry);
00271                             } else {
00272                                    zend_hash_next_index_insert(Z_ARRVAL_P(find_arr), arg2, sizeof(zval), (void **) &entry);
00273                             }
00274                             Z_STRVAL_P(entry) = zend_strndup(Z_STRVAL_P(entry), Z_STRLEN_P(entry));
00275                      }
00276                      break;
00277 
00278               case ZEND_INI_PARSER_SECTION: { /* Create an array of entries of each section */
00279 
00280 /* fprintf(stdout, "ZEND_INI_PARSER_SECTION: %s\n",Z_STRVAL_P(arg1)); */
00281 
00282                             char *key = NULL;
00283                             uint key_len;
00284 
00285                             /* PATH sections */
00286                             if (!strncasecmp(Z_STRVAL_P(arg1), "PATH", sizeof("PATH") - 1)) {
00287                                    key = Z_STRVAL_P(arg1);
00288                                    key = key + sizeof("PATH") - 1;
00289                                    key_len = Z_STRLEN_P(arg1) - sizeof("PATH") + 1;
00290                                    is_special_section = 1;
00291                                    has_per_dir_config = 1;
00292 
00293                                    /* make the path lowercase on Windows, for case insensitivty. Does nothign for other platforms */
00294                                    TRANSLATE_SLASHES_LOWER(key);
00295 
00296                             /* HOST sections */
00297                             } else if (!strncasecmp(Z_STRVAL_P(arg1), "HOST", sizeof("HOST") - 1)) {
00298                                    key = Z_STRVAL_P(arg1);
00299                                    key = key + sizeof("HOST") - 1;
00300                                    key_len = Z_STRLEN_P(arg1) - sizeof("HOST") + 1;
00301                                    is_special_section = 1;
00302                                    has_per_host_config = 1;
00303                                    zend_str_tolower(key, key_len); /* host names are case-insensitive. */
00304 
00305                             } else {
00306                                    is_special_section = 0;
00307                             }
00308 
00309                             if (key && key_len > 0) {
00310                                    /* Strip any trailing slashes */
00311                                    while (key_len > 0 && (key[key_len - 1] == '/' || key[key_len - 1] == '\\')) {
00312                                           key_len--;
00313                                           key[key_len] = 0;
00314                                    }
00315 
00316                                    /* Strip any leading whitespace and '=' */
00317                                    while (*key && (
00318                                           *key == '=' ||
00319                                           *key == ' ' ||
00320                                           *key == '\t'
00321                                    )) {
00322                                           key++;
00323                                           key_len--;
00324                                    }
00325 
00326                                    /* Search for existing entry and if it does not exist create one */
00327                                    if (zend_hash_find(target_hash, key, key_len + 1, (void **) &entry) == FAILURE) {
00328                                           zval *section_arr;
00329 
00330                                           section_arr = (zval *) pemalloc(sizeof(zval), 1);
00331                                           INIT_PZVAL(section_arr);
00332                                           Z_TYPE_P(section_arr) = IS_ARRAY;
00333                                           Z_ARRVAL_P(section_arr) = (HashTable *) pemalloc(sizeof(HashTable), 1);
00334                                           zend_hash_init(Z_ARRVAL_P(section_arr), 0, NULL, (dtor_func_t) config_zval_dtor, 1);
00335                                           zend_hash_update(target_hash, key, key_len + 1, section_arr, sizeof(zval), (void **) &entry);
00336                                           free(section_arr);
00337                                    }
00338                                    active_ini_hash = Z_ARRVAL_P(entry);
00339                             }
00340                      }
00341                      break;
00342        }
00343 }
00344 /* }}} */
00345 
00346 /* {{{ php_load_php_extension_cb
00347  */
00348 static void php_load_php_extension_cb(void *arg TSRMLS_DC)
00349 {
00350 #ifdef HAVE_LIBDL
00351        php_load_extension(*((char **) arg), MODULE_PERSISTENT, 0 TSRMLS_CC);
00352 #endif
00353 }
00354 /* }}} */
00355 
00356 /* {{{ php_load_zend_extension_cb
00357  */
00358 static void php_load_zend_extension_cb(void *arg TSRMLS_DC)
00359 {
00360        zend_load_extension(*((char **) arg));
00361 }
00362 /* }}} */
00363 
00364 /* {{{ php_init_config
00365  */
00366 int php_init_config(TSRMLS_D)
00367 {
00368        char *php_ini_file_name = NULL;
00369        char *php_ini_search_path = NULL;
00370        int php_ini_scanned_path_len;
00371        int safe_mode_state;
00372        char *open_basedir;
00373        int free_ini_search_path = 0;
00374        zend_file_handle fh;
00375 
00376        if (zend_hash_init(&configuration_hash, 0, NULL, (dtor_func_t) config_zval_dtor, 1) == FAILURE) {
00377               return FAILURE;
00378        }
00379 
00380        if (sapi_module.ini_defaults) {
00381               sapi_module.ini_defaults(&configuration_hash);
00382        }
00383 
00384        zend_llist_init(&extension_lists.engine, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
00385        zend_llist_init(&extension_lists.functions, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
00386 
00387        safe_mode_state = PG(safe_mode);
00388        open_basedir = PG(open_basedir);
00389 
00390        if (sapi_module.php_ini_path_override) {
00391               php_ini_file_name = sapi_module.php_ini_path_override;
00392               php_ini_search_path = sapi_module.php_ini_path_override;
00393               free_ini_search_path = 0;
00394        } else if (!sapi_module.php_ini_ignore) {
00395               int search_path_size;
00396               char *default_location;
00397               char *env_location;
00398               char *binary_location;
00399               static const char paths_separator[] = { ZEND_PATHS_SEPARATOR, 0 };
00400 #ifdef PHP_WIN32
00401               char *reg_location;
00402               char phprc_path[MAXPATHLEN];
00403 #endif
00404 
00405               env_location = getenv("PHPRC");
00406 
00407 #ifdef PHP_WIN32
00408               if (!env_location) {
00409                      char dummybuf;
00410                      int size;
00411 
00412                      SetLastError(0);
00413 
00414                      /*If the given bugger is not large enough to hold the data, the return value is 
00415                      the buffer size,  in characters, required to hold the string and its terminating 
00416                      null character. We use this return value to alloc the final buffer. */
00417                      size = GetEnvironmentVariableA("PHPRC", &dummybuf, 0);
00418                      if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
00419                             /* The environment variable doesn't exist. */
00420                             env_location = "";
00421                      } else {
00422                             if (size == 0) {
00423                                    env_location = "";
00424                             } else {
00425                                    size = GetEnvironmentVariableA("PHPRC", phprc_path, size);
00426                                    env_location = phprc_path;
00427                             }
00428                      }
00429               }
00430 #else
00431               if (!env_location) {
00432                      env_location = "";
00433               }
00434 #endif
00435               /*
00436                * Prepare search path
00437                */
00438 
00439               search_path_size = MAXPATHLEN * 4 + strlen(env_location) + 3 + 1;
00440               php_ini_search_path = (char *) emalloc(search_path_size);
00441               free_ini_search_path = 1;
00442               php_ini_search_path[0] = 0;
00443 
00444               /* Add environment location */
00445               if (env_location[0]) {
00446                      if (*php_ini_search_path) {
00447                             strlcat(php_ini_search_path, paths_separator, search_path_size);
00448                      }
00449                      strlcat(php_ini_search_path, env_location, search_path_size);
00450                      php_ini_file_name = env_location;
00451               }
00452 
00453 #ifdef PHP_WIN32
00454               /* Add registry location */
00455               reg_location = GetIniPathFromRegistry();
00456               if (reg_location != NULL) {
00457                      if (*php_ini_search_path) {
00458                             strlcat(php_ini_search_path, paths_separator, search_path_size);
00459                      }
00460                      strlcat(php_ini_search_path, reg_location, search_path_size);
00461                      efree(reg_location);
00462               }
00463 #endif
00464 
00465               /* Add cwd (not with CLI) */
00466               if (strcmp(sapi_module.name, "cli") != 0) {
00467                      if (*php_ini_search_path) {
00468                             strlcat(php_ini_search_path, paths_separator, search_path_size);
00469                      }
00470                      strlcat(php_ini_search_path, ".", search_path_size);
00471               }
00472 
00473               /* Add binary directory */
00474 #ifdef PHP_WIN32
00475               binary_location = (char *) emalloc(MAXPATHLEN);
00476               if (GetModuleFileName(0, binary_location, MAXPATHLEN) == 0) {
00477                      efree(binary_location);
00478                      binary_location = NULL;
00479               }
00480 #else
00481               if (sapi_module.executable_location) {
00482                      binary_location = (char *)emalloc(MAXPATHLEN);
00483                      if (!strchr(sapi_module.executable_location, '/')) {
00484                             char *envpath, *path;
00485                             int found = 0;
00486 
00487                             if ((envpath = getenv("PATH")) != NULL) {
00488                                    char *search_dir, search_path[MAXPATHLEN];
00489                                    char *last = NULL;
00490 
00491                                    path = estrdup(envpath);
00492                                    search_dir = php_strtok_r(path, ":", &last);
00493 
00494                                    while (search_dir) {
00495                                           snprintf(search_path, MAXPATHLEN, "%s/%s", search_dir, sapi_module.executable_location);
00496                                           if (VCWD_REALPATH(search_path, binary_location) && !VCWD_ACCESS(binary_location, X_OK)) {
00497                                                  found = 1;
00498                                                  break;
00499                                           }
00500                                           search_dir = php_strtok_r(NULL, ":", &last);
00501                                    }
00502                                    efree(path);
00503                             }
00504                             if (!found) {
00505                                    efree(binary_location);
00506                                    binary_location = NULL;
00507                             }
00508                      } else if (!VCWD_REALPATH(sapi_module.executable_location, binary_location) || VCWD_ACCESS(binary_location, X_OK)) {
00509                             efree(binary_location);
00510                             binary_location = NULL;
00511                      }
00512               } else {
00513                      binary_location = NULL;
00514               }
00515 #endif
00516               if (binary_location) {
00517                      char *separator_location = strrchr(binary_location, DEFAULT_SLASH);
00518 
00519                      if (separator_location && separator_location != binary_location) {
00520                             *(separator_location) = 0;
00521                      }
00522                      if (*php_ini_search_path) {
00523                             strlcat(php_ini_search_path, paths_separator, search_path_size);
00524                      }
00525                      strlcat(php_ini_search_path, binary_location, search_path_size);
00526                      efree(binary_location);
00527               }
00528 
00529               /* Add default location */
00530 #ifdef PHP_WIN32
00531               default_location = (char *) emalloc(MAXPATHLEN + 1);
00532 
00533               if (0 < GetWindowsDirectory(default_location, MAXPATHLEN)) {
00534                      if (*php_ini_search_path) {
00535                             strlcat(php_ini_search_path, paths_separator, search_path_size);
00536                      }
00537                      strlcat(php_ini_search_path, default_location, search_path_size);
00538               }
00539 
00540               /* For people running under terminal services, GetWindowsDirectory will
00541                * return their personal Windows directory, so lets add the system
00542                * windows directory too */
00543               if (0 < GetSystemWindowsDirectory(default_location, MAXPATHLEN)) {
00544                      if (*php_ini_search_path) {
00545                             strlcat(php_ini_search_path, paths_separator, search_path_size);
00546                      }
00547                      strlcat(php_ini_search_path, default_location, search_path_size);
00548               }
00549               efree(default_location);
00550 
00551 #else
00552               default_location = PHP_CONFIG_FILE_PATH;
00553               if (*php_ini_search_path) {
00554                      strlcat(php_ini_search_path, paths_separator, search_path_size);
00555               }
00556               strlcat(php_ini_search_path, default_location, search_path_size);
00557 #endif
00558        }
00559 
00560        PG(safe_mode) = 0;
00561        PG(open_basedir) = NULL;
00562 
00563        /*
00564         * Find and open actual ini file
00565         */
00566 
00567        memset(&fh, 0, sizeof(fh));
00568 
00569        /* If SAPI does not want to ignore all ini files OR an overriding file/path is given.
00570         * This allows disabling scanning for ini files in the PHP_CONFIG_FILE_SCAN_DIR but still
00571         * load an optional ini file. */
00572        if (!sapi_module.php_ini_ignore || sapi_module.php_ini_path_override) {
00573 
00574               /* Check if php_ini_file_name is a file and can be opened */
00575               if (php_ini_file_name && php_ini_file_name[0]) {
00576                      struct stat statbuf;
00577 
00578                      if (!VCWD_STAT(php_ini_file_name, &statbuf)) {
00579                             if (!((statbuf.st_mode & S_IFMT) == S_IFDIR)) {
00580                                    fh.handle.fp = VCWD_FOPEN(php_ini_file_name, "r");
00581                                    if (fh.handle.fp) {
00582                                           fh.filename = php_ini_opened_path = expand_filepath(php_ini_file_name, NULL TSRMLS_CC);
00583                                    }
00584                             }
00585                      }
00586               }
00587 
00588               /* Otherwise search for php-%sapi-module-name%.ini file in search path */
00589               if (!fh.handle.fp) {
00590                      const char *fmt = "php-%s.ini";
00591                      char *ini_fname;
00592                      spprintf(&ini_fname, 0, fmt, sapi_module.name);
00593                      fh.handle.fp = php_fopen_with_path(ini_fname, "r", php_ini_search_path, &php_ini_opened_path TSRMLS_CC);
00594                      efree(ini_fname);
00595                      if (fh.handle.fp) {
00596                             fh.filename = php_ini_opened_path;
00597                      }
00598               }
00599 
00600               /* If still no ini file found, search for php.ini file in search path */
00601               if (!fh.handle.fp) {
00602                      fh.handle.fp = php_fopen_with_path("php.ini", "r", php_ini_search_path, &php_ini_opened_path TSRMLS_CC);
00603                      if (fh.handle.fp) {
00604                             fh.filename = php_ini_opened_path;
00605                      }
00606               }
00607        }
00608 
00609        if (free_ini_search_path) {
00610               efree(php_ini_search_path);
00611        }
00612 
00613        PG(safe_mode) = safe_mode_state;
00614        PG(open_basedir) = open_basedir;
00615 
00616        if (fh.handle.fp) {
00617               fh.type = ZEND_HANDLE_FP;
00618               RESET_ACTIVE_INI_HASH();
00619 
00620               zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash TSRMLS_CC);
00621 
00622               {
00623                      zval tmp;
00624 
00625                      Z_STRLEN(tmp) = strlen(fh.filename);
00626                      Z_STRVAL(tmp) = zend_strndup(fh.filename, Z_STRLEN(tmp));
00627                      Z_TYPE(tmp) = IS_STRING;
00628                      Z_SET_REFCOUNT(tmp, 0);
00629 
00630                      zend_hash_update(&configuration_hash, "cfg_file_path", sizeof("cfg_file_path"), (void *) &tmp, sizeof(zval), NULL);
00631                      if (php_ini_opened_path) {
00632                             efree(php_ini_opened_path);
00633                      }
00634                      php_ini_opened_path = zend_strndup(Z_STRVAL(tmp), Z_STRLEN(tmp));
00635               }
00636        }
00637 
00638        /* Check for PHP_INI_SCAN_DIR environment variable to override/set config file scan directory */
00639        php_ini_scanned_path = getenv("PHP_INI_SCAN_DIR");
00640        if (!php_ini_scanned_path) {
00641               /* Or fall back using possible --with-config-file-scan-dir setting (defaults to empty string!) */
00642               php_ini_scanned_path = PHP_CONFIG_FILE_SCAN_DIR;
00643        }
00644        php_ini_scanned_path_len = strlen(php_ini_scanned_path);
00645 
00646        /* Scan and parse any .ini files found in scan path if path not empty. */
00647        if (!sapi_module.php_ini_ignore && php_ini_scanned_path_len) {
00648               struct dirent **namelist;
00649               int ndir, i;
00650               struct stat sb;
00651               char ini_file[MAXPATHLEN];
00652               char *p;
00653               zend_file_handle fh2;
00654               zend_llist scanned_ini_list;
00655               zend_llist_element *element;
00656               int l, total_l = 0;
00657 
00658               if ((ndir = php_scandir(php_ini_scanned_path, &namelist, 0, php_alphasort)) > 0) {
00659                      zend_llist_init(&scanned_ini_list, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
00660                      memset(&fh2, 0, sizeof(fh2));
00661 
00662                      for (i = 0; i < ndir; i++) {
00663 
00664                             /* check for any file with .ini extension */
00665                             if (!(p = strrchr(namelist[i]->d_name, '.')) || (p && strcmp(p, ".ini"))) {
00666                                    free(namelist[i]);
00667                                    continue;
00668                             }
00669                             /* Reset active ini section */
00670                             RESET_ACTIVE_INI_HASH();
00671 
00672                             if (IS_SLASH(php_ini_scanned_path[php_ini_scanned_path_len - 1])) {
00673                                    snprintf(ini_file, MAXPATHLEN, "%s%s", php_ini_scanned_path, namelist[i]->d_name);
00674                             } else {
00675                                    snprintf(ini_file, MAXPATHLEN, "%s%c%s", php_ini_scanned_path, DEFAULT_SLASH, namelist[i]->d_name);
00676                             }
00677                             if (VCWD_STAT(ini_file, &sb) == 0) {
00678                                    if (S_ISREG(sb.st_mode)) {
00679                                           if ((fh2.handle.fp = VCWD_FOPEN(ini_file, "r"))) {
00680                                                  fh2.filename = ini_file;
00681                                                  fh2.type = ZEND_HANDLE_FP;
00682 
00683                                                  if (zend_parse_ini_file(&fh2, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash TSRMLS_CC) == SUCCESS) {
00684                                                         /* Here, add it to the list of ini files read */
00685                                                         l = strlen(ini_file);
00686                                                         total_l += l + 2;
00687                                                         p = estrndup(ini_file, l);
00688                                                         zend_llist_add_element(&scanned_ini_list, &p);
00689                                                  }
00690                                           }
00691                                    }
00692                             }
00693                             free(namelist[i]);
00694                      }
00695                      free(namelist);
00696 
00697                      if (total_l) {
00698                             int php_ini_scanned_files_len = (php_ini_scanned_files) ? strlen(php_ini_scanned_files) + 1 : 0;
00699                             php_ini_scanned_files = (char *) realloc(php_ini_scanned_files, php_ini_scanned_files_len + total_l + 1);
00700                             if (!php_ini_scanned_files_len) {
00701                                    *php_ini_scanned_files = '\0';
00702                             }
00703                             total_l += php_ini_scanned_files_len;
00704                             for (element = scanned_ini_list.head; element; element = element->next) {
00705                                    if (php_ini_scanned_files_len) {
00706                                           strlcat(php_ini_scanned_files, ",\n", total_l);
00707                                    }
00708                                    strlcat(php_ini_scanned_files, *(char **)element->data, total_l);
00709                                    strlcat(php_ini_scanned_files, element->next ? ",\n" : "\n", total_l);
00710                             }
00711                      }
00712                      zend_llist_destroy(&scanned_ini_list);
00713               }
00714        } else {
00715               /* Make sure an empty php_ini_scanned_path ends up as NULL */
00716               php_ini_scanned_path = NULL;
00717        }
00718 
00719        if (sapi_module.ini_entries) {
00720               /* Reset active ini section */
00721               RESET_ACTIVE_INI_HASH();
00722               zend_parse_ini_string(sapi_module.ini_entries, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash TSRMLS_CC);
00723        }
00724 
00725        return SUCCESS;
00726 }
00727 /* }}} */
00728 
00729 /* {{{ php_shutdown_config
00730  */
00731 int php_shutdown_config(void)
00732 {
00733        zend_hash_destroy(&configuration_hash);
00734        if (php_ini_opened_path) {
00735               free(php_ini_opened_path);
00736               php_ini_opened_path = NULL;
00737        }
00738        if (php_ini_scanned_files) {
00739               free(php_ini_scanned_files);
00740               php_ini_scanned_files = NULL;
00741        }
00742        return SUCCESS;
00743 }
00744 /* }}} */
00745 
00746 /* {{{ php_ini_register_extensions
00747  */
00748 void php_ini_register_extensions(TSRMLS_D)
00749 {
00750        zend_llist_apply(&extension_lists.engine, php_load_zend_extension_cb TSRMLS_CC);
00751        zend_llist_apply(&extension_lists.functions, php_load_php_extension_cb TSRMLS_CC);
00752 
00753        zend_llist_destroy(&extension_lists.engine);
00754        zend_llist_destroy(&extension_lists.functions);
00755 }
00756 /* }}} */
00757 
00758 /* {{{ php_parse_user_ini_file
00759  */
00760 PHPAPI int php_parse_user_ini_file(const char *dirname, char *ini_filename, HashTable *target_hash TSRMLS_DC)
00761 {
00762        struct stat sb;
00763        char ini_file[MAXPATHLEN];
00764        zend_file_handle fh;
00765 
00766        snprintf(ini_file, MAXPATHLEN, "%s%c%s", dirname, DEFAULT_SLASH, ini_filename);
00767 
00768        if (VCWD_STAT(ini_file, &sb) == 0) {
00769               if (S_ISREG(sb.st_mode)) {
00770                      memset(&fh, 0, sizeof(fh));
00771                      if ((fh.handle.fp = VCWD_FOPEN(ini_file, "r"))) {
00772                             fh.filename = ini_file;
00773                             fh.type = ZEND_HANDLE_FP;
00774 
00775                             /* Reset active ini section */
00776                             RESET_ACTIVE_INI_HASH();
00777 
00778                             if (zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, target_hash TSRMLS_CC) == SUCCESS) {
00779                                    /* FIXME: Add parsed file to the list of user files read? */
00780                                    return SUCCESS;
00781                             }
00782                             return FAILURE;
00783                      }
00784               }
00785        }
00786        return FAILURE;
00787 }
00788 /* }}} */
00789 
00790 /* {{{ php_ini_activate_config
00791  */
00792 PHPAPI void php_ini_activate_config(HashTable *source_hash, int modify_type, int stage TSRMLS_DC)
00793 {
00794        char *str;
00795        zval *data;
00796        uint str_len;
00797        ulong num_index;
00798 
00799        /* Walk through config hash and alter matching ini entries using the values found in the hash */
00800        for (zend_hash_internal_pointer_reset(source_hash);
00801               zend_hash_get_current_key_ex(source_hash, &str, &str_len, &num_index, 0, NULL) == HASH_KEY_IS_STRING;
00802               zend_hash_move_forward(source_hash)
00803        ) {
00804               zend_hash_get_current_data(source_hash, (void **) &data);
00805               zend_alter_ini_entry_ex(str, str_len, Z_STRVAL_P(data), Z_STRLEN_P(data), modify_type, stage, 0 TSRMLS_CC);
00806        }
00807 }
00808 /* }}} */
00809 
00810 /* {{{ php_ini_has_per_dir_config
00811  */
00812 PHPAPI int php_ini_has_per_dir_config(void)
00813 {
00814        return has_per_dir_config;
00815 }
00816 /* }}} */
00817 
00818 /* {{{ php_ini_activate_per_dir_config
00819  */
00820 PHPAPI void php_ini_activate_per_dir_config(char *path, uint path_len TSRMLS_DC)
00821 {
00822        zval *tmp2;
00823        char *ptr;
00824 
00825 #if PHP_WIN32
00826        char path_bak[MAXPATHLEN];
00827 #endif
00828 
00829        if (path_len > MAXPATHLEN) {
00830               return;
00831        }
00832 
00833 #if PHP_WIN32
00834        memcpy(path_bak, path, path_len);
00835        path_bak[path_len] = 0;
00836        TRANSLATE_SLASHES_LOWER(path_bak);
00837        path = path_bak;
00838 #endif
00839 
00840        /* Walk through each directory in path and apply any found per-dir-system-configuration from configuration_hash */
00841        if (has_per_dir_config && path && path_len) {
00842               ptr = path + 1;
00843               while ((ptr = strchr(ptr, '/')) != NULL) {
00844                      *ptr = 0;
00845                      /* Search for source array matching the path from configuration_hash */
00846                      if (zend_hash_find(&configuration_hash, path, strlen(path) + 1, (void **) &tmp2) == SUCCESS) {
00847                             php_ini_activate_config(Z_ARRVAL_P(tmp2), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE TSRMLS_CC);
00848                      }
00849                      *ptr = '/';
00850                      ptr++;
00851               }
00852        }
00853 }
00854 /* }}} */
00855 
00856 /* {{{ php_ini_has_per_host_config
00857  */
00858 PHPAPI int php_ini_has_per_host_config(void)
00859 {
00860        return has_per_host_config;
00861 }
00862 /* }}} */
00863 
00864 /* {{{ php_ini_activate_per_host_config
00865  */
00866 PHPAPI void php_ini_activate_per_host_config(const char *host, uint host_len TSRMLS_DC)
00867 {
00868        zval *tmp;
00869 
00870        if (has_per_host_config && host && host_len) {
00871               /* Search for source array matching the host from configuration_hash */
00872               if (zend_hash_find(&configuration_hash, host, host_len, (void **) &tmp) == SUCCESS) {
00873                      php_ini_activate_config(Z_ARRVAL_P(tmp), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE TSRMLS_CC);
00874               }
00875        }
00876 }
00877 /* }}} */
00878 
00879 /* {{{ cfg_get_entry
00880  */
00881 PHPAPI zval *cfg_get_entry(const char *name, uint name_length)
00882 {
00883        zval *tmp;
00884 
00885        if (zend_hash_find(&configuration_hash, name, name_length, (void **) &tmp) == SUCCESS) {
00886               return tmp;
00887        } else {
00888               return NULL;
00889        }
00890 }
00891 /* }}} */
00892 
00893 /* {{{ cfg_get_long
00894  */
00895 PHPAPI int cfg_get_long(const char *varname, long *result)
00896 {
00897        zval *tmp, var;
00898 
00899        if (zend_hash_find(&configuration_hash, varname, strlen(varname) + 1, (void **) &tmp) == FAILURE) {
00900               *result = 0;
00901               return FAILURE;
00902        }
00903        var = *tmp;
00904        zval_copy_ctor(&var);
00905        convert_to_long(&var);
00906        *result = Z_LVAL(var);
00907        return SUCCESS;
00908 }
00909 /* }}} */
00910 
00911 /* {{{ cfg_get_double
00912  */
00913 PHPAPI int cfg_get_double(const char *varname, double *result)
00914 {
00915        zval *tmp, var;
00916 
00917        if (zend_hash_find(&configuration_hash, varname, strlen(varname) + 1, (void **) &tmp) == FAILURE) {
00918               *result = (double) 0;
00919               return FAILURE;
00920        }
00921        var = *tmp;
00922        zval_copy_ctor(&var);
00923        convert_to_double(&var);
00924        *result = Z_DVAL(var);
00925        return SUCCESS;
00926 }
00927 /* }}} */
00928 
00929 /* {{{ cfg_get_string
00930  */
00931 PHPAPI int cfg_get_string(const char *varname, char **result)
00932 {
00933        zval *tmp;
00934 
00935        if (zend_hash_find(&configuration_hash, varname, strlen(varname)+1, (void **) &tmp) == FAILURE) {
00936               *result = NULL;
00937               return FAILURE;
00938        }
00939        *result = Z_STRVAL_P(tmp);
00940        return SUCCESS;
00941 }
00942 /* }}} */
00943 
00944 PHPAPI HashTable* php_ini_get_configuration_hash(void) /* {{{ */
00945 {
00946        return &configuration_hash;
00947 } /* }}} */
00948 
00949 /*
00950  * Local variables:
00951  * tab-width: 4
00952  * c-basic-offset: 4
00953  * indent-tabs-mode: t
00954  * End:
00955  * vim600: sw=4 ts=4 fdm=marker
00956  * vim<600: sw=4 ts=4
00957  */