123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672 |
- /*
- +----------------------------------------------------------------------+
- | Zend Engine |
- +----------------------------------------------------------------------+
- | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
- +----------------------------------------------------------------------+
- | This source file is subject to version 2.00 of the Zend license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.zend.com/license/2_00.txt. |
- | If you did not receive a copy of the Zend license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@zend.com so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Author: Zeev Suraski <zeev@php.net> |
- +----------------------------------------------------------------------+
- */
- #include "zend.h"
- #include "zend_sort.h"
- #include "zend_API.h"
- #include "zend_ini.h"
- #include "zend_alloc.h"
- #include "zend_operators.h"
- #include "zend_strtod.h"
- #include "zend_modules.h"
- static HashTable *registered_zend_ini_directives;
- #define NO_VALUE_PLAINTEXT "no value"
- #define NO_VALUE_HTML "<i>no value</i>"
- /*
- * hash_apply functions
- */
- static int zend_remove_ini_entries(zval *el, void *arg) /* {{{ */
- {
- zend_ini_entry *ini_entry = (zend_ini_entry *)Z_PTR_P(el);
- int module_number = *(int *)arg;
- return ini_entry->module_number == module_number;
- }
- /* }}} */
- static zend_result zend_restore_ini_entry_cb(zend_ini_entry *ini_entry, int stage) /* {{{ */
- {
- zend_result result = FAILURE;
- if (ini_entry->modified) {
- if (ini_entry->on_modify) {
- zend_try {
- /* even if on_modify bails out, we have to continue on with restoring,
- since there can be allocated variables that would be freed on MM shutdown
- and would lead to memory corruption later ini entry is modified again */
- result = ini_entry->on_modify(ini_entry, ini_entry->orig_value, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage);
- } zend_end_try();
- }
- if (stage == ZEND_INI_STAGE_RUNTIME && result == FAILURE) {
- /* runtime failure is OK */
- return 1;
- }
- if (ini_entry->value != ini_entry->orig_value) {
- zend_string_release(ini_entry->value);
- }
- ini_entry->value = ini_entry->orig_value;
- ini_entry->modifiable = ini_entry->orig_modifiable;
- ini_entry->modified = 0;
- ini_entry->orig_value = NULL;
- ini_entry->orig_modifiable = 0;
- }
- return 0;
- }
- /* }}} */
- static void free_ini_entry(zval *zv) /* {{{ */
- {
- zend_ini_entry *entry = (zend_ini_entry*)Z_PTR_P(zv);
- zend_string_release_ex(entry->name, 1);
- if (entry->value) {
- zend_string_release(entry->value);
- }
- if (entry->orig_value) {
- zend_string_release_ex(entry->orig_value, 1);
- }
- free(entry);
- }
- /* }}} */
- /*
- * Startup / shutdown
- */
- ZEND_API void zend_ini_startup(void) /* {{{ */
- {
- registered_zend_ini_directives = (HashTable *) malloc(sizeof(HashTable));
- EG(ini_directives) = registered_zend_ini_directives;
- EG(modified_ini_directives) = NULL;
- EG(error_reporting_ini_entry) = NULL;
- zend_hash_init(registered_zend_ini_directives, 128, NULL, free_ini_entry, 1);
- }
- /* }}} */
- ZEND_API void zend_ini_shutdown(void) /* {{{ */
- {
- zend_ini_dtor(EG(ini_directives));
- }
- /* }}} */
- ZEND_API void zend_ini_dtor(HashTable *ini_directives) /* {{{ */
- {
- zend_hash_destroy(ini_directives);
- free(ini_directives);
- }
- /* }}} */
- ZEND_API void zend_ini_global_shutdown(void) /* {{{ */
- {
- zend_hash_destroy(registered_zend_ini_directives);
- free(registered_zend_ini_directives);
- }
- /* }}} */
- ZEND_API void zend_ini_deactivate(void) /* {{{ */
- {
- if (EG(modified_ini_directives)) {
- zend_ini_entry *ini_entry;
- ZEND_HASH_FOREACH_PTR(EG(modified_ini_directives), ini_entry) {
- zend_restore_ini_entry_cb(ini_entry, ZEND_INI_STAGE_DEACTIVATE);
- } ZEND_HASH_FOREACH_END();
- zend_hash_destroy(EG(modified_ini_directives));
- FREE_HASHTABLE(EG(modified_ini_directives));
- EG(modified_ini_directives) = NULL;
- }
- }
- /* }}} */
- #ifdef ZTS
- static void copy_ini_entry(zval *zv) /* {{{ */
- {
- zend_ini_entry *old_entry = (zend_ini_entry*)Z_PTR_P(zv);
- zend_ini_entry *new_entry = pemalloc(sizeof(zend_ini_entry), 1);
- Z_PTR_P(zv) = new_entry;
- memcpy(new_entry, old_entry, sizeof(zend_ini_entry));
- if (old_entry->name) {
- new_entry->name = zend_string_dup(old_entry->name, 1);
- }
- if (old_entry->value) {
- new_entry->value = zend_string_dup(old_entry->value, 1);
- }
- if (old_entry->orig_value) {
- new_entry->orig_value = zend_string_dup(old_entry->orig_value, 1);
- }
- }
- /* }}} */
- ZEND_API void zend_copy_ini_directives(void) /* {{{ */
- {
- EG(modified_ini_directives) = NULL;
- EG(error_reporting_ini_entry) = NULL;
- EG(ini_directives) = (HashTable *) malloc(sizeof(HashTable));
- zend_hash_init(EG(ini_directives), registered_zend_ini_directives->nNumOfElements, NULL, free_ini_entry, 1);
- zend_hash_copy(EG(ini_directives), registered_zend_ini_directives, copy_ini_entry);
- }
- /* }}} */
- #endif
- static int ini_key_compare(Bucket *f, Bucket *s) /* {{{ */
- {
- if (!f->key && !s->key) { /* both numeric */
- if (f->h > s->h) {
- return -1;
- } else if (f->h < s->h) {
- return 1;
- }
- return 0;
- } else if (!f->key) { /* f is numeric, s is not */
- return -1;
- } else if (!s->key) { /* s is numeric, f is not */
- return 1;
- } else { /* both strings */
- return zend_binary_strcasecmp(ZSTR_VAL(f->key), ZSTR_LEN(f->key), ZSTR_VAL(s->key), ZSTR_LEN(s->key));
- }
- }
- /* }}} */
- ZEND_API void zend_ini_sort_entries(void) /* {{{ */
- {
- zend_hash_sort(EG(ini_directives), ini_key_compare, 0);
- }
- /* }}} */
- /*
- * Registration / unregistration
- */
- ZEND_API zend_result zend_register_ini_entries_ex(const zend_ini_entry_def *ini_entry, int module_number, int module_type) /* {{{ */
- {
- zend_ini_entry *p;
- zval *default_value;
- HashTable *directives = registered_zend_ini_directives;
- #ifdef ZTS
- /* if we are called during the request, eg: from dl(),
- * then we should not touch the global directives table,
- * and should update the per-(request|thread) version instead.
- * This solves two problems: one is that ini entries for dl()'d
- * extensions will now work, and the second is that updating the
- * global hash here from dl() is not mutex protected and can
- * lead to death.
- */
- if (directives != EG(ini_directives)) {
- ZEND_ASSERT(module_type == MODULE_TEMPORARY);
- directives = EG(ini_directives);
- } else {
- ZEND_ASSERT(module_type == MODULE_PERSISTENT);
- }
- #endif
- while (ini_entry->name) {
- p = pemalloc(sizeof(zend_ini_entry), 1);
- p->name = zend_string_init_interned(ini_entry->name, ini_entry->name_length, 1);
- p->on_modify = ini_entry->on_modify;
- p->mh_arg1 = ini_entry->mh_arg1;
- p->mh_arg2 = ini_entry->mh_arg2;
- p->mh_arg3 = ini_entry->mh_arg3;
- p->value = NULL;
- p->orig_value = NULL;
- p->displayer = ini_entry->displayer;
- p->modifiable = ini_entry->modifiable;
- p->orig_modifiable = 0;
- p->modified = 0;
- p->module_number = module_number;
- if (zend_hash_add_ptr(directives, p->name, (void*)p) == NULL) {
- if (p->name) {
- zend_string_release_ex(p->name, 1);
- }
- zend_unregister_ini_entries_ex(module_number, module_type);
- return FAILURE;
- }
- if (((default_value = zend_get_configuration_directive(p->name)) != NULL) &&
- (!p->on_modify || p->on_modify(p, Z_STR_P(default_value), p->mh_arg1, p->mh_arg2, p->mh_arg3, ZEND_INI_STAGE_STARTUP) == SUCCESS)) {
- p->value = zend_new_interned_string(zend_string_copy(Z_STR_P(default_value)));
- } else {
- p->value = ini_entry->value ?
- zend_string_init_interned(ini_entry->value, ini_entry->value_length, 1) : NULL;
- if (p->on_modify) {
- p->on_modify(p, p->value, p->mh_arg1, p->mh_arg2, p->mh_arg3, ZEND_INI_STAGE_STARTUP);
- }
- }
- ini_entry++;
- }
- return SUCCESS;
- }
- /* }}} */
- ZEND_API zend_result zend_register_ini_entries(const zend_ini_entry_def *ini_entry, int module_number) /* {{{ */
- {
- zend_module_entry *module;
- /* Module is likely to be the last one in the list */
- ZEND_HASH_REVERSE_FOREACH_PTR(&module_registry, module) {
- if (module->module_number == module_number) {
- return zend_register_ini_entries_ex(ini_entry, module_number, module->type);
- }
- } ZEND_HASH_FOREACH_END();
- return FAILURE;
- }
- /* }}} */
- ZEND_API void zend_unregister_ini_entries_ex(int module_number, int module_type) /* {{{ */
- {
- static HashTable *ini_directives;
- if (module_type == MODULE_TEMPORARY) {
- ini_directives = EG(ini_directives);
- } else {
- ini_directives = registered_zend_ini_directives;
- }
- zend_hash_apply_with_argument(ini_directives, zend_remove_ini_entries, (void *) &module_number);
- }
- /* }}} */
- ZEND_API void zend_unregister_ini_entries(int module_number) /* {{{ */
- {
- zend_module_entry *module;
- /* Module is likely to be the last one in the list */
- ZEND_HASH_REVERSE_FOREACH_PTR(&module_registry, module) {
- if (module->module_number == module_number) {
- zend_unregister_ini_entries_ex(module_number, module->type);
- return;
- }
- } ZEND_HASH_FOREACH_END();
- }
- /* }}} */
- #ifdef ZTS
- ZEND_API void zend_ini_refresh_caches(int stage) /* {{{ */
- {
- zend_ini_entry *p;
- ZEND_HASH_FOREACH_PTR(EG(ini_directives), p) {
- if (p->on_modify) {
- p->on_modify(p, p->value, p->mh_arg1, p->mh_arg2, p->mh_arg3, stage);
- }
- } ZEND_HASH_FOREACH_END();
- }
- /* }}} */
- #endif
- ZEND_API zend_result zend_alter_ini_entry(zend_string *name, zend_string *new_value, int modify_type, int stage) /* {{{ */
- {
- return zend_alter_ini_entry_ex(name, new_value, modify_type, stage, 0);
- }
- /* }}} */
- ZEND_API zend_result zend_alter_ini_entry_chars(zend_string *name, const char *value, size_t value_length, int modify_type, int stage) /* {{{ */
- {
- zend_result ret;
- zend_string *new_value;
- new_value = zend_string_init(value, value_length, !(stage & ZEND_INI_STAGE_IN_REQUEST));
- ret = zend_alter_ini_entry_ex(name, new_value, modify_type, stage, 0);
- zend_string_release(new_value);
- return ret;
- }
- /* }}} */
- ZEND_API zend_result zend_alter_ini_entry_chars_ex(zend_string *name, const char *value, size_t value_length, int modify_type, int stage, int force_change) /* {{{ */
- {
- zend_result ret;
- zend_string *new_value;
- new_value = zend_string_init(value, value_length, !(stage & ZEND_INI_STAGE_IN_REQUEST));
- ret = zend_alter_ini_entry_ex(name, new_value, modify_type, stage, force_change);
- zend_string_release(new_value);
- return ret;
- }
- /* }}} */
- ZEND_API zend_result zend_alter_ini_entry_ex(zend_string *name, zend_string *new_value, int modify_type, int stage, bool force_change) /* {{{ */
- {
- zend_ini_entry *ini_entry;
- zend_string *duplicate;
- uint8_t modifiable;
- bool modified;
- if ((ini_entry = zend_hash_find_ptr(EG(ini_directives), name)) == NULL) {
- return FAILURE;
- }
- modifiable = ini_entry->modifiable;
- modified = ini_entry->modified;
- if (stage == ZEND_INI_STAGE_ACTIVATE && modify_type == ZEND_INI_SYSTEM) {
- ini_entry->modifiable = ZEND_INI_SYSTEM;
- }
- if (!force_change) {
- if (!(ini_entry->modifiable & modify_type)) {
- return FAILURE;
- }
- }
- if (!EG(modified_ini_directives)) {
- ALLOC_HASHTABLE(EG(modified_ini_directives));
- zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
- }
- if (!modified) {
- ini_entry->orig_value = ini_entry->value;
- ini_entry->orig_modifiable = modifiable;
- ini_entry->modified = 1;
- zend_hash_add_ptr(EG(modified_ini_directives), ini_entry->name, ini_entry);
- }
- duplicate = zend_string_copy(new_value);
- if (!ini_entry->on_modify
- || ini_entry->on_modify(ini_entry, duplicate, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage) == SUCCESS) {
- if (modified && ini_entry->orig_value != ini_entry->value) { /* we already changed the value, free the changed value */
- zend_string_release(ini_entry->value);
- }
- ini_entry->value = duplicate;
- } else {
- zend_string_release(duplicate);
- return FAILURE;
- }
- return SUCCESS;
- }
- /* }}} */
- ZEND_API zend_result zend_restore_ini_entry(zend_string *name, int stage) /* {{{ */
- {
- zend_ini_entry *ini_entry;
- if ((ini_entry = zend_hash_find_ptr(EG(ini_directives), name)) == NULL ||
- (stage == ZEND_INI_STAGE_RUNTIME && (ini_entry->modifiable & ZEND_INI_USER) == 0)) {
- return FAILURE;
- }
- if (EG(modified_ini_directives)) {
- if (zend_restore_ini_entry_cb(ini_entry, stage) == 0) {
- zend_hash_del(EG(modified_ini_directives), name);
- } else {
- return FAILURE;
- }
- }
- return SUCCESS;
- }
- /* }}} */
- ZEND_API zend_result zend_ini_register_displayer(const char *name, uint32_t name_length, void (*displayer)(zend_ini_entry *ini_entry, int type)) /* {{{ */
- {
- zend_ini_entry *ini_entry;
- ini_entry = zend_hash_str_find_ptr(registered_zend_ini_directives, name, name_length);
- if (ini_entry == NULL) {
- return FAILURE;
- }
- ini_entry->displayer = displayer;
- return SUCCESS;
- }
- /* }}} */
- /*
- * Data retrieval
- */
- ZEND_API zend_long zend_ini_long(const char *name, size_t name_length, int orig) /* {{{ */
- {
- zend_ini_entry *ini_entry;
- ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length);
- if (ini_entry) {
- if (orig && ini_entry->modified) {
- return (ini_entry->orig_value ? ZEND_STRTOL(ZSTR_VAL(ini_entry->orig_value), NULL, 0) : 0);
- } else {
- return (ini_entry->value ? ZEND_STRTOL(ZSTR_VAL(ini_entry->value), NULL, 0) : 0);
- }
- }
- return 0;
- }
- /* }}} */
- ZEND_API double zend_ini_double(const char *name, size_t name_length, int orig) /* {{{ */
- {
- zend_ini_entry *ini_entry;
- ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length);
- if (ini_entry) {
- if (orig && ini_entry->modified) {
- return (double) (ini_entry->orig_value ? zend_strtod(ZSTR_VAL(ini_entry->orig_value), NULL) : 0.0);
- } else {
- return (double) (ini_entry->value ? zend_strtod(ZSTR_VAL(ini_entry->value), NULL) : 0.0);
- }
- }
- return 0.0;
- }
- /* }}} */
- ZEND_API char *zend_ini_string_ex(const char *name, size_t name_length, int orig, bool *exists) /* {{{ */
- {
- zend_ini_entry *ini_entry;
- ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length);
- if (ini_entry) {
- if (exists) {
- *exists = 1;
- }
- if (orig && ini_entry->modified) {
- return ini_entry->orig_value ? ZSTR_VAL(ini_entry->orig_value) : NULL;
- } else {
- return ini_entry->value ? ZSTR_VAL(ini_entry->value) : NULL;
- }
- } else {
- if (exists) {
- *exists = 0;
- }
- return NULL;
- }
- }
- /* }}} */
- ZEND_API char *zend_ini_string(const char *name, size_t name_length, int orig) /* {{{ */
- {
- bool exists = 1;
- char *return_value;
- return_value = zend_ini_string_ex(name, name_length, orig, &exists);
- if (!exists) {
- return NULL;
- } else if (!return_value) {
- return_value = "";
- }
- return return_value;
- }
- /* }}} */
- ZEND_API zend_string *zend_ini_get_value(zend_string *name) /* {{{ */
- {
- zend_ini_entry *ini_entry;
- ini_entry = zend_hash_find_ptr(EG(ini_directives), name);
- if (ini_entry) {
- return ini_entry->value ? ini_entry->value : ZSTR_EMPTY_ALLOC();
- } else {
- return NULL;
- }
- }
- /* }}} */
- ZEND_API bool zend_ini_parse_bool(zend_string *str)
- {
- if (zend_string_equals_literal_ci(str, "true")
- || zend_string_equals_literal_ci(str, "yes")
- || zend_string_equals_literal_ci(str, "on")
- ) {
- return 1;
- } else {
- return atoi(ZSTR_VAL(str)) != 0;
- }
- }
- ZEND_INI_DISP(zend_ini_boolean_displayer_cb) /* {{{ */
- {
- int value;
- zend_string *tmp_value;
- if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
- tmp_value = (ini_entry->orig_value ? ini_entry->orig_value : NULL );
- } else if (ini_entry->value) {
- tmp_value = ini_entry->value;
- } else {
- tmp_value = NULL;
- }
- if (tmp_value) {
- value = zend_ini_parse_bool(tmp_value);
- } else {
- value = 0;
- }
- if (value) {
- ZEND_PUTS("On");
- } else {
- ZEND_PUTS("Off");
- }
- }
- /* }}} */
- ZEND_INI_DISP(zend_ini_color_displayer_cb) /* {{{ */
- {
- char *value;
- if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
- value = ZSTR_VAL(ini_entry->orig_value);
- } else if (ini_entry->value) {
- value = ZSTR_VAL(ini_entry->value);
- } else {
- value = NULL;
- }
- if (value) {
- if (zend_uv.html_errors) {
- zend_printf("<font style=\"color: %s\">%s</font>", value, value);
- } else {
- ZEND_PUTS(value);
- }
- } else {
- if (zend_uv.html_errors) {
- ZEND_PUTS(NO_VALUE_HTML);
- } else {
- ZEND_PUTS(NO_VALUE_PLAINTEXT);
- }
- }
- }
- /* }}} */
- ZEND_INI_DISP(display_link_numbers) /* {{{ */
- {
- char *value;
- if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
- value = ZSTR_VAL(ini_entry->orig_value);
- } else if (ini_entry->value) {
- value = ZSTR_VAL(ini_entry->value);
- } else {
- value = NULL;
- }
- if (value) {
- if (atoi(value) == -1) {
- ZEND_PUTS("Unlimited");
- } else {
- zend_printf("%s", value);
- }
- }
- }
- /* }}} */
- /* Standard message handlers */
- ZEND_API ZEND_INI_MH(OnUpdateBool) /* {{{ */
- {
- bool *p = (bool *) ZEND_INI_GET_ADDR();
- *p = zend_ini_parse_bool(new_value);
- return SUCCESS;
- }
- /* }}} */
- ZEND_API ZEND_INI_MH(OnUpdateLong) /* {{{ */
- {
- zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
- *p = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
- return SUCCESS;
- }
- /* }}} */
- ZEND_API ZEND_INI_MH(OnUpdateLongGEZero) /* {{{ */
- {
- zend_long tmp = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
- if (tmp < 0) {
- return FAILURE;
- }
- zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
- *p = tmp;
- return SUCCESS;
- }
- /* }}} */
- ZEND_API ZEND_INI_MH(OnUpdateReal) /* {{{ */
- {
- double *p = (double *) ZEND_INI_GET_ADDR();
- *p = zend_strtod(ZSTR_VAL(new_value), NULL);
- return SUCCESS;
- }
- /* }}} */
- ZEND_API ZEND_INI_MH(OnUpdateString) /* {{{ */
- {
- char **p = (char **) ZEND_INI_GET_ADDR();
- *p = new_value ? ZSTR_VAL(new_value) : NULL;
- return SUCCESS;
- }
- /* }}} */
- ZEND_API ZEND_INI_MH(OnUpdateStringUnempty) /* {{{ */
- {
- if (new_value && !ZSTR_VAL(new_value)[0]) {
- return FAILURE;
- }
- char **p = (char **) ZEND_INI_GET_ADDR();
- *p = new_value ? ZSTR_VAL(new_value) : NULL;
- return SUCCESS;
- }
- /* }}} */
|