xref: /PHP-8.0/Zend/zend_ini.c (revision fa8d9b11)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) Zend Technologies Ltd. (http://www.zend.com)           |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 2.00 of the Zend 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.zend.com/license/2_00.txt.                                |
11    | If you did not receive a copy of the Zend license and are unable to  |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@zend.com so we can mail you a copy immediately.              |
14    +----------------------------------------------------------------------+
15    | Author: Zeev Suraski <zeev@php.net>                                  |
16    +----------------------------------------------------------------------+
17 */
18 
19 #include "zend.h"
20 #include "zend_sort.h"
21 #include "zend_API.h"
22 #include "zend_ini.h"
23 #include "zend_alloc.h"
24 #include "zend_operators.h"
25 #include "zend_strtod.h"
26 
27 static HashTable *registered_zend_ini_directives;
28 
29 #define NO_VALUE_PLAINTEXT		"no value"
30 #define NO_VALUE_HTML			"<i>no value</i>"
31 
32 /*
33  * hash_apply functions
34  */
zend_remove_ini_entries(zval * el,void * arg)35 static int zend_remove_ini_entries(zval *el, void *arg) /* {{{ */
36 {
37 	zend_ini_entry *ini_entry = (zend_ini_entry *)Z_PTR_P(el);
38 	int module_number = *(int *)arg;
39 
40 	return ini_entry->module_number == module_number;
41 }
42 /* }}} */
43 
zend_restore_ini_entry_cb(zend_ini_entry * ini_entry,int stage)44 static zend_result zend_restore_ini_entry_cb(zend_ini_entry *ini_entry, int stage) /* {{{ */
45 {
46 	zend_result result = FAILURE;
47 
48 	if (ini_entry->modified) {
49 		if (ini_entry->on_modify) {
50 			zend_try {
51 			/* even if on_modify bails out, we have to continue on with restoring,
52 				since there can be allocated variables that would be freed on MM shutdown
53 				and would lead to memory corruption later ini entry is modified again */
54 				result = ini_entry->on_modify(ini_entry, ini_entry->orig_value, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage);
55 			} zend_end_try();
56 		}
57 		if (stage == ZEND_INI_STAGE_RUNTIME && result == FAILURE) {
58 			/* runtime failure is OK */
59 			return 1;
60 		}
61 		if (ini_entry->value != ini_entry->orig_value) {
62 			zend_string_release(ini_entry->value);
63 		}
64 		ini_entry->value = ini_entry->orig_value;
65 		ini_entry->modifiable = ini_entry->orig_modifiable;
66 		ini_entry->modified = 0;
67 		ini_entry->orig_value = NULL;
68 		ini_entry->orig_modifiable = 0;
69 	}
70 	return 0;
71 }
72 /* }}} */
73 
free_ini_entry(zval * zv)74 static void free_ini_entry(zval *zv) /* {{{ */
75 {
76 	zend_ini_entry *entry = (zend_ini_entry*)Z_PTR_P(zv);
77 
78 	zend_string_release_ex(entry->name, 1);
79 	if (entry->value) {
80 		zend_string_release(entry->value);
81 	}
82 	if (entry->orig_value) {
83 		zend_string_release_ex(entry->orig_value, 1);
84 	}
85 	free(entry);
86 }
87 /* }}} */
88 
89 /*
90  * Startup / shutdown
91  */
zend_ini_startup(void)92 ZEND_API void zend_ini_startup(void) /* {{{ */
93 {
94 	registered_zend_ini_directives = (HashTable *) malloc(sizeof(HashTable));
95 
96 	EG(ini_directives) = registered_zend_ini_directives;
97 	EG(modified_ini_directives) = NULL;
98 	EG(error_reporting_ini_entry) = NULL;
99 	zend_hash_init(registered_zend_ini_directives, 128, NULL, free_ini_entry, 1);
100 }
101 /* }}} */
102 
zend_ini_shutdown(void)103 ZEND_API void zend_ini_shutdown(void) /* {{{ */
104 {
105 	zend_ini_dtor(EG(ini_directives));
106 }
107 /* }}} */
108 
zend_ini_dtor(HashTable * ini_directives)109 ZEND_API void zend_ini_dtor(HashTable *ini_directives) /* {{{ */
110 {
111 	zend_hash_destroy(ini_directives);
112 	free(ini_directives);
113 }
114 /* }}} */
115 
zend_ini_global_shutdown(void)116 ZEND_API void zend_ini_global_shutdown(void) /* {{{ */
117 {
118 	zend_hash_destroy(registered_zend_ini_directives);
119 	free(registered_zend_ini_directives);
120 }
121 /* }}} */
122 
zend_ini_deactivate(void)123 ZEND_API void zend_ini_deactivate(void) /* {{{ */
124 {
125 	if (EG(modified_ini_directives)) {
126 		zend_ini_entry *ini_entry;
127 
128 		ZEND_HASH_FOREACH_PTR(EG(modified_ini_directives), ini_entry) {
129 			zend_restore_ini_entry_cb(ini_entry, ZEND_INI_STAGE_DEACTIVATE);
130 		} ZEND_HASH_FOREACH_END();
131 		zend_hash_destroy(EG(modified_ini_directives));
132 		FREE_HASHTABLE(EG(modified_ini_directives));
133 		EG(modified_ini_directives) = NULL;
134 	}
135 }
136 /* }}} */
137 
138 #ifdef ZTS
copy_ini_entry(zval * zv)139 static void copy_ini_entry(zval *zv) /* {{{ */
140 {
141 	zend_ini_entry *old_entry = (zend_ini_entry*)Z_PTR_P(zv);
142 	zend_ini_entry *new_entry = pemalloc(sizeof(zend_ini_entry), 1);
143 
144 	Z_PTR_P(zv) = new_entry;
145 	memcpy(new_entry, old_entry, sizeof(zend_ini_entry));
146 	if (old_entry->name) {
147 		new_entry->name = zend_string_dup(old_entry->name, 1);
148 	}
149 	if (old_entry->value) {
150 		new_entry->value = zend_string_dup(old_entry->value, 1);
151 	}
152 	if (old_entry->orig_value) {
153 		new_entry->orig_value = zend_string_dup(old_entry->orig_value, 1);
154 	}
155 }
156 /* }}} */
157 
zend_copy_ini_directives(void)158 ZEND_API void zend_copy_ini_directives(void) /* {{{ */
159 {
160 	EG(modified_ini_directives) = NULL;
161 	EG(error_reporting_ini_entry) = NULL;
162 	EG(ini_directives) = (HashTable *) malloc(sizeof(HashTable));
163 	zend_hash_init(EG(ini_directives), registered_zend_ini_directives->nNumOfElements, NULL, free_ini_entry, 1);
164 	zend_hash_copy(EG(ini_directives), registered_zend_ini_directives, copy_ini_entry);
165 }
166 /* }}} */
167 #endif
168 
ini_key_compare(Bucket * f,Bucket * s)169 static int ini_key_compare(Bucket *f, Bucket *s) /* {{{ */
170 {
171 	if (!f->key && !s->key) { /* both numeric */
172 		if (f->h > s->h) {
173 			return -1;
174 		} else if (f->h < s->h) {
175 			return 1;
176 		}
177 		return 0;
178 	} else if (!f->key) { /* f is numeric, s is not */
179 		return -1;
180 	} else if (!s->key) { /* s is numeric, f is not */
181 		return 1;
182 	} else { /* both strings */
183 		return zend_binary_strcasecmp(ZSTR_VAL(f->key), ZSTR_LEN(f->key), ZSTR_VAL(s->key), ZSTR_LEN(s->key));
184 	}
185 }
186 /* }}} */
187 
zend_ini_sort_entries(void)188 ZEND_API void zend_ini_sort_entries(void) /* {{{ */
189 {
190 	zend_hash_sort(EG(ini_directives), ini_key_compare, 0);
191 }
192 /* }}} */
193 
194 /*
195  * Registration / unregistration
196  */
zend_register_ini_entries(const zend_ini_entry_def * ini_entry,int module_number)197 ZEND_API zend_result zend_register_ini_entries(const zend_ini_entry_def *ini_entry, int module_number) /* {{{ */
198 {
199 	zend_ini_entry *p;
200 	zval *default_value;
201 	HashTable *directives = registered_zend_ini_directives;
202 
203 #ifdef ZTS
204 	/* if we are called during the request, eg: from dl(),
205 	 * then we should not touch the global directives table,
206 	 * and should update the per-(request|thread) version instead.
207 	 * This solves two problems: one is that ini entries for dl()'d
208 	 * extensions will now work, and the second is that updating the
209 	 * global hash here from dl() is not mutex protected and can
210 	 * lead to death.
211 	 */
212 	if (directives != EG(ini_directives)) {
213 		directives = EG(ini_directives);
214 	}
215 #endif
216 
217 	while (ini_entry->name) {
218 		p = pemalloc(sizeof(zend_ini_entry), 1);
219 		p->name = zend_string_init_interned(ini_entry->name, ini_entry->name_length, 1);
220 		p->on_modify = ini_entry->on_modify;
221 		p->mh_arg1 = ini_entry->mh_arg1;
222 		p->mh_arg2 = ini_entry->mh_arg2;
223 		p->mh_arg3 = ini_entry->mh_arg3;
224 		p->value = NULL;
225 		p->orig_value = NULL;
226 		p->displayer = ini_entry->displayer;
227 		p->modifiable = ini_entry->modifiable;
228 
229 		p->orig_modifiable = 0;
230 		p->modified = 0;
231 		p->module_number = module_number;
232 
233 		if (zend_hash_add_ptr(directives, p->name, (void*)p) == NULL) {
234 			if (p->name) {
235 				zend_string_release_ex(p->name, 1);
236 			}
237 			zend_unregister_ini_entries(module_number);
238 			return FAILURE;
239 		}
240 		if (((default_value = zend_get_configuration_directive(p->name)) != NULL) &&
241             (!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)) {
242 
243 			p->value = zend_new_interned_string(zend_string_copy(Z_STR_P(default_value)));
244 		} else {
245 			p->value = ini_entry->value ?
246 				zend_string_init_interned(ini_entry->value, ini_entry->value_length, 1) : NULL;
247 
248 			if (p->on_modify) {
249 				p->on_modify(p, p->value, p->mh_arg1, p->mh_arg2, p->mh_arg3, ZEND_INI_STAGE_STARTUP);
250 			}
251 		}
252 		ini_entry++;
253 	}
254 	return SUCCESS;
255 }
256 /* }}} */
257 
zend_unregister_ini_entries(int module_number)258 ZEND_API void zend_unregister_ini_entries(int module_number) /* {{{ */
259 {
260 	zend_hash_apply_with_argument(registered_zend_ini_directives, zend_remove_ini_entries, (void *) &module_number);
261 }
262 /* }}} */
263 
264 #ifdef ZTS
zend_ini_refresh_caches(int stage)265 ZEND_API void zend_ini_refresh_caches(int stage) /* {{{ */
266 {
267 	zend_ini_entry *p;
268 
269 	ZEND_HASH_FOREACH_PTR(EG(ini_directives), p) {
270 		if (p->on_modify) {
271 			p->on_modify(p, p->value, p->mh_arg1, p->mh_arg2, p->mh_arg3, stage);
272 		}
273 	} ZEND_HASH_FOREACH_END();
274 }
275 /* }}} */
276 #endif
277 
zend_alter_ini_entry(zend_string * name,zend_string * new_value,int modify_type,int stage)278 ZEND_API zend_result zend_alter_ini_entry(zend_string *name, zend_string *new_value, int modify_type, int stage) /* {{{ */
279 {
280 
281 	return zend_alter_ini_entry_ex(name, new_value, modify_type, stage, 0);
282 }
283 /* }}} */
284 
zend_alter_ini_entry_chars(zend_string * name,const char * value,size_t value_length,int modify_type,int stage)285 ZEND_API zend_result zend_alter_ini_entry_chars(zend_string *name, const char *value, size_t value_length, int modify_type, int stage) /* {{{ */
286 {
287     zend_result ret;
288     zend_string *new_value;
289 
290 	new_value = zend_string_init(value, value_length, !(stage & ZEND_INI_STAGE_IN_REQUEST));
291 	ret = zend_alter_ini_entry_ex(name, new_value, modify_type, stage, 0);
292 	zend_string_release(new_value);
293 	return ret;
294 }
295 /* }}} */
296 
zend_alter_ini_entry_chars_ex(zend_string * name,const char * value,size_t value_length,int modify_type,int stage,int force_change)297 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) /* {{{ */
298 {
299     zend_result ret;
300     zend_string *new_value;
301 
302 	new_value = zend_string_init(value, value_length, !(stage & ZEND_INI_STAGE_IN_REQUEST));
303 	ret = zend_alter_ini_entry_ex(name, new_value, modify_type, stage, force_change);
304 	zend_string_release(new_value);
305 	return ret;
306 }
307 /* }}} */
308 
zend_alter_ini_entry_ex(zend_string * name,zend_string * new_value,int modify_type,int stage,bool force_change)309 ZEND_API zend_result zend_alter_ini_entry_ex(zend_string *name, zend_string *new_value, int modify_type, int stage, bool force_change) /* {{{ */
310 {
311 	zend_ini_entry *ini_entry;
312 	zend_string *duplicate;
313 	uint8_t modifiable;
314 	zend_bool modified;
315 
316 	if ((ini_entry = zend_hash_find_ptr(EG(ini_directives), name)) == NULL) {
317 		return FAILURE;
318 	}
319 
320 	modifiable = ini_entry->modifiable;
321 	modified = ini_entry->modified;
322 
323 	if (stage == ZEND_INI_STAGE_ACTIVATE && modify_type == ZEND_INI_SYSTEM) {
324 		ini_entry->modifiable = ZEND_INI_SYSTEM;
325 	}
326 
327 	if (!force_change) {
328 		if (!(ini_entry->modifiable & modify_type)) {
329 			return FAILURE;
330 		}
331 	}
332 
333 	if (!EG(modified_ini_directives)) {
334 		ALLOC_HASHTABLE(EG(modified_ini_directives));
335 		zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
336 	}
337 	if (!modified) {
338 		ini_entry->orig_value = ini_entry->value;
339 		ini_entry->orig_modifiable = modifiable;
340 		ini_entry->modified = 1;
341 		zend_hash_add_ptr(EG(modified_ini_directives), ini_entry->name, ini_entry);
342 	}
343 
344 	duplicate = zend_string_copy(new_value);
345 
346 	if (!ini_entry->on_modify
347 		|| ini_entry->on_modify(ini_entry, duplicate, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage) == SUCCESS) {
348 		if (modified && ini_entry->orig_value != ini_entry->value) { /* we already changed the value, free the changed value */
349 			zend_string_release(ini_entry->value);
350 		}
351 		ini_entry->value = duplicate;
352 	} else {
353 		zend_string_release(duplicate);
354 		return FAILURE;
355 	}
356 
357 	return SUCCESS;
358 }
359 /* }}} */
360 
zend_restore_ini_entry(zend_string * name,int stage)361 ZEND_API zend_result zend_restore_ini_entry(zend_string *name, int stage) /* {{{ */
362 {
363 	zend_ini_entry *ini_entry;
364 
365 	if ((ini_entry = zend_hash_find_ptr(EG(ini_directives), name)) == NULL ||
366 		(stage == ZEND_INI_STAGE_RUNTIME && (ini_entry->modifiable & ZEND_INI_USER) == 0)) {
367 		return FAILURE;
368 	}
369 
370 	if (EG(modified_ini_directives)) {
371 		if (zend_restore_ini_entry_cb(ini_entry, stage) == 0) {
372 			zend_hash_del(EG(modified_ini_directives), name);
373 		} else {
374 			return FAILURE;
375 		}
376 	}
377 
378 	return SUCCESS;
379 }
380 /* }}} */
381 
zend_ini_register_displayer(const char * name,uint32_t name_length,void (* displayer)(zend_ini_entry * ini_entry,int type))382 ZEND_API zend_result zend_ini_register_displayer(const char *name, uint32_t name_length, void (*displayer)(zend_ini_entry *ini_entry, int type)) /* {{{ */
383 {
384 	zend_ini_entry *ini_entry;
385 
386 	ini_entry = zend_hash_str_find_ptr(registered_zend_ini_directives, name, name_length);
387 	if (ini_entry == NULL) {
388 		return FAILURE;
389 	}
390 
391 	ini_entry->displayer = displayer;
392 	return SUCCESS;
393 }
394 /* }}} */
395 
396 /*
397  * Data retrieval
398  */
399 
zend_ini_long(const char * name,size_t name_length,int orig)400 ZEND_API zend_long zend_ini_long(const char *name, size_t name_length, int orig) /* {{{ */
401 {
402 	zend_ini_entry *ini_entry;
403 
404 	ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length);
405 	if (ini_entry) {
406 		if (orig && ini_entry->modified) {
407 			return (ini_entry->orig_value ? ZEND_STRTOL(ZSTR_VAL(ini_entry->orig_value), NULL, 0) : 0);
408 		} else {
409 			return (ini_entry->value      ? ZEND_STRTOL(ZSTR_VAL(ini_entry->value), NULL, 0)      : 0);
410 		}
411 	}
412 
413 	return 0;
414 }
415 /* }}} */
416 
zend_ini_double(const char * name,size_t name_length,int orig)417 ZEND_API double zend_ini_double(const char *name, size_t name_length, int orig) /* {{{ */
418 {
419 	zend_ini_entry *ini_entry;
420 
421 	ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length);
422 	if (ini_entry) {
423 		if (orig && ini_entry->modified) {
424 			return (double) (ini_entry->orig_value ? zend_strtod(ZSTR_VAL(ini_entry->orig_value), NULL) : 0.0);
425 		} else {
426 			return (double) (ini_entry->value      ? zend_strtod(ZSTR_VAL(ini_entry->value), NULL)      : 0.0);
427 		}
428 	}
429 
430 	return 0.0;
431 }
432 /* }}} */
433 
zend_ini_string_ex(const char * name,size_t name_length,int orig,zend_bool * exists)434 ZEND_API char *zend_ini_string_ex(const char *name, size_t name_length, int orig, zend_bool *exists) /* {{{ */
435 {
436 	zend_ini_entry *ini_entry;
437 
438 	ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length);
439 	if (ini_entry) {
440 		if (exists) {
441 			*exists = 1;
442 		}
443 
444 		if (orig && ini_entry->modified) {
445 			return ini_entry->orig_value ? ZSTR_VAL(ini_entry->orig_value) : NULL;
446 		} else {
447 			return ini_entry->value ? ZSTR_VAL(ini_entry->value) : NULL;
448 		}
449 	} else {
450 		if (exists) {
451 			*exists = 0;
452 		}
453 		return NULL;
454 	}
455 }
456 /* }}} */
457 
zend_ini_string(const char * name,size_t name_length,int orig)458 ZEND_API char *zend_ini_string(const char *name, size_t name_length, int orig) /* {{{ */
459 {
460 	zend_bool exists = 1;
461 	char *return_value;
462 
463 	return_value = zend_ini_string_ex(name, name_length, orig, &exists);
464 	if (!exists) {
465 		return NULL;
466 	} else if (!return_value) {
467 		return_value = "";
468 	}
469 	return return_value;
470 }
471 /* }}} */
472 
zend_ini_get_value(zend_string * name)473 ZEND_API zend_string *zend_ini_get_value(zend_string *name) /* {{{ */
474 {
475 	zend_ini_entry *ini_entry;
476 
477 	ini_entry = zend_hash_find_ptr(EG(ini_directives), name);
478 	if (ini_entry) {
479 		return ini_entry->value ? ini_entry->value : ZSTR_EMPTY_ALLOC();
480 	} else {
481 		return NULL;
482 	}
483 }
484 /* }}} */
485 
zend_ini_parse_bool(zend_string * str)486 ZEND_API zend_bool zend_ini_parse_bool(zend_string *str)
487 {
488 	if ((ZSTR_LEN(str) == 4 && strcasecmp(ZSTR_VAL(str), "true") == 0)
489 	  || (ZSTR_LEN(str) == 3 && strcasecmp(ZSTR_VAL(str), "yes") == 0)
490 	  || (ZSTR_LEN(str) == 2 && strcasecmp(ZSTR_VAL(str), "on") == 0)) {
491 		return 1;
492 	} else {
493 		return atoi(ZSTR_VAL(str)) != 0;
494 	}
495 }
496 
ZEND_INI_DISP(zend_ini_boolean_displayer_cb)497 ZEND_INI_DISP(zend_ini_boolean_displayer_cb) /* {{{ */
498 {
499 	int value;
500 	zend_string *tmp_value;
501 
502 	if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
503 		tmp_value = (ini_entry->orig_value ? ini_entry->orig_value : NULL );
504 	} else if (ini_entry->value) {
505 		tmp_value = ini_entry->value;
506 	} else {
507 		tmp_value = NULL;
508 	}
509 
510 	if (tmp_value) {
511 		value = zend_ini_parse_bool(tmp_value);
512 	} else {
513 		value = 0;
514 	}
515 
516 	if (value) {
517 		ZEND_PUTS("On");
518 	} else {
519 		ZEND_PUTS("Off");
520 	}
521 }
522 /* }}} */
523 
ZEND_INI_DISP(zend_ini_color_displayer_cb)524 ZEND_INI_DISP(zend_ini_color_displayer_cb) /* {{{ */
525 {
526 	char *value;
527 
528 	if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
529 		value = ZSTR_VAL(ini_entry->orig_value);
530 	} else if (ini_entry->value) {
531 		value = ZSTR_VAL(ini_entry->value);
532 	} else {
533 		value = NULL;
534 	}
535 	if (value) {
536 		if (zend_uv.html_errors) {
537 			zend_printf("<font style=\"color: %s\">%s</font>", value, value);
538 		} else {
539 			ZEND_PUTS(value);
540 		}
541 	} else {
542 		if (zend_uv.html_errors) {
543 			ZEND_PUTS(NO_VALUE_HTML);
544 		} else {
545 			ZEND_PUTS(NO_VALUE_PLAINTEXT);
546 		}
547 	}
548 }
549 /* }}} */
550 
ZEND_INI_DISP(display_link_numbers)551 ZEND_INI_DISP(display_link_numbers) /* {{{ */
552 {
553 	char *value;
554 
555 	if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
556 		value = ZSTR_VAL(ini_entry->orig_value);
557 	} else if (ini_entry->value) {
558 		value = ZSTR_VAL(ini_entry->value);
559 	} else {
560 		value = NULL;
561 	}
562 
563 	if (value) {
564 		if (atoi(value) == -1) {
565 			ZEND_PUTS("Unlimited");
566 		} else {
567 			zend_printf("%s", value);
568 		}
569 	}
570 }
571 /* }}} */
572 
573 /* Standard message handlers */
ZEND_INI_MH(OnUpdateBool)574 ZEND_API ZEND_INI_MH(OnUpdateBool) /* {{{ */
575 {
576 	zend_bool *p = (zend_bool *) ZEND_INI_GET_ADDR();
577 	*p = zend_ini_parse_bool(new_value);
578 	return SUCCESS;
579 }
580 /* }}} */
581 
ZEND_INI_MH(OnUpdateLong)582 ZEND_API ZEND_INI_MH(OnUpdateLong) /* {{{ */
583 {
584 	zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
585 	*p = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
586 	return SUCCESS;
587 }
588 /* }}} */
589 
ZEND_INI_MH(OnUpdateLongGEZero)590 ZEND_API ZEND_INI_MH(OnUpdateLongGEZero) /* {{{ */
591 {
592 	zend_long tmp = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
593 	if (tmp < 0) {
594 		return FAILURE;
595 	}
596 
597 	zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
598 	*p = tmp;
599 
600 	return SUCCESS;
601 }
602 /* }}} */
603 
ZEND_INI_MH(OnUpdateReal)604 ZEND_API ZEND_INI_MH(OnUpdateReal) /* {{{ */
605 {
606 	double *p = (double *) ZEND_INI_GET_ADDR();
607 	*p = zend_strtod(ZSTR_VAL(new_value), NULL);
608 	return SUCCESS;
609 }
610 /* }}} */
611 
ZEND_INI_MH(OnUpdateString)612 ZEND_API ZEND_INI_MH(OnUpdateString) /* {{{ */
613 {
614 	char **p = (char **) ZEND_INI_GET_ADDR();
615 	*p = new_value ? ZSTR_VAL(new_value) : NULL;
616 	return SUCCESS;
617 }
618 /* }}} */
619 
ZEND_INI_MH(OnUpdateStringUnempty)620 ZEND_API ZEND_INI_MH(OnUpdateStringUnempty) /* {{{ */
621 {
622 	if (new_value && !ZSTR_VAL(new_value)[0]) {
623 		return FAILURE;
624 	}
625 
626 	char **p = (char **) ZEND_INI_GET_ADDR();
627 	*p = new_value ? ZSTR_VAL(new_value) : NULL;
628 	return SUCCESS;
629 }
630 /* }}} */
631