Annotation of embedaddon/php/main/php_ini.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
                      5:    | Copyright (c) 1997-2012 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: Zeev Suraski <zeev@zend.com>                                 |
                     16:    +----------------------------------------------------------------------+
                     17:  */
                     18: 
1.1.1.2 ! misho      19: /* $Id$ */
1.1       misho      20: 
                     21: #include "php.h"
                     22: #include "ext/standard/info.h"
                     23: #include "zend_ini.h"
                     24: #include "zend_ini_scanner.h"
                     25: #include "php_ini.h"
                     26: #include "ext/standard/dl.h"
                     27: #include "zend_extensions.h"
                     28: #include "zend_highlight.h"
                     29: #include "SAPI.h"
                     30: #include "php_main.h"
                     31: #include "php_scandir.h"
                     32: #ifdef PHP_WIN32
                     33: #include "win32/php_registry.h"
                     34: #endif
                     35: 
                     36: #if HAVE_SCANDIR && HAVE_ALPHASORT && HAVE_DIRENT_H
                     37: #include <dirent.h>
                     38: #endif
                     39: 
                     40: #ifndef S_ISREG
                     41: #define S_ISREG(mode)   (((mode) & S_IFMT) == S_IFREG)
                     42: #endif
                     43: 
                     44: #ifdef PHP_WIN32
                     45: #define TRANSLATE_SLASHES_LOWER(path) \
                     46:        { \
                     47:                char *tmp = path; \
                     48:                while (*tmp) { \
                     49:                        if (*tmp == '\\') *tmp = '/'; \
                     50:                        else *tmp = tolower(*tmp); \
                     51:                                tmp++; \
                     52:                } \
                     53:        }
                     54: #else
                     55: #define TRANSLATE_SLASHES_LOWER(path)
                     56: #endif
                     57: 
                     58: 
                     59: typedef struct _php_extension_lists {
                     60:        zend_llist engine;
                     61:        zend_llist functions;
                     62: } php_extension_lists;
                     63: 
                     64: /* True globals */
                     65: static int is_special_section = 0;
                     66: static HashTable *active_ini_hash;
                     67: static HashTable configuration_hash;
                     68: static int has_per_dir_config = 0;
                     69: static int has_per_host_config = 0;
                     70: PHPAPI char *php_ini_opened_path=NULL;
                     71: static php_extension_lists extension_lists;
                     72: PHPAPI char *php_ini_scanned_path=NULL;
                     73: PHPAPI char *php_ini_scanned_files=NULL;
                     74: 
                     75: /* {{{ php_ini_displayer_cb
                     76:  */
                     77: static void php_ini_displayer_cb(zend_ini_entry *ini_entry, int type TSRMLS_DC)
                     78: {
                     79:        if (ini_entry->displayer) {
                     80:                ini_entry->displayer(ini_entry, type);
                     81:        } else {
                     82:                char *display_string;
                     83:                uint display_string_length, esc_html=0;
                     84: 
                     85:                if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
                     86:                        if (ini_entry->orig_value && ini_entry->orig_value[0]) {
                     87:                                display_string = ini_entry->orig_value;
                     88:                                display_string_length = ini_entry->orig_value_length;
                     89:                                esc_html = !sapi_module.phpinfo_as_text;
                     90:                        } else {
                     91:                                if (!sapi_module.phpinfo_as_text) {
                     92:                                        display_string = "<i>no value</i>";
                     93:                                        display_string_length = sizeof("<i>no value</i>") - 1;
                     94:                                } else {
                     95:                                        display_string = "no value";
                     96:                                        display_string_length = sizeof("no value") - 1;
                     97:                                }
                     98:                        }
                     99:                } else if (ini_entry->value && ini_entry->value[0]) {
                    100:                        display_string = ini_entry->value;
                    101:                        display_string_length = ini_entry->value_length;
                    102:                        esc_html = !sapi_module.phpinfo_as_text;
                    103:                } else {
                    104:                        if (!sapi_module.phpinfo_as_text) {
                    105:                                display_string = "<i>no value</i>";
                    106:                                display_string_length = sizeof("<i>no value</i>") - 1;
                    107:                        } else {
                    108:                                display_string = "no value";
                    109:                                display_string_length = sizeof("no value") - 1;
                    110:                        }
                    111:                }
                    112: 
                    113:                if (esc_html) {
                    114:                        php_html_puts(display_string, display_string_length TSRMLS_CC);
                    115:                } else {
                    116:                        PHPWRITE(display_string, display_string_length);
                    117:                }
                    118:        }
                    119: }
                    120: /* }}} */
                    121: 
                    122: /* {{{ php_ini_displayer
                    123:  */
                    124: static int php_ini_displayer(zend_ini_entry *ini_entry, int module_number TSRMLS_DC)
                    125: {
                    126:        if (ini_entry->module_number != module_number) {
                    127:                return 0;
                    128:        }
                    129:        if (!sapi_module.phpinfo_as_text) {
                    130:                PUTS("<tr>");
                    131:                PUTS("<td class=\"e\">");
                    132:                PHPWRITE(ini_entry->name, ini_entry->name_length - 1);
                    133:                PUTS("</td><td class=\"v\">");
                    134:                php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ACTIVE TSRMLS_CC);
                    135:                PUTS("</td><td class=\"v\">");
                    136:                php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ORIG TSRMLS_CC);
                    137:                PUTS("</td></tr>\n");
                    138:        } else {
                    139:                PHPWRITE(ini_entry->name, ini_entry->name_length - 1);
                    140:                PUTS(" => ");
                    141:                php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ACTIVE TSRMLS_CC);
                    142:                PUTS(" => ");
                    143:                php_ini_displayer_cb(ini_entry, ZEND_INI_DISPLAY_ORIG TSRMLS_CC);
                    144:                PUTS("\n");
                    145:        }
                    146:        return 0;
                    147: }
                    148: /* }}} */
                    149: 
                    150: /* {{{ php_ini_available
                    151:  */
                    152: static int php_ini_available(zend_ini_entry *ini_entry, int *module_number_available TSRMLS_DC)
                    153: {
                    154:        if (ini_entry->module_number == *module_number_available) {
                    155:                *module_number_available = -1;
                    156:                return ZEND_HASH_APPLY_STOP;
                    157:        } else {
                    158:                return ZEND_HASH_APPLY_KEEP;
                    159:        }
                    160: }
                    161: /* }}} */
                    162: 
                    163: /* {{{ display_ini_entries
                    164:  */
                    165: PHPAPI void display_ini_entries(zend_module_entry *module)
                    166: {
                    167:        int module_number, module_number_available;
                    168:        TSRMLS_FETCH();
                    169: 
                    170:        if (module) {
                    171:                module_number = module->module_number;
                    172:        } else {
                    173:                module_number = 0;
                    174:        }
                    175:        module_number_available = module_number;
                    176:        zend_hash_apply_with_argument(EG(ini_directives), (apply_func_arg_t) php_ini_available, &module_number_available TSRMLS_CC);
                    177:        if (module_number_available == -1) {
                    178:                php_info_print_table_start();
                    179:                php_info_print_table_header(3, "Directive", "Local Value", "Master Value");
                    180:                zend_hash_apply_with_argument(EG(ini_directives), (apply_func_arg_t) php_ini_displayer, (void *) (zend_intptr_t) module_number TSRMLS_CC);
                    181:                php_info_print_table_end();
                    182:        }
                    183: }
                    184: /* }}} */
                    185: 
                    186: /* php.ini support */
                    187: #define PHP_EXTENSION_TOKEN            "extension"
                    188: #define ZEND_EXTENSION_TOKEN   "zend_extension"
                    189: 
                    190: /* {{{ config_zval_dtor
                    191:  */
                    192: PHPAPI void config_zval_dtor(zval *zvalue)
                    193: {
                    194:        if (Z_TYPE_P(zvalue) == IS_ARRAY) {
                    195:                zend_hash_destroy(Z_ARRVAL_P(zvalue));
                    196:                free(Z_ARRVAL_P(zvalue));
                    197:        } else if (Z_TYPE_P(zvalue) == IS_STRING) {
                    198:                free(Z_STRVAL_P(zvalue));
                    199:        }
                    200: }
                    201: /* Reset / free active_ini_sectin global */
                    202: #define RESET_ACTIVE_INI_HASH() do { \
                    203:        active_ini_hash = NULL;          \
                    204:        is_special_section = 0;          \
                    205: } while (0)
                    206: /* }}} */
                    207: 
                    208: /* {{{ php_ini_parser_cb
                    209:  */
                    210: static void php_ini_parser_cb(zval *arg1, zval *arg2, zval *arg3, int callback_type, HashTable *target_hash)
                    211: {
                    212:        zval *entry;
                    213:        HashTable *active_hash;
                    214:        char *extension_name;
                    215: 
                    216:        if (active_ini_hash) {
                    217:                active_hash = active_ini_hash;
                    218:        } else {
                    219:                active_hash = target_hash;
                    220:        }
                    221: 
                    222:        switch (callback_type) {
                    223:                case ZEND_INI_PARSER_ENTRY: {
                    224:                                if (!arg2) {
                    225:                                        /* bare string - nothing to do */
                    226:                                        break;
                    227:                                }
                    228: 
                    229:                                /* PHP and Zend extensions are not added into configuration hash! */
                    230:                                if (!is_special_section && !strcasecmp(Z_STRVAL_P(arg1), PHP_EXTENSION_TOKEN)) { /* load PHP extension */
                    231:                                        extension_name = estrndup(Z_STRVAL_P(arg2), Z_STRLEN_P(arg2));
                    232:                                        zend_llist_add_element(&extension_lists.functions, &extension_name);
                    233:                                } else if (!is_special_section && !strcasecmp(Z_STRVAL_P(arg1), ZEND_EXTENSION_TOKEN)) { /* load Zend extension */
                    234:                                        extension_name = estrndup(Z_STRVAL_P(arg2), Z_STRLEN_P(arg2));
                    235:                                        zend_llist_add_element(&extension_lists.engine, &extension_name);
                    236: 
                    237:                                /* All other entries are added into either configuration_hash or active ini section array */
                    238:                                } else {
                    239:                                        /* Store in active hash */
                    240:                                        zend_hash_update(active_hash, Z_STRVAL_P(arg1), Z_STRLEN_P(arg1) + 1, arg2, sizeof(zval), (void **) &entry);
                    241:                                        Z_STRVAL_P(entry) = zend_strndup(Z_STRVAL_P(entry), Z_STRLEN_P(entry));
                    242:                                }
                    243:                        }
                    244:                        break;
                    245: 
                    246:                case ZEND_INI_PARSER_POP_ENTRY: {
                    247:                                zval *option_arr;
                    248:                                zval *find_arr;
                    249: 
                    250:                                if (!arg2) {
                    251:                                        /* bare string - nothing to do */
                    252:                                        break;
                    253:                                }
                    254: 
                    255: /* fprintf(stdout, "ZEND_INI_PARSER_POP_ENTRY: %s[%s] = %s\n",Z_STRVAL_P(arg1), Z_STRVAL_P(arg3), Z_STRVAL_P(arg2)); */
                    256: 
                    257:                                /* If option not found in hash or is not an array -> create array, otherwise add to existing array */
                    258:                                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) {
                    259:                                        option_arr = (zval *) pemalloc(sizeof(zval), 1);
                    260:                                        INIT_PZVAL(option_arr);
                    261:                                        Z_TYPE_P(option_arr) = IS_ARRAY;
                    262:                                        Z_ARRVAL_P(option_arr) = (HashTable *) pemalloc(sizeof(HashTable), 1);
                    263:                                        zend_hash_init(Z_ARRVAL_P(option_arr), 0, NULL, (dtor_func_t) config_zval_dtor, 1);
                    264:                                        zend_hash_update(active_hash, Z_STRVAL_P(arg1), Z_STRLEN_P(arg1) + 1, option_arr, sizeof(zval), (void **) &find_arr);
                    265:                                        free(option_arr);
                    266:                                }
                    267: 
                    268:                                /* arg3 is possible option offset name */
                    269:                                if (arg3 && Z_STRLEN_P(arg3) > 0) {
                    270:                                        zend_symtable_update(Z_ARRVAL_P(find_arr), Z_STRVAL_P(arg3), Z_STRLEN_P(arg3) + 1, arg2, sizeof(zval), (void **) &entry);
                    271:                                } else {
                    272:                                        zend_hash_next_index_insert(Z_ARRVAL_P(find_arr), arg2, sizeof(zval), (void **) &entry);
                    273:                                }
                    274:                                Z_STRVAL_P(entry) = zend_strndup(Z_STRVAL_P(entry), Z_STRLEN_P(entry));
                    275:                        }
                    276:                        break;
                    277: 
                    278:                case ZEND_INI_PARSER_SECTION: { /* Create an array of entries of each section */
                    279: 
                    280: /* fprintf(stdout, "ZEND_INI_PARSER_SECTION: %s\n",Z_STRVAL_P(arg1)); */
                    281: 
                    282:                                char *key = NULL;
                    283:                                uint key_len;
                    284: 
                    285:                                /* PATH sections */
                    286:                                if (!strncasecmp(Z_STRVAL_P(arg1), "PATH", sizeof("PATH") - 1)) {
                    287:                                        key = Z_STRVAL_P(arg1);
                    288:                                        key = key + sizeof("PATH") - 1;
                    289:                                        key_len = Z_STRLEN_P(arg1) - sizeof("PATH") + 1;
                    290:                                        is_special_section = 1;
                    291:                                        has_per_dir_config = 1;
                    292: 
                    293:                                        /* make the path lowercase on Windows, for case insensitivty. Does nothign for other platforms */
                    294:                                        TRANSLATE_SLASHES_LOWER(key);
                    295: 
                    296:                                /* HOST sections */
                    297:                                } else if (!strncasecmp(Z_STRVAL_P(arg1), "HOST", sizeof("HOST") - 1)) {
                    298:                                        key = Z_STRVAL_P(arg1);
                    299:                                        key = key + sizeof("HOST") - 1;
                    300:                                        key_len = Z_STRLEN_P(arg1) - sizeof("HOST") + 1;
                    301:                                        is_special_section = 1;
                    302:                                        has_per_host_config = 1;
                    303:                                        zend_str_tolower(key, key_len); /* host names are case-insensitive. */
                    304: 
                    305:                                } else {
                    306:                                        is_special_section = 0;
                    307:                                }
                    308: 
                    309:                                if (key && key_len > 0) {
                    310:                                        /* Strip any trailing slashes */
                    311:                                        while (key_len > 0 && (key[key_len - 1] == '/' || key[key_len - 1] == '\\')) {
                    312:                                                key_len--;
                    313:                                                key[key_len] = 0;
                    314:                                        }
                    315: 
                    316:                                        /* Strip any leading whitespace and '=' */
                    317:                                        while (*key && (
                    318:                                                *key == '=' ||
                    319:                                                *key == ' ' ||
                    320:                                                *key == '\t'
                    321:                                        )) {
                    322:                                                key++;
                    323:                                                key_len--;
                    324:                                        }
                    325: 
                    326:                                        /* Search for existing entry and if it does not exist create one */
                    327:                                        if (zend_hash_find(target_hash, key, key_len + 1, (void **) &entry) == FAILURE) {
                    328:                                                zval *section_arr;
                    329: 
                    330:                                                section_arr = (zval *) pemalloc(sizeof(zval), 1);
                    331:                                                INIT_PZVAL(section_arr);
                    332:                                                Z_TYPE_P(section_arr) = IS_ARRAY;
                    333:                                                Z_ARRVAL_P(section_arr) = (HashTable *) pemalloc(sizeof(HashTable), 1);
                    334:                                                zend_hash_init(Z_ARRVAL_P(section_arr), 0, NULL, (dtor_func_t) config_zval_dtor, 1);
                    335:                                                zend_hash_update(target_hash, key, key_len + 1, section_arr, sizeof(zval), (void **) &entry);
                    336:                                                free(section_arr);
                    337:                                        }
                    338:                                        active_ini_hash = Z_ARRVAL_P(entry);
                    339:                                }
                    340:                        }
                    341:                        break;
                    342:        }
                    343: }
                    344: /* }}} */
                    345: 
                    346: /* {{{ php_load_php_extension_cb
                    347:  */
                    348: static void php_load_php_extension_cb(void *arg TSRMLS_DC)
                    349: {
                    350: #ifdef HAVE_LIBDL
                    351:        php_load_extension(*((char **) arg), MODULE_PERSISTENT, 0 TSRMLS_CC);
                    352: #endif
                    353: }
                    354: /* }}} */
                    355: 
                    356: /* {{{ php_load_zend_extension_cb
                    357:  */
                    358: static void php_load_zend_extension_cb(void *arg TSRMLS_DC)
                    359: {
                    360:        zend_load_extension(*((char **) arg));
                    361: }
                    362: /* }}} */
                    363: 
                    364: /* {{{ php_init_config
                    365:  */
                    366: int php_init_config(TSRMLS_D)
                    367: {
                    368:        char *php_ini_file_name = NULL;
                    369:        char *php_ini_search_path = NULL;
                    370:        int php_ini_scanned_path_len;
                    371:        char *open_basedir;
                    372:        int free_ini_search_path = 0;
                    373:        zend_file_handle fh;
                    374: 
                    375:        if (zend_hash_init(&configuration_hash, 0, NULL, (dtor_func_t) config_zval_dtor, 1) == FAILURE) {
                    376:                return FAILURE;
                    377:        }
                    378: 
                    379:        if (sapi_module.ini_defaults) {
                    380:                sapi_module.ini_defaults(&configuration_hash);
                    381:        }
                    382: 
                    383:        zend_llist_init(&extension_lists.engine, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
                    384:        zend_llist_init(&extension_lists.functions, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
                    385: 
                    386:        open_basedir = PG(open_basedir);
                    387: 
                    388:        if (sapi_module.php_ini_path_override) {
                    389:                php_ini_file_name = sapi_module.php_ini_path_override;
                    390:                php_ini_search_path = sapi_module.php_ini_path_override;
                    391:                free_ini_search_path = 0;
                    392:        } else if (!sapi_module.php_ini_ignore) {
                    393:                int search_path_size;
                    394:                char *default_location;
                    395:                char *env_location;
                    396:                static const char paths_separator[] = { ZEND_PATHS_SEPARATOR, 0 };
                    397: #ifdef PHP_WIN32
                    398:                char *reg_location;
                    399:                char phprc_path[MAXPATHLEN];
                    400: #endif
                    401: 
                    402:                env_location = getenv("PHPRC");
                    403: 
                    404: #ifdef PHP_WIN32
                    405:                if (!env_location) {
                    406:                        char dummybuf;
                    407:                        int size;
                    408: 
                    409:                        SetLastError(0);
                    410: 
                    411:                        /*If the given bugger is not large enough to hold the data, the return value is 
                    412:                        the buffer size,  in characters, required to hold the string and its terminating 
                    413:                        null character. We use this return value to alloc the final buffer. */
                    414:                        size = GetEnvironmentVariableA("PHPRC", &dummybuf, 0);
                    415:                        if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
                    416:                                /* The environment variable doesn't exist. */
                    417:                                env_location = "";
                    418:                        } else {
                    419:                                if (size == 0) {
                    420:                                        env_location = "";
                    421:                                } else {
                    422:                                        size = GetEnvironmentVariableA("PHPRC", phprc_path, size);
1.1.1.2 ! misho     423:                                        if (size == 0) {
        !           424:                                                env_location = "";
        !           425:                                        } else {
        !           426:                                                env_location = phprc_path;
        !           427:                                        }
1.1       misho     428:                                }
                    429:                        }
                    430:                }
                    431: #else
                    432:                if (!env_location) {
                    433:                        env_location = "";
                    434:                }
                    435: #endif
                    436:                /*
                    437:                 * Prepare search path
                    438:                 */
                    439: 
                    440:                search_path_size = MAXPATHLEN * 4 + strlen(env_location) + 3 + 1;
                    441:                php_ini_search_path = (char *) emalloc(search_path_size);
                    442:                free_ini_search_path = 1;
                    443:                php_ini_search_path[0] = 0;
                    444: 
                    445:                /* Add environment location */
                    446:                if (env_location[0]) {
                    447:                        if (*php_ini_search_path) {
                    448:                                strlcat(php_ini_search_path, paths_separator, search_path_size);
                    449:                        }
                    450:                        strlcat(php_ini_search_path, env_location, search_path_size);
                    451:                        php_ini_file_name = env_location;
                    452:                }
                    453: 
                    454: #ifdef PHP_WIN32
                    455:                /* Add registry location */
                    456:                reg_location = GetIniPathFromRegistry();
                    457:                if (reg_location != NULL) {
                    458:                        if (*php_ini_search_path) {
                    459:                                strlcat(php_ini_search_path, paths_separator, search_path_size);
                    460:                        }
                    461:                        strlcat(php_ini_search_path, reg_location, search_path_size);
                    462:                        efree(reg_location);
                    463:                }
                    464: #endif
                    465: 
                    466:                /* Add cwd (not with CLI) */
1.1.1.2 ! misho     467:                if (!sapi_module.php_ini_ignore_cwd) {
1.1       misho     468:                        if (*php_ini_search_path) {
                    469:                                strlcat(php_ini_search_path, paths_separator, search_path_size);
                    470:                        }
                    471:                        strlcat(php_ini_search_path, ".", search_path_size);
                    472:                }
                    473: 
1.1.1.2 ! misho     474:                if (PG(php_binary)) {
        !           475:                        char *separator_location, *binary_location;
        !           476: 
        !           477:                        binary_location = estrdup(PG(php_binary));
        !           478:                        separator_location = strrchr(binary_location, DEFAULT_SLASH);
1.1       misho     479: 
                    480:                        if (separator_location && separator_location != binary_location) {
                    481:                                *(separator_location) = 0;
                    482:                        }
                    483:                        if (*php_ini_search_path) {
                    484:                                strlcat(php_ini_search_path, paths_separator, search_path_size);
                    485:                        }
                    486:                        strlcat(php_ini_search_path, binary_location, search_path_size);
                    487:                        efree(binary_location);
                    488:                }
                    489: 
                    490:                /* Add default location */
                    491: #ifdef PHP_WIN32
                    492:                default_location = (char *) emalloc(MAXPATHLEN + 1);
                    493: 
                    494:                if (0 < GetWindowsDirectory(default_location, MAXPATHLEN)) {
                    495:                        if (*php_ini_search_path) {
                    496:                                strlcat(php_ini_search_path, paths_separator, search_path_size);
                    497:                        }
                    498:                        strlcat(php_ini_search_path, default_location, search_path_size);
                    499:                }
                    500: 
                    501:                /* For people running under terminal services, GetWindowsDirectory will
                    502:                 * return their personal Windows directory, so lets add the system
                    503:                 * windows directory too */
                    504:                if (0 < GetSystemWindowsDirectory(default_location, MAXPATHLEN)) {
                    505:                        if (*php_ini_search_path) {
                    506:                                strlcat(php_ini_search_path, paths_separator, search_path_size);
                    507:                        }
                    508:                        strlcat(php_ini_search_path, default_location, search_path_size);
                    509:                }
                    510:                efree(default_location);
                    511: 
                    512: #else
                    513:                default_location = PHP_CONFIG_FILE_PATH;
                    514:                if (*php_ini_search_path) {
                    515:                        strlcat(php_ini_search_path, paths_separator, search_path_size);
                    516:                }
                    517:                strlcat(php_ini_search_path, default_location, search_path_size);
                    518: #endif
                    519:        }
                    520: 
                    521:        PG(open_basedir) = NULL;
                    522: 
                    523:        /*
                    524:         * Find and open actual ini file
                    525:         */
                    526: 
                    527:        memset(&fh, 0, sizeof(fh));
                    528: 
                    529:        /* If SAPI does not want to ignore all ini files OR an overriding file/path is given.
                    530:         * This allows disabling scanning for ini files in the PHP_CONFIG_FILE_SCAN_DIR but still
                    531:         * load an optional ini file. */
                    532:        if (!sapi_module.php_ini_ignore || sapi_module.php_ini_path_override) {
                    533: 
                    534:                /* Check if php_ini_file_name is a file and can be opened */
                    535:                if (php_ini_file_name && php_ini_file_name[0]) {
                    536:                        struct stat statbuf;
                    537: 
                    538:                        if (!VCWD_STAT(php_ini_file_name, &statbuf)) {
                    539:                                if (!((statbuf.st_mode & S_IFMT) == S_IFDIR)) {
                    540:                                        fh.handle.fp = VCWD_FOPEN(php_ini_file_name, "r");
                    541:                                        if (fh.handle.fp) {
                    542:                                                fh.filename = php_ini_opened_path = expand_filepath(php_ini_file_name, NULL TSRMLS_CC);
                    543:                                        }
                    544:                                }
                    545:                        }
                    546:                }
                    547: 
                    548:                /* Otherwise search for php-%sapi-module-name%.ini file in search path */
                    549:                if (!fh.handle.fp) {
                    550:                        const char *fmt = "php-%s.ini";
                    551:                        char *ini_fname;
                    552:                        spprintf(&ini_fname, 0, fmt, sapi_module.name);
                    553:                        fh.handle.fp = php_fopen_with_path(ini_fname, "r", php_ini_search_path, &php_ini_opened_path TSRMLS_CC);
                    554:                        efree(ini_fname);
                    555:                        if (fh.handle.fp) {
                    556:                                fh.filename = php_ini_opened_path;
                    557:                        }
                    558:                }
                    559: 
                    560:                /* If still no ini file found, search for php.ini file in search path */
                    561:                if (!fh.handle.fp) {
                    562:                        fh.handle.fp = php_fopen_with_path("php.ini", "r", php_ini_search_path, &php_ini_opened_path TSRMLS_CC);
                    563:                        if (fh.handle.fp) {
                    564:                                fh.filename = php_ini_opened_path;
                    565:                        }
                    566:                }
                    567:        }
                    568: 
                    569:        if (free_ini_search_path) {
                    570:                efree(php_ini_search_path);
                    571:        }
                    572: 
                    573:        PG(open_basedir) = open_basedir;
                    574: 
                    575:        if (fh.handle.fp) {
                    576:                fh.type = ZEND_HANDLE_FP;
                    577:                RESET_ACTIVE_INI_HASH();
                    578: 
                    579:                zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash TSRMLS_CC);
                    580: 
                    581:                {
                    582:                        zval tmp;
                    583: 
                    584:                        Z_STRLEN(tmp) = strlen(fh.filename);
                    585:                        Z_STRVAL(tmp) = zend_strndup(fh.filename, Z_STRLEN(tmp));
                    586:                        Z_TYPE(tmp) = IS_STRING;
                    587:                        Z_SET_REFCOUNT(tmp, 0);
                    588: 
                    589:                        zend_hash_update(&configuration_hash, "cfg_file_path", sizeof("cfg_file_path"), (void *) &tmp, sizeof(zval), NULL);
                    590:                        if (php_ini_opened_path) {
                    591:                                efree(php_ini_opened_path);
                    592:                        }
                    593:                        php_ini_opened_path = zend_strndup(Z_STRVAL(tmp), Z_STRLEN(tmp));
                    594:                }
                    595:        }
                    596: 
                    597:        /* Check for PHP_INI_SCAN_DIR environment variable to override/set config file scan directory */
                    598:        php_ini_scanned_path = getenv("PHP_INI_SCAN_DIR");
                    599:        if (!php_ini_scanned_path) {
                    600:                /* Or fall back using possible --with-config-file-scan-dir setting (defaults to empty string!) */
                    601:                php_ini_scanned_path = PHP_CONFIG_FILE_SCAN_DIR;
                    602:        }
                    603:        php_ini_scanned_path_len = strlen(php_ini_scanned_path);
                    604: 
                    605:        /* Scan and parse any .ini files found in scan path if path not empty. */
                    606:        if (!sapi_module.php_ini_ignore && php_ini_scanned_path_len) {
                    607:                struct dirent **namelist;
                    608:                int ndir, i;
                    609:                struct stat sb;
                    610:                char ini_file[MAXPATHLEN];
                    611:                char *p;
                    612:                zend_file_handle fh2;
                    613:                zend_llist scanned_ini_list;
                    614:                zend_llist_element *element;
                    615:                int l, total_l = 0;
                    616: 
                    617:                if ((ndir = php_scandir(php_ini_scanned_path, &namelist, 0, php_alphasort)) > 0) {
                    618:                        zend_llist_init(&scanned_ini_list, sizeof(char *), (llist_dtor_func_t) free_estring, 1);
                    619:                        memset(&fh2, 0, sizeof(fh2));
                    620: 
                    621:                        for (i = 0; i < ndir; i++) {
                    622: 
                    623:                                /* check for any file with .ini extension */
                    624:                                if (!(p = strrchr(namelist[i]->d_name, '.')) || (p && strcmp(p, ".ini"))) {
                    625:                                        free(namelist[i]);
                    626:                                        continue;
                    627:                                }
                    628:                                /* Reset active ini section */
                    629:                                RESET_ACTIVE_INI_HASH();
                    630: 
                    631:                                if (IS_SLASH(php_ini_scanned_path[php_ini_scanned_path_len - 1])) {
                    632:                                        snprintf(ini_file, MAXPATHLEN, "%s%s", php_ini_scanned_path, namelist[i]->d_name);
                    633:                                } else {
                    634:                                        snprintf(ini_file, MAXPATHLEN, "%s%c%s", php_ini_scanned_path, DEFAULT_SLASH, namelist[i]->d_name);
                    635:                                }
                    636:                                if (VCWD_STAT(ini_file, &sb) == 0) {
                    637:                                        if (S_ISREG(sb.st_mode)) {
                    638:                                                if ((fh2.handle.fp = VCWD_FOPEN(ini_file, "r"))) {
                    639:                                                        fh2.filename = ini_file;
                    640:                                                        fh2.type = ZEND_HANDLE_FP;
                    641: 
                    642:                                                        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) {
                    643:                                                                /* Here, add it to the list of ini files read */
                    644:                                                                l = strlen(ini_file);
                    645:                                                                total_l += l + 2;
                    646:                                                                p = estrndup(ini_file, l);
                    647:                                                                zend_llist_add_element(&scanned_ini_list, &p);
                    648:                                                        }
                    649:                                                }
                    650:                                        }
                    651:                                }
                    652:                                free(namelist[i]);
                    653:                        }
                    654:                        free(namelist);
                    655: 
                    656:                        if (total_l) {
                    657:                                int php_ini_scanned_files_len = (php_ini_scanned_files) ? strlen(php_ini_scanned_files) + 1 : 0;
                    658:                                php_ini_scanned_files = (char *) realloc(php_ini_scanned_files, php_ini_scanned_files_len + total_l + 1);
                    659:                                if (!php_ini_scanned_files_len) {
                    660:                                        *php_ini_scanned_files = '\0';
                    661:                                }
                    662:                                total_l += php_ini_scanned_files_len;
                    663:                                for (element = scanned_ini_list.head; element; element = element->next) {
                    664:                                        if (php_ini_scanned_files_len) {
                    665:                                                strlcat(php_ini_scanned_files, ",\n", total_l);
                    666:                                        }
                    667:                                        strlcat(php_ini_scanned_files, *(char **)element->data, total_l);
                    668:                                        strlcat(php_ini_scanned_files, element->next ? ",\n" : "\n", total_l);
                    669:                                }
                    670:                        }
                    671:                        zend_llist_destroy(&scanned_ini_list);
                    672:                }
                    673:        } else {
                    674:                /* Make sure an empty php_ini_scanned_path ends up as NULL */
                    675:                php_ini_scanned_path = NULL;
                    676:        }
                    677: 
                    678:        if (sapi_module.ini_entries) {
                    679:                /* Reset active ini section */
                    680:                RESET_ACTIVE_INI_HASH();
                    681:                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);
                    682:        }
                    683: 
                    684:        return SUCCESS;
                    685: }
                    686: /* }}} */
                    687: 
                    688: /* {{{ php_shutdown_config
                    689:  */
                    690: int php_shutdown_config(void)
                    691: {
                    692:        zend_hash_destroy(&configuration_hash);
                    693:        if (php_ini_opened_path) {
                    694:                free(php_ini_opened_path);
                    695:                php_ini_opened_path = NULL;
                    696:        }
                    697:        if (php_ini_scanned_files) {
                    698:                free(php_ini_scanned_files);
                    699:                php_ini_scanned_files = NULL;
                    700:        }
                    701:        return SUCCESS;
                    702: }
                    703: /* }}} */
                    704: 
                    705: /* {{{ php_ini_register_extensions
                    706:  */
                    707: void php_ini_register_extensions(TSRMLS_D)
                    708: {
                    709:        zend_llist_apply(&extension_lists.engine, php_load_zend_extension_cb TSRMLS_CC);
                    710:        zend_llist_apply(&extension_lists.functions, php_load_php_extension_cb TSRMLS_CC);
                    711: 
                    712:        zend_llist_destroy(&extension_lists.engine);
                    713:        zend_llist_destroy(&extension_lists.functions);
                    714: }
                    715: /* }}} */
                    716: 
                    717: /* {{{ php_parse_user_ini_file
                    718:  */
                    719: PHPAPI int php_parse_user_ini_file(const char *dirname, char *ini_filename, HashTable *target_hash TSRMLS_DC)
                    720: {
                    721:        struct stat sb;
                    722:        char ini_file[MAXPATHLEN];
                    723:        zend_file_handle fh;
                    724: 
                    725:        snprintf(ini_file, MAXPATHLEN, "%s%c%s", dirname, DEFAULT_SLASH, ini_filename);
                    726: 
                    727:        if (VCWD_STAT(ini_file, &sb) == 0) {
                    728:                if (S_ISREG(sb.st_mode)) {
                    729:                        memset(&fh, 0, sizeof(fh));
                    730:                        if ((fh.handle.fp = VCWD_FOPEN(ini_file, "r"))) {
                    731:                                fh.filename = ini_file;
                    732:                                fh.type = ZEND_HANDLE_FP;
                    733: 
                    734:                                /* Reset active ini section */
                    735:                                RESET_ACTIVE_INI_HASH();
                    736: 
                    737:                                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) {
                    738:                                        /* FIXME: Add parsed file to the list of user files read? */
                    739:                                        return SUCCESS;
                    740:                                }
                    741:                                return FAILURE;
                    742:                        }
                    743:                }
                    744:        }
                    745:        return FAILURE;
                    746: }
                    747: /* }}} */
                    748: 
                    749: /* {{{ php_ini_activate_config
                    750:  */
                    751: PHPAPI void php_ini_activate_config(HashTable *source_hash, int modify_type, int stage TSRMLS_DC)
                    752: {
                    753:        char *str;
                    754:        zval *data;
                    755:        uint str_len;
                    756:        ulong num_index;
                    757: 
                    758:        /* Walk through config hash and alter matching ini entries using the values found in the hash */
                    759:        for (zend_hash_internal_pointer_reset(source_hash);
                    760:                zend_hash_get_current_key_ex(source_hash, &str, &str_len, &num_index, 0, NULL) == HASH_KEY_IS_STRING;
                    761:                zend_hash_move_forward(source_hash)
                    762:        ) {
                    763:                zend_hash_get_current_data(source_hash, (void **) &data);
                    764:                zend_alter_ini_entry_ex(str, str_len, Z_STRVAL_P(data), Z_STRLEN_P(data), modify_type, stage, 0 TSRMLS_CC);
                    765:        }
                    766: }
                    767: /* }}} */
                    768: 
                    769: /* {{{ php_ini_has_per_dir_config
                    770:  */
                    771: PHPAPI int php_ini_has_per_dir_config(void)
                    772: {
                    773:        return has_per_dir_config;
                    774: }
                    775: /* }}} */
                    776: 
                    777: /* {{{ php_ini_activate_per_dir_config
                    778:  */
                    779: PHPAPI void php_ini_activate_per_dir_config(char *path, uint path_len TSRMLS_DC)
                    780: {
                    781:        zval *tmp2;
                    782:        char *ptr;
                    783: 
                    784: #if PHP_WIN32
                    785:        char path_bak[MAXPATHLEN];
                    786: #endif
                    787: 
                    788:        if (path_len > MAXPATHLEN) {
                    789:                return;
                    790:        }
                    791: 
                    792: #if PHP_WIN32
                    793:        memcpy(path_bak, path, path_len);
                    794:        path_bak[path_len] = 0;
                    795:        TRANSLATE_SLASHES_LOWER(path_bak);
                    796:        path = path_bak;
                    797: #endif
                    798: 
                    799:        /* Walk through each directory in path and apply any found per-dir-system-configuration from configuration_hash */
                    800:        if (has_per_dir_config && path && path_len) {
                    801:                ptr = path + 1;
                    802:                while ((ptr = strchr(ptr, '/')) != NULL) {
                    803:                        *ptr = 0;
                    804:                        /* Search for source array matching the path from configuration_hash */
                    805:                        if (zend_hash_find(&configuration_hash, path, strlen(path) + 1, (void **) &tmp2) == SUCCESS) {
                    806:                                php_ini_activate_config(Z_ARRVAL_P(tmp2), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE TSRMLS_CC);
                    807:                        }
                    808:                        *ptr = '/';
                    809:                        ptr++;
                    810:                }
                    811:        }
                    812: }
                    813: /* }}} */
                    814: 
                    815: /* {{{ php_ini_has_per_host_config
                    816:  */
                    817: PHPAPI int php_ini_has_per_host_config(void)
                    818: {
                    819:        return has_per_host_config;
                    820: }
                    821: /* }}} */
                    822: 
                    823: /* {{{ php_ini_activate_per_host_config
                    824:  */
                    825: PHPAPI void php_ini_activate_per_host_config(const char *host, uint host_len TSRMLS_DC)
                    826: {
                    827:        zval *tmp;
                    828: 
                    829:        if (has_per_host_config && host && host_len) {
                    830:                /* Search for source array matching the host from configuration_hash */
                    831:                if (zend_hash_find(&configuration_hash, host, host_len, (void **) &tmp) == SUCCESS) {
                    832:                        php_ini_activate_config(Z_ARRVAL_P(tmp), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE TSRMLS_CC);
                    833:                }
                    834:        }
                    835: }
                    836: /* }}} */
                    837: 
                    838: /* {{{ cfg_get_entry
                    839:  */
                    840: PHPAPI zval *cfg_get_entry(const char *name, uint name_length)
                    841: {
                    842:        zval *tmp;
                    843: 
                    844:        if (zend_hash_find(&configuration_hash, name, name_length, (void **) &tmp) == SUCCESS) {
                    845:                return tmp;
                    846:        } else {
                    847:                return NULL;
                    848:        }
                    849: }
                    850: /* }}} */
                    851: 
                    852: /* {{{ cfg_get_long
                    853:  */
                    854: PHPAPI int cfg_get_long(const char *varname, long *result)
                    855: {
                    856:        zval *tmp, var;
                    857: 
                    858:        if (zend_hash_find(&configuration_hash, varname, strlen(varname) + 1, (void **) &tmp) == FAILURE) {
                    859:                *result = 0;
                    860:                return FAILURE;
                    861:        }
                    862:        var = *tmp;
                    863:        zval_copy_ctor(&var);
                    864:        convert_to_long(&var);
                    865:        *result = Z_LVAL(var);
                    866:        return SUCCESS;
                    867: }
                    868: /* }}} */
                    869: 
                    870: /* {{{ cfg_get_double
                    871:  */
                    872: PHPAPI int cfg_get_double(const char *varname, double *result)
                    873: {
                    874:        zval *tmp, var;
                    875: 
                    876:        if (zend_hash_find(&configuration_hash, varname, strlen(varname) + 1, (void **) &tmp) == FAILURE) {
                    877:                *result = (double) 0;
                    878:                return FAILURE;
                    879:        }
                    880:        var = *tmp;
                    881:        zval_copy_ctor(&var);
                    882:        convert_to_double(&var);
                    883:        *result = Z_DVAL(var);
                    884:        return SUCCESS;
                    885: }
                    886: /* }}} */
                    887: 
                    888: /* {{{ cfg_get_string
                    889:  */
                    890: PHPAPI int cfg_get_string(const char *varname, char **result)
                    891: {
                    892:        zval *tmp;
                    893: 
                    894:        if (zend_hash_find(&configuration_hash, varname, strlen(varname)+1, (void **) &tmp) == FAILURE) {
                    895:                *result = NULL;
                    896:                return FAILURE;
                    897:        }
                    898:        *result = Z_STRVAL_P(tmp);
                    899:        return SUCCESS;
                    900: }
                    901: /* }}} */
                    902: 
                    903: PHPAPI HashTable* php_ini_get_configuration_hash(void) /* {{{ */
                    904: {
                    905:        return &configuration_hash;
                    906: } /* }}} */
                    907: 
                    908: /*
                    909:  * Local variables:
                    910:  * tab-width: 4
                    911:  * c-basic-offset: 4
                    912:  * indent-tabs-mode: t
                    913:  * End:
                    914:  * vim600: sw=4 ts=4 fdm=marker
                    915:  * vim<600: sw=4 ts=4
                    916:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>