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