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 int zend_restore_ini_entry_cb(zend_ini_entry *ini_entry, int stage) /* {{{ */
45 {
46 int 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 int 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_ex(registered_zend_ini_directives, 128, NULL, free_ini_entry, 1, 0);
100 return SUCCESS;
101 }
102 /* }}} */
103
zend_ini_shutdown(void)104 ZEND_API int zend_ini_shutdown(void) /* {{{ */
105 {
106 zend_ini_dtor(EG(ini_directives));
107 return SUCCESS;
108 }
109 /* }}} */
110
zend_ini_dtor(HashTable * ini_directives)111 ZEND_API void zend_ini_dtor(HashTable *ini_directives) /* {{{ */
112 {
113 zend_hash_destroy(ini_directives);
114 free(ini_directives);
115 }
116 /* }}} */
117
zend_ini_global_shutdown(void)118 ZEND_API int zend_ini_global_shutdown(void) /* {{{ */
119 {
120 zend_hash_destroy(registered_zend_ini_directives);
121 free(registered_zend_ini_directives);
122 return SUCCESS;
123 }
124 /* }}} */
125
zend_ini_deactivate(void)126 ZEND_API int zend_ini_deactivate(void) /* {{{ */
127 {
128 if (EG(modified_ini_directives)) {
129 zend_ini_entry *ini_entry;
130
131 ZEND_HASH_FOREACH_PTR(EG(modified_ini_directives), ini_entry) {
132 zend_restore_ini_entry_cb(ini_entry, ZEND_INI_STAGE_DEACTIVATE);
133 } ZEND_HASH_FOREACH_END();
134 zend_hash_destroy(EG(modified_ini_directives));
135 FREE_HASHTABLE(EG(modified_ini_directives));
136 EG(modified_ini_directives) = NULL;
137 }
138 return SUCCESS;
139 }
140 /* }}} */
141
142 #ifdef ZTS
copy_ini_entry(zval * zv)143 static void copy_ini_entry(zval *zv) /* {{{ */
144 {
145 zend_ini_entry *old_entry = (zend_ini_entry*)Z_PTR_P(zv);
146 zend_ini_entry *new_entry = pemalloc(sizeof(zend_ini_entry), 1);
147
148 Z_PTR_P(zv) = new_entry;
149 memcpy(new_entry, old_entry, sizeof(zend_ini_entry));
150 if (old_entry->name) {
151 new_entry->name = zend_string_dup(old_entry->name, 1);
152 }
153 if (old_entry->value) {
154 new_entry->value = zend_string_dup(old_entry->value, 1);
155 }
156 if (old_entry->orig_value) {
157 new_entry->orig_value = zend_string_dup(old_entry->orig_value, 1);
158 }
159 }
160 /* }}} */
161
zend_copy_ini_directives(void)162 ZEND_API int zend_copy_ini_directives(void) /* {{{ */
163 {
164 EG(modified_ini_directives) = NULL;
165 EG(error_reporting_ini_entry) = NULL;
166 EG(ini_directives) = (HashTable *) malloc(sizeof(HashTable));
167 zend_hash_init_ex(EG(ini_directives), registered_zend_ini_directives->nNumOfElements, NULL, free_ini_entry, 1, 0);
168 zend_hash_copy(EG(ini_directives), registered_zend_ini_directives, copy_ini_entry);
169 return SUCCESS;
170 }
171 /* }}} */
172 #endif
173
ini_key_compare(const void * a,const void * b)174 static int ini_key_compare(const void *a, const void *b) /* {{{ */
175 {
176 const Bucket *f;
177 const Bucket *s;
178
179 f = (const Bucket *) a;
180 s = (const Bucket *) b;
181
182 if (!f->key && !s->key) { /* both numeric */
183 if (f->h > s->h) {
184 return -1;
185 } else if (f->h < s->h) {
186 return 1;
187 }
188 return 0;
189 } else if (!f->key) { /* f is numeric, s is not */
190 return -1;
191 } else if (!s->key) { /* s is numeric, f is not */
192 return 1;
193 } else { /* both strings */
194 return zend_binary_strcasecmp(ZSTR_VAL(f->key), ZSTR_LEN(f->key), ZSTR_VAL(s->key), ZSTR_LEN(s->key));
195 }
196 }
197 /* }}} */
198
zend_ini_sort_entries(void)199 ZEND_API void zend_ini_sort_entries(void) /* {{{ */
200 {
201 zend_hash_sort(EG(ini_directives), ini_key_compare, 0);
202 }
203 /* }}} */
204
205 /*
206 * Registration / unregistration
207 */
zend_register_ini_entries(const zend_ini_entry_def * ini_entry,int module_number)208 ZEND_API int zend_register_ini_entries(const zend_ini_entry_def *ini_entry, int module_number) /* {{{ */
209 {
210 zend_ini_entry *p;
211 zval *default_value;
212 HashTable *directives = registered_zend_ini_directives;
213
214 #ifdef ZTS
215 /* if we are called during the request, eg: from dl(),
216 * then we should not touch the global directives table,
217 * and should update the per-(request|thread) version instead.
218 * This solves two problems: one is that ini entries for dl()'d
219 * extensions will now work, and the second is that updating the
220 * global hash here from dl() is not mutex protected and can
221 * lead to death.
222 */
223 if (directives != EG(ini_directives)) {
224 directives = EG(ini_directives);
225 }
226 #endif
227
228 while (ini_entry->name) {
229 p = pemalloc(sizeof(zend_ini_entry), 1);
230 p->name = zend_string_init_interned(ini_entry->name, ini_entry->name_length, 1);
231 p->on_modify = ini_entry->on_modify;
232 p->mh_arg1 = ini_entry->mh_arg1;
233 p->mh_arg2 = ini_entry->mh_arg2;
234 p->mh_arg3 = ini_entry->mh_arg3;
235 p->value = NULL;
236 p->orig_value = NULL;
237 p->displayer = ini_entry->displayer;
238 p->modifiable = ini_entry->modifiable;
239
240 p->orig_modifiable = 0;
241 p->modified = 0;
242 p->module_number = module_number;
243
244 if (zend_hash_add_ptr(directives, p->name, (void*)p) == NULL) {
245 if (p->name) {
246 zend_string_release_ex(p->name, 1);
247 }
248 zend_unregister_ini_entries(module_number);
249 return FAILURE;
250 }
251 if (((default_value = zend_get_configuration_directive(p->name)) != NULL) &&
252 (!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)) {
253
254 p->value = zend_new_interned_string(zend_string_copy(Z_STR_P(default_value)));
255 } else {
256 p->value = ini_entry->value ?
257 zend_string_init_interned(ini_entry->value, ini_entry->value_length, 1) : NULL;
258
259 if (p->on_modify) {
260 p->on_modify(p, p->value, p->mh_arg1, p->mh_arg2, p->mh_arg3, ZEND_INI_STAGE_STARTUP);
261 }
262 }
263 ini_entry++;
264 }
265 return SUCCESS;
266 }
267 /* }}} */
268
zend_unregister_ini_entries(int module_number)269 ZEND_API void zend_unregister_ini_entries(int module_number) /* {{{ */
270 {
271 zend_hash_apply_with_argument(registered_zend_ini_directives, zend_remove_ini_entries, (void *) &module_number);
272 }
273 /* }}} */
274
275 #ifdef ZTS
zend_ini_refresh_caches(int stage)276 ZEND_API void zend_ini_refresh_caches(int stage) /* {{{ */
277 {
278 zend_ini_entry *p;
279
280 ZEND_HASH_FOREACH_PTR(EG(ini_directives), p) {
281 if (p->on_modify) {
282 p->on_modify(p, p->value, p->mh_arg1, p->mh_arg2, p->mh_arg3, stage);
283 }
284 } ZEND_HASH_FOREACH_END();
285 }
286 /* }}} */
287 #endif
288
zend_alter_ini_entry(zend_string * name,zend_string * new_value,int modify_type,int stage)289 ZEND_API int zend_alter_ini_entry(zend_string *name, zend_string *new_value, int modify_type, int stage) /* {{{ */
290 {
291
292 return zend_alter_ini_entry_ex(name, new_value, modify_type, stage, 0);
293 }
294 /* }}} */
295
zend_alter_ini_entry_chars(zend_string * name,const char * value,size_t value_length,int modify_type,int stage)296 ZEND_API int zend_alter_ini_entry_chars(zend_string *name, const char *value, size_t value_length, int modify_type, int stage) /* {{{ */
297 {
298 int ret;
299 zend_string *new_value;
300
301 new_value = zend_string_init(value, value_length, !(stage & ZEND_INI_STAGE_IN_REQUEST));
302 ret = zend_alter_ini_entry_ex(name, new_value, modify_type, stage, 0);
303 zend_string_release(new_value);
304 return ret;
305 }
306 /* }}} */
307
zend_alter_ini_entry_chars_ex(zend_string * name,const char * value,size_t value_length,int modify_type,int stage,int force_change)308 ZEND_API int zend_alter_ini_entry_chars_ex(zend_string *name, const char *value, size_t value_length, int modify_type, int stage, int force_change) /* {{{ */
309 {
310 int ret;
311 zend_string *new_value;
312
313 new_value = zend_string_init(value, value_length, !(stage & ZEND_INI_STAGE_IN_REQUEST));
314 ret = zend_alter_ini_entry_ex(name, new_value, modify_type, stage, force_change);
315 zend_string_release(new_value);
316 return ret;
317 }
318 /* }}} */
319
zend_alter_ini_entry_ex(zend_string * name,zend_string * new_value,int modify_type,int stage,int force_change)320 ZEND_API int zend_alter_ini_entry_ex(zend_string *name, zend_string *new_value, int modify_type, int stage, int force_change) /* {{{ */
321 {
322 zend_ini_entry *ini_entry;
323 zend_string *duplicate;
324 uint8_t modifiable;
325 zend_bool modified;
326
327 if ((ini_entry = zend_hash_find_ptr(EG(ini_directives), name)) == NULL) {
328 return FAILURE;
329 }
330
331 modifiable = ini_entry->modifiable;
332 modified = ini_entry->modified;
333
334 if (stage == ZEND_INI_STAGE_ACTIVATE && modify_type == ZEND_INI_SYSTEM) {
335 ini_entry->modifiable = ZEND_INI_SYSTEM;
336 }
337
338 if (!force_change) {
339 if (!(ini_entry->modifiable & modify_type)) {
340 return FAILURE;
341 }
342 }
343
344 if (!EG(modified_ini_directives)) {
345 ALLOC_HASHTABLE(EG(modified_ini_directives));
346 zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
347 }
348 if (!modified) {
349 ini_entry->orig_value = ini_entry->value;
350 ini_entry->orig_modifiable = modifiable;
351 ini_entry->modified = 1;
352 zend_hash_add_ptr(EG(modified_ini_directives), ini_entry->name, ini_entry);
353 }
354
355 duplicate = zend_string_copy(new_value);
356
357 if (!ini_entry->on_modify
358 || ini_entry->on_modify(ini_entry, duplicate, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage) == SUCCESS) {
359 if (modified && ini_entry->orig_value != ini_entry->value) { /* we already changed the value, free the changed value */
360 zend_string_release(ini_entry->value);
361 }
362 ini_entry->value = duplicate;
363 } else {
364 zend_string_release(duplicate);
365 return FAILURE;
366 }
367
368 return SUCCESS;
369 }
370 /* }}} */
371
zend_restore_ini_entry(zend_string * name,int stage)372 ZEND_API int zend_restore_ini_entry(zend_string *name, int stage) /* {{{ */
373 {
374 zend_ini_entry *ini_entry;
375
376 if ((ini_entry = zend_hash_find_ptr(EG(ini_directives), name)) == NULL ||
377 (stage == ZEND_INI_STAGE_RUNTIME && (ini_entry->modifiable & ZEND_INI_USER) == 0)) {
378 return FAILURE;
379 }
380
381 if (EG(modified_ini_directives)) {
382 if (zend_restore_ini_entry_cb(ini_entry, stage) == 0) {
383 zend_hash_del(EG(modified_ini_directives), name);
384 } else {
385 return FAILURE;
386 }
387 }
388
389 return SUCCESS;
390 }
391 /* }}} */
392
zend_ini_register_displayer(char * name,uint32_t name_length,void (* displayer)(zend_ini_entry * ini_entry,int type))393 ZEND_API int zend_ini_register_displayer(char *name, uint32_t name_length, void (*displayer)(zend_ini_entry *ini_entry, int type)) /* {{{ */
394 {
395 zend_ini_entry *ini_entry;
396
397 ini_entry = zend_hash_str_find_ptr(registered_zend_ini_directives, name, name_length);
398 if (ini_entry == NULL) {
399 return FAILURE;
400 }
401
402 ini_entry->displayer = displayer;
403 return SUCCESS;
404 }
405 /* }}} */
406
407 /*
408 * Data retrieval
409 */
410
zend_ini_long(char * name,size_t name_length,int orig)411 ZEND_API zend_long zend_ini_long(char *name, size_t name_length, int orig) /* {{{ */
412 {
413 zend_ini_entry *ini_entry;
414
415 ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length);
416 if (ini_entry) {
417 if (orig && ini_entry->modified) {
418 return (ini_entry->orig_value ? ZEND_STRTOL(ZSTR_VAL(ini_entry->orig_value), NULL, 0) : 0);
419 } else {
420 return (ini_entry->value ? ZEND_STRTOL(ZSTR_VAL(ini_entry->value), NULL, 0) : 0);
421 }
422 }
423
424 return 0;
425 }
426 /* }}} */
427
zend_ini_double(char * name,size_t name_length,int orig)428 ZEND_API double zend_ini_double(char *name, size_t name_length, int orig) /* {{{ */
429 {
430 zend_ini_entry *ini_entry;
431
432 ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length);
433 if (ini_entry) {
434 if (orig && ini_entry->modified) {
435 return (double) (ini_entry->orig_value ? zend_strtod(ZSTR_VAL(ini_entry->orig_value), NULL) : 0.0);
436 } else {
437 return (double) (ini_entry->value ? zend_strtod(ZSTR_VAL(ini_entry->value), NULL) : 0.0);
438 }
439 }
440
441 return 0.0;
442 }
443 /* }}} */
444
zend_ini_string_ex(char * name,size_t name_length,int orig,zend_bool * exists)445 ZEND_API char *zend_ini_string_ex(char *name, size_t name_length, int orig, zend_bool *exists) /* {{{ */
446 {
447 zend_ini_entry *ini_entry;
448
449 ini_entry = zend_hash_str_find_ptr(EG(ini_directives), name, name_length);
450 if (ini_entry) {
451 if (exists) {
452 *exists = 1;
453 }
454
455 if (orig && ini_entry->modified) {
456 return ini_entry->orig_value ? ZSTR_VAL(ini_entry->orig_value) : NULL;
457 } else {
458 return ini_entry->value ? ZSTR_VAL(ini_entry->value) : NULL;
459 }
460 } else {
461 if (exists) {
462 *exists = 0;
463 }
464 return NULL;
465 }
466 }
467 /* }}} */
468
zend_ini_string(char * name,size_t name_length,int orig)469 ZEND_API char *zend_ini_string(char *name, size_t name_length, int orig) /* {{{ */
470 {
471 zend_bool exists = 1;
472 char *return_value;
473
474 return_value = zend_ini_string_ex(name, name_length, orig, &exists);
475 if (!exists) {
476 return NULL;
477 } else if (!return_value) {
478 return_value = "";
479 }
480 return return_value;
481 }
482 /* }}} */
483
zend_ini_get_value(zend_string * name)484 ZEND_API zend_string *zend_ini_get_value(zend_string *name) /* {{{ */
485 {
486 zend_ini_entry *ini_entry;
487
488 ini_entry = zend_hash_find_ptr(EG(ini_directives), name);
489 if (ini_entry) {
490 return ini_entry->value ? ini_entry->value : ZSTR_EMPTY_ALLOC();
491 } else {
492 return NULL;
493 }
494 }
495 /* }}} */
496
zend_ini_parse_bool(zend_string * str)497 ZEND_API zend_bool zend_ini_parse_bool(zend_string *str)
498 {
499 if ((ZSTR_LEN(str) == 4 && strcasecmp(ZSTR_VAL(str), "true") == 0)
500 || (ZSTR_LEN(str) == 3 && strcasecmp(ZSTR_VAL(str), "yes") == 0)
501 || (ZSTR_LEN(str) == 2 && strcasecmp(ZSTR_VAL(str), "on") == 0)) {
502 return 1;
503 } else {
504 return atoi(ZSTR_VAL(str)) != 0;
505 }
506 }
507
ZEND_INI_DISP(zend_ini_boolean_displayer_cb)508 ZEND_INI_DISP(zend_ini_boolean_displayer_cb) /* {{{ */
509 {
510 int value;
511 zend_string *tmp_value;
512
513 if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
514 tmp_value = (ini_entry->orig_value ? ini_entry->orig_value : NULL );
515 } else if (ini_entry->value) {
516 tmp_value = ini_entry->value;
517 } else {
518 tmp_value = NULL;
519 }
520
521 if (tmp_value) {
522 value = zend_ini_parse_bool(tmp_value);
523 } else {
524 value = 0;
525 }
526
527 if (value) {
528 ZEND_PUTS("On");
529 } else {
530 ZEND_PUTS("Off");
531 }
532 }
533 /* }}} */
534
ZEND_INI_DISP(zend_ini_color_displayer_cb)535 ZEND_INI_DISP(zend_ini_color_displayer_cb) /* {{{ */
536 {
537 char *value;
538
539 if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
540 value = ZSTR_VAL(ini_entry->orig_value);
541 } else if (ini_entry->value) {
542 value = ZSTR_VAL(ini_entry->value);
543 } else {
544 value = NULL;
545 }
546 if (value) {
547 if (zend_uv.html_errors) {
548 zend_printf("<font style=\"color: %s\">%s</font>", value, value);
549 } else {
550 ZEND_PUTS(value);
551 }
552 } else {
553 if (zend_uv.html_errors) {
554 ZEND_PUTS(NO_VALUE_HTML);
555 } else {
556 ZEND_PUTS(NO_VALUE_PLAINTEXT);
557 }
558 }
559 }
560 /* }}} */
561
ZEND_INI_DISP(display_link_numbers)562 ZEND_INI_DISP(display_link_numbers) /* {{{ */
563 {
564 char *value;
565
566 if (type == ZEND_INI_DISPLAY_ORIG && ini_entry->modified) {
567 value = ZSTR_VAL(ini_entry->orig_value);
568 } else if (ini_entry->value) {
569 value = ZSTR_VAL(ini_entry->value);
570 } else {
571 value = NULL;
572 }
573
574 if (value) {
575 if (atoi(value) == -1) {
576 ZEND_PUTS("Unlimited");
577 } else {
578 zend_printf("%s", value);
579 }
580 }
581 }
582 /* }}} */
583
584 /* Standard message handlers */
ZEND_INI_MH(OnUpdateBool)585 ZEND_API ZEND_INI_MH(OnUpdateBool) /* {{{ */
586 {
587 zend_bool *p;
588 #ifndef ZTS
589 char *base = (char *) mh_arg2;
590 #else
591 char *base;
592
593 base = (char *) ts_resource(*((int *) mh_arg2));
594 #endif
595
596 p = (zend_bool *) (base+(size_t) mh_arg1);
597
598 *p = zend_ini_parse_bool(new_value);
599 return SUCCESS;
600 }
601 /* }}} */
602
ZEND_INI_MH(OnUpdateLong)603 ZEND_API ZEND_INI_MH(OnUpdateLong) /* {{{ */
604 {
605 zend_long *p;
606 #ifndef ZTS
607 char *base = (char *) mh_arg2;
608 #else
609 char *base;
610
611 base = (char *) ts_resource(*((int *) mh_arg2));
612 #endif
613
614 p = (zend_long *) (base+(size_t) mh_arg1);
615
616 *p = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
617 return SUCCESS;
618 }
619 /* }}} */
620
ZEND_INI_MH(OnUpdateLongGEZero)621 ZEND_API ZEND_INI_MH(OnUpdateLongGEZero) /* {{{ */
622 {
623 zend_long *p, tmp;
624 #ifndef ZTS
625 char *base = (char *) mh_arg2;
626 #else
627 char *base;
628
629 base = (char *) ts_resource(*((int *) mh_arg2));
630 #endif
631
632 tmp = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value));
633 if (tmp < 0) {
634 return FAILURE;
635 }
636
637 p = (zend_long *) (base+(size_t) mh_arg1);
638 *p = tmp;
639
640 return SUCCESS;
641 }
642 /* }}} */
643
ZEND_INI_MH(OnUpdateReal)644 ZEND_API ZEND_INI_MH(OnUpdateReal) /* {{{ */
645 {
646 double *p;
647 #ifndef ZTS
648 char *base = (char *) mh_arg2;
649 #else
650 char *base;
651
652 base = (char *) ts_resource(*((int *) mh_arg2));
653 #endif
654
655 p = (double *) (base+(size_t) mh_arg1);
656
657 *p = zend_strtod(ZSTR_VAL(new_value), NULL);
658 return SUCCESS;
659 }
660 /* }}} */
661
ZEND_INI_MH(OnUpdateString)662 ZEND_API ZEND_INI_MH(OnUpdateString) /* {{{ */
663 {
664 char **p;
665 #ifndef ZTS
666 char *base = (char *) mh_arg2;
667 #else
668 char *base;
669
670 base = (char *) ts_resource(*((int *) mh_arg2));
671 #endif
672
673 p = (char **) (base+(size_t) mh_arg1);
674
675 *p = new_value ? ZSTR_VAL(new_value) : NULL;
676 return SUCCESS;
677 }
678 /* }}} */
679
ZEND_INI_MH(OnUpdateStringUnempty)680 ZEND_API ZEND_INI_MH(OnUpdateStringUnempty) /* {{{ */
681 {
682 char **p;
683 #ifndef ZTS
684 char *base = (char *) mh_arg2;
685 #else
686 char *base;
687
688 base = (char *) ts_resource(*((int *) mh_arg2));
689 #endif
690
691 if (new_value && !ZSTR_VAL(new_value)[0]) {
692 return FAILURE;
693 }
694
695 p = (char **) (base+(size_t) mh_arg1);
696
697 *p = new_value ? ZSTR_VAL(new_value) : NULL;
698 return SUCCESS;
699 }
700 /* }}} */
701