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