~ubuntu-branches/ubuntu/breezy/php5/breezy-security

« back to all changes in this revision

Viewing changes to Zend/zend_API.c

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-10-09 03:14:32 UTC
  • Revision ID: james.westby@ubuntu.com-20051009031432-kspik3lobxstafv9
Tags: upstream-5.0.5
ImportĀ upstreamĀ versionĀ 5.0.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   +----------------------------------------------------------------------+
 
3
   | Zend Engine                                                          |
 
4
   +----------------------------------------------------------------------+
 
5
   | Copyright (c) 1998-2004 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
   | Authors: Andi Gutmans <andi@zend.com>                                |
 
16
   |          Zeev Suraski <zeev@zend.com>                                |
 
17
   |          Andrei Zmievski <andrei@php.net>                            |
 
18
   +----------------------------------------------------------------------+
 
19
*/
 
20
 
 
21
/* $Id: zend_API.c,v 1.256.2.18 2005/07/25 20:26:49 helly Exp $ */
 
22
 
 
23
#include "zend.h"
 
24
#include "zend_execute.h"
 
25
#include "zend_API.h"
 
26
#include "zend_modules.h"
 
27
#include "zend_constants.h"
 
28
 
 
29
#ifdef HAVE_STDARG_H
 
30
#include <stdarg.h>
 
31
#endif
 
32
 
 
33
/* these variables are true statics/globals, and have to be mutex'ed on every access */
 
34
static int module_count=0;
 
35
ZEND_API HashTable module_registry;
 
36
 
 
37
/* this function doesn't check for too many parameters */
 
38
ZEND_API int zend_get_parameters(int ht, int param_count, ...)
 
39
{
 
40
        void **p;
 
41
        int arg_count;
 
42
        va_list ptr;
 
43
        zval **param, *param_ptr;
 
44
        TSRMLS_FETCH();
 
45
 
 
46
        p = EG(argument_stack).top_element-2;
 
47
        arg_count = (ulong) *p;
 
48
 
 
49
        if (param_count>arg_count) {
 
50
                return FAILURE;
 
51
        }
 
52
 
 
53
        va_start(ptr, param_count);
 
54
 
 
55
        while (param_count-->0) {
 
56
                param = va_arg(ptr, zval **);
 
57
                param_ptr = *(p-arg_count);
 
58
                if (!PZVAL_IS_REF(param_ptr) && param_ptr->refcount>1) {
 
59
                        zval *new_tmp;
 
60
 
 
61
                        ALLOC_ZVAL(new_tmp);
 
62
                        *new_tmp = *param_ptr;
 
63
                        zval_copy_ctor(new_tmp);
 
64
                        INIT_PZVAL(new_tmp);
 
65
                        param_ptr = new_tmp;
 
66
                        ((zval *) *(p-arg_count))->refcount--;
 
67
                        *(p-arg_count) = param_ptr;
 
68
                }
 
69
                *param = param_ptr;
 
70
                arg_count--;
 
71
        }
 
72
        va_end(ptr);
 
73
 
 
74
        return SUCCESS;
 
75
}
 
76
 
 
77
 
 
78
ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval **argument_array TSRMLS_DC)
 
79
{
 
80
        void **p;
 
81
        int arg_count;
 
82
        zval *param_ptr;
 
83
 
 
84
        p = EG(argument_stack).top_element-2;
 
85
        arg_count = (ulong) *p;
 
86
 
 
87
        if (param_count>arg_count) {
 
88
                return FAILURE;
 
89
        }
 
90
 
 
91
        while (param_count-->0) {
 
92
                param_ptr = *(p-arg_count);
 
93
                if (!PZVAL_IS_REF(param_ptr) && param_ptr->refcount>1) {
 
94
                        zval *new_tmp;
 
95
 
 
96
                        ALLOC_ZVAL(new_tmp);
 
97
                        *new_tmp = *param_ptr;
 
98
                        zval_copy_ctor(new_tmp);
 
99
                        INIT_PZVAL(new_tmp);
 
100
                        param_ptr = new_tmp;
 
101
                        ((zval *) *(p-arg_count))->refcount--;
 
102
                        *(p-arg_count) = param_ptr;
 
103
                }
 
104
                *(argument_array++) = param_ptr;
 
105
                arg_count--;
 
106
        }
 
107
 
 
108
        return SUCCESS;
 
109
}
 
110
 
 
111
 
 
112
 
 
113
 
 
114
/* Zend-optimized Extended functions */
 
115
/* this function doesn't check for too many parameters */
 
116
ZEND_API int zend_get_parameters_ex(int param_count, ...)
 
117
{
 
118
        void **p;
 
119
        int arg_count;
 
120
        va_list ptr;
 
121
        zval ***param;
 
122
        TSRMLS_FETCH();
 
123
 
 
124
        p = EG(argument_stack).top_element-2;
 
125
        arg_count = (ulong) *p;
 
126
 
 
127
        if (param_count>arg_count) {
 
128
                return FAILURE;
 
129
        }
 
130
 
 
131
        va_start(ptr, param_count);
 
132
        while (param_count-->0) {
 
133
                param = va_arg(ptr, zval ***);
 
134
                *param = (zval **) p-(arg_count--);
 
135
        }
 
136
        va_end(ptr);
 
137
 
 
138
        return SUCCESS;
 
139
}
 
140
 
 
141
 
 
142
ZEND_API int _zend_get_parameters_array_ex(int param_count, zval ***argument_array TSRMLS_DC)
 
143
{
 
144
        void **p;
 
145
        int arg_count;
 
146
 
 
147
        p = EG(argument_stack).top_element-2;
 
148
        arg_count = (ulong) *p;
 
149
 
 
150
        if (param_count>arg_count) {
 
151
                return FAILURE;
 
152
        }
 
153
 
 
154
        while (param_count-->0) {
 
155
                zval **value = (zval**)(p-arg_count);
 
156
 
 
157
                if (EG(ze1_compatibility_mode) && Z_TYPE_PP(value) == IS_OBJECT) {
 
158
                        zval *value_ptr;
 
159
                        char *class_name;
 
160
                        zend_uint class_name_len;
 
161
                        int dup;
 
162
                        
 
163
                        dup = zend_get_object_classname(*value, &class_name, &class_name_len TSRMLS_CC);
 
164
 
 
165
                        ALLOC_ZVAL(value_ptr);
 
166
                        *value_ptr = **value;
 
167
                        INIT_PZVAL(value_ptr);
 
168
                        zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
 
169
                        if(!dup) {
 
170
                                efree(class_name);
 
171
                        }
 
172
                        value_ptr->value.obj = Z_OBJ_HANDLER_PP(value, clone_obj)(*value TSRMLS_CC);
 
173
                        zval_ptr_dtor(value);
 
174
                        *value = value_ptr;
 
175
                }
 
176
                *(argument_array++) = value;
 
177
                arg_count--;
 
178
        }
 
179
 
 
180
        return SUCCESS;
 
181
}
 
182
 
 
183
 
 
184
ZEND_API void zend_wrong_param_count(TSRMLS_D)
 
185
{
 
186
        char *space;
 
187
        char *class_name = get_active_class_name(&space TSRMLS_CC);
 
188
        
 
189
        zend_error(E_WARNING, "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name(TSRMLS_C));
 
190
}
 
191
 
 
192
 
 
193
/* Argument parsing API -- andrei */
 
194
 
 
195
ZEND_API char *zend_zval_type_name(zval *arg)
 
196
{
 
197
        switch (Z_TYPE_P(arg)) {
 
198
                case IS_NULL:
 
199
                        return "null";
 
200
 
 
201
                case IS_LONG:
 
202
                        return "integer";
 
203
 
 
204
                case IS_DOUBLE:
 
205
                        return "double";
 
206
 
 
207
                case IS_STRING:
 
208
                        return "string";
 
209
 
 
210
                case IS_ARRAY:
 
211
                        return "array";
 
212
 
 
213
                case IS_OBJECT:
 
214
                        return "object";
 
215
 
 
216
                case IS_BOOL:
 
217
                        return "boolean";
 
218
 
 
219
                case IS_RESOURCE:
 
220
                        return "resource";
 
221
 
 
222
                default:
 
223
                        return "unknown";
 
224
        }
 
225
}
 
226
 
 
227
ZEND_API zend_class_entry *zend_get_class_entry(zval *zobject TSRMLS_DC)
 
228
{
 
229
        if (Z_OBJ_HT_P(zobject)->get_class_entry) {
 
230
                return Z_OBJ_HT_P(zobject)->get_class_entry(zobject TSRMLS_CC);
 
231
        } else {
 
232
                zend_error(E_ERROR, "Class entry requested for an object without PHP class");
 
233
                return NULL;
 
234
        }
 
235
}
 
236
 
 
237
/* returns 1 if you need to copy result, 0 if it's already a copy */
 
238
ZEND_API int zend_get_object_classname(zval *object, char **class_name, zend_uint *class_name_len TSRMLS_DC)
 
239
{
 
240
        if (Z_OBJ_HT_P(object)->get_class_name == NULL ||
 
241
                Z_OBJ_HT_P(object)->get_class_name(object, class_name, class_name_len, 0 TSRMLS_CC) != SUCCESS) {
 
242
                zend_class_entry *ce = Z_OBJCE_P(object);
 
243
                
 
244
                *class_name = ce->name;
 
245
                *class_name_len = ce->name_length;
 
246
                return 1;
 
247
        }
 
248
        return 0;
 
249
}
 
250
 
 
251
 
 
252
static char *zend_parse_arg_impl(zval **arg, va_list *va, char **spec TSRMLS_DC)
 
253
{
 
254
        char *spec_walk = *spec;
 
255
        char c = *spec_walk++;
 
256
        int return_null = 0;
 
257
 
 
258
        while (*spec_walk == '/' || *spec_walk == '!') {
 
259
                if (*spec_walk == '/') {
 
260
                        SEPARATE_ZVAL_IF_NOT_REF(arg);
 
261
                } else if (*spec_walk == '!' && Z_TYPE_PP(arg) == IS_NULL) {
 
262
                        return_null = 1;
 
263
                }
 
264
                spec_walk++;
 
265
        }
 
266
 
 
267
        switch (c) {
 
268
                case 'l':
 
269
                        {
 
270
                                long *p = va_arg(*va, long *);
 
271
                                switch (Z_TYPE_PP(arg)) {
 
272
                                        case IS_STRING:
 
273
                                                {
 
274
                                                        double d;
 
275
                                                        int type;
 
276
 
 
277
                                                        if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), p, &d, 0)) == 0) {
 
278
                                                                return "long";
 
279
                                                        } else if (type == IS_DOUBLE) {
 
280
                                                                *p = (long) d;
 
281
                                                        }
 
282
                                                }
 
283
                                                break;
 
284
 
 
285
                                        case IS_NULL:
 
286
                                        case IS_LONG:
 
287
                                        case IS_DOUBLE:
 
288
                                        case IS_BOOL:
 
289
                                                convert_to_long_ex(arg);
 
290
                                                *p = Z_LVAL_PP(arg);
 
291
                                                break;
 
292
 
 
293
                                        case IS_ARRAY:
 
294
                                        case IS_OBJECT:
 
295
                                        case IS_RESOURCE:
 
296
                                        default:
 
297
                                                return "long";
 
298
                                }
 
299
                        }
 
300
                        break;
 
301
 
 
302
                case 'd':
 
303
                        {
 
304
                                double *p = va_arg(*va, double *);
 
305
                                switch (Z_TYPE_PP(arg)) {
 
306
                                        case IS_STRING:
 
307
                                                {
 
308
                                                        long l;
 
309
                                                        int type;
 
310
 
 
311
                                                        if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &l, p, 0)) == 0) {
 
312
                                                                return "double";
 
313
                                                        } else if (type == IS_LONG) {
 
314
                                                                *p = (double) l;
 
315
                                                        }
 
316
                                                }
 
317
                                                break;
 
318
 
 
319
                                        case IS_NULL:
 
320
                                        case IS_LONG:
 
321
                                        case IS_DOUBLE:
 
322
                                        case IS_BOOL:
 
323
                                                convert_to_double_ex(arg);
 
324
                                                *p = Z_DVAL_PP(arg);
 
325
                                                break;
 
326
 
 
327
                                        case IS_ARRAY:
 
328
                                        case IS_OBJECT:
 
329
                                        case IS_RESOURCE:
 
330
                                        default:
 
331
                                                return "double";
 
332
                                }
 
333
                        }
 
334
                        break;
 
335
 
 
336
                case 's':
 
337
                        {
 
338
                                char **p = va_arg(*va, char **);
 
339
                                int *pl = va_arg(*va, int *);
 
340
                                switch (Z_TYPE_PP(arg)) {
 
341
                                        case IS_NULL:
 
342
                                                if (return_null) {
 
343
                                                        *p = NULL;
 
344
                                                        *pl = 0;
 
345
                                                        break;
 
346
                                                }
 
347
                                                /* break omitted intentionally */
 
348
 
 
349
                                        case IS_STRING:
 
350
                                        case IS_LONG:
 
351
                                        case IS_DOUBLE:
 
352
                                        case IS_BOOL:
 
353
                                                convert_to_string_ex(arg);
 
354
                                                *p = Z_STRVAL_PP(arg);
 
355
                                                *pl = Z_STRLEN_PP(arg);
 
356
                                                break;
 
357
                                        case IS_OBJECT: {
 
358
                                                if (Z_OBJ_HANDLER_PP(arg, cast_object)) {
 
359
                                                        SEPARATE_ZVAL_IF_NOT_REF(arg);
 
360
                                                        if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
 
361
                                                                *pl = Z_STRLEN_PP(arg);
 
362
                                                                *p = Z_STRVAL_PP(arg);
 
363
                                                                break;
 
364
                                                        }
 
365
                                                }
 
366
                                        }
 
367
                                                
 
368
                                        case IS_ARRAY:
 
369
                                        case IS_RESOURCE:
 
370
                                        default:
 
371
                                                return "string";
 
372
                                }
 
373
                        }
 
374
                        break;
 
375
 
 
376
                case 'b':
 
377
                        {
 
378
                                zend_bool *p = va_arg(*va, zend_bool *);
 
379
                                switch (Z_TYPE_PP(arg)) {
 
380
                                        case IS_NULL:
 
381
                                        case IS_STRING:
 
382
                                        case IS_LONG:
 
383
                                        case IS_DOUBLE:
 
384
                                        case IS_BOOL:
 
385
                                                convert_to_boolean_ex(arg);
 
386
                                                *p = Z_BVAL_PP(arg);
 
387
                                                break;
 
388
 
 
389
                                        case IS_ARRAY:
 
390
                                        case IS_OBJECT:
 
391
                                        case IS_RESOURCE:
 
392
                                        default:
 
393
                                                return "boolean";
 
394
                                }
 
395
                        }
 
396
                        break;
 
397
 
 
398
                case 'r':
 
399
                        {
 
400
                                zval **p = va_arg(*va, zval **);
 
401
                                if (Z_TYPE_PP(arg) != IS_RESOURCE) {
 
402
                                        if (Z_TYPE_PP(arg) == IS_NULL && return_null) {
 
403
                                                *p = NULL;
 
404
                                        } else {
 
405
                                                return "resource";
 
406
                                        }
 
407
                                } else
 
408
                                        *p = *arg;
 
409
                        }
 
410
                        break;
 
411
 
 
412
                case 'a':
 
413
                        {
 
414
                                zval **p = va_arg(*va, zval **);
 
415
                                if (Z_TYPE_PP(arg) != IS_ARRAY) {
 
416
                                        if (Z_TYPE_PP(arg) == IS_NULL && return_null) {
 
417
                                                *p = NULL;
 
418
                                        } else {
 
419
                                                return "array";
 
420
                                        }
 
421
                                } else
 
422
                                        *p = *arg;
 
423
                        }
 
424
                        break;
 
425
 
 
426
                case 'o':
 
427
                        {
 
428
                                zval **p = va_arg(*va, zval **);
 
429
                                if (Z_TYPE_PP(arg) != IS_OBJECT) {
 
430
                                        if (Z_TYPE_PP(arg) == IS_NULL && return_null) {
 
431
                                                *p = NULL;
 
432
                                        } else {
 
433
                                                return "object";
 
434
                                        }
 
435
                                } else
 
436
                                        *p = *arg;
 
437
                        }
 
438
                        break;
 
439
 
 
440
                case 'O':
 
441
                        {
 
442
                                zval **p = va_arg(*va, zval **);
 
443
                                zend_class_entry *ce = va_arg(*va, zend_class_entry *);
 
444
 
 
445
                                if (Z_TYPE_PP(arg) == IS_OBJECT &&
 
446
                                                (!ce || instanceof_function(Z_OBJCE_PP(arg), ce TSRMLS_CC))) {
 
447
                                        *p = *arg;
 
448
                                } else {
 
449
                                        if (Z_TYPE_PP(arg) == IS_NULL && return_null) {
 
450
                                                *p = NULL;
 
451
                                        } else {
 
452
                                                return ce ? ce->name : "object";
 
453
                                        }
 
454
                                }
 
455
                        }
 
456
                        break;
 
457
 
 
458
                case 'z':
 
459
                        {
 
460
                                zval **p = va_arg(*va, zval **);
 
461
                                if (Z_TYPE_PP(arg) == IS_NULL && return_null) {
 
462
                                        *p = NULL;
 
463
                                } else {
 
464
                                        *p = *arg;
 
465
                                }
 
466
                        }
 
467
                        break;
 
468
                case 'Z':
 
469
                        {
 
470
                                zval ***p = va_arg(*va, zval ***);
 
471
                                if (Z_TYPE_PP(arg) == IS_NULL && return_null) {
 
472
                                        *p = NULL;
 
473
                                } else {
 
474
                                        *p = arg;
 
475
                                }
 
476
                        }
 
477
                        break;
 
478
                default:
 
479
                        return "unknown";
 
480
        }
 
481
 
 
482
        *spec = spec_walk;
 
483
 
 
484
        return NULL;
 
485
}
 
486
 
 
487
static int zend_parse_arg(int arg_num, zval **arg, va_list *va, char **spec, int quiet TSRMLS_DC)
 
488
{
 
489
        char *expected_type = NULL;
 
490
 
 
491
        expected_type = zend_parse_arg_impl(arg, va, spec TSRMLS_CC);
 
492
        if (expected_type) {
 
493
                if (!quiet) {
 
494
                        char *space;
 
495
                        char *class_name = get_active_class_name(&space TSRMLS_CC);
 
496
                        zend_error(E_WARNING, "%s%s%s() expects parameter %d to be %s, %s given",
 
497
                                        class_name, space, get_active_function_name(TSRMLS_C), arg_num, expected_type,
 
498
                                        zend_zval_type_name(*arg));
 
499
                }
 
500
                return FAILURE;
 
501
        }
 
502
        
 
503
        return SUCCESS;
 
504
}
 
505
 
 
506
static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int flags TSRMLS_DC)
 
507
{
 
508
        char *spec_walk;
 
509
        int c, i;
 
510
        int min_num_args = -1;
 
511
        int max_num_args = 0;
 
512
        zval **arg;
 
513
        void **p;
 
514
        int arg_count;
 
515
        int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
 
516
 
 
517
        for (spec_walk = type_spec; *spec_walk; spec_walk++) {
 
518
                c = *spec_walk;
 
519
                switch (c) {
 
520
                        case 'l': case 'd':
 
521
                        case 's': case 'b':
 
522
                        case 'r': case 'a':
 
523
                        case 'o': case 'O':
 
524
                        case 'z': case 'Z':
 
525
                                max_num_args++;
 
526
                                break;
 
527
 
 
528
                        case '|':
 
529
                                min_num_args = max_num_args;
 
530
                                break;
 
531
 
 
532
                        case '/':
 
533
                        case '!':
 
534
                                /* Pass */
 
535
                                break;
 
536
 
 
537
                        default:
 
538
                                if (!quiet) {
 
539
                                        zend_function *active_function = EG(function_state_ptr)->function;
 
540
                                        char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
 
541
                                        zend_error(E_WARNING, "%s%s%s(): bad type specifier while parsing parameters", 
 
542
                                                        class_name,
 
543
                                                        class_name[0] ? "::" : "",
 
544
                                                        get_active_function_name(TSRMLS_C));
 
545
                                }
 
546
                                return FAILURE;
 
547
                }
 
548
        }
 
549
 
 
550
        if (min_num_args < 0) {
 
551
                min_num_args = max_num_args;
 
552
        }
 
553
 
 
554
        if (num_args < min_num_args || num_args > max_num_args) {
 
555
                if (!quiet) {
 
556
                        zend_function *active_function = EG(function_state_ptr)->function;
 
557
                        char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
 
558
                        zend_error(E_WARNING, "%s%s%s() expects %s %d parameter%s, %d given",
 
559
                                        class_name,
 
560
                                        class_name[0] ? "::" : "",
 
561
                                        get_active_function_name(TSRMLS_C),
 
562
                                        min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
 
563
                                        num_args < min_num_args ? min_num_args : max_num_args,
 
564
                                        (num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
 
565
                                        num_args);
 
566
                }
 
567
                return FAILURE;
 
568
        }
 
569
 
 
570
        p = EG(argument_stack).top_element-2;
 
571
        arg_count = (ulong) *p;
 
572
 
 
573
        if (num_args > arg_count) {
 
574
                zend_error(E_WARNING, "%s(): could not obtain parameters for parsing",
 
575
                                   get_active_function_name(TSRMLS_C));
 
576
                return FAILURE;
 
577
        }
 
578
 
 
579
        i = 0;
 
580
        while (num_args-- > 0) {
 
581
                arg = (zval **) p - (arg_count-i);
 
582
                if (*type_spec == '|') {
 
583
                        type_spec++;
 
584
                }
 
585
                if (zend_parse_arg(i+1, arg, va, &type_spec, quiet TSRMLS_CC) == FAILURE) {
 
586
                        return FAILURE;
 
587
                }
 
588
                i++;
 
589
        }
 
590
 
 
591
        return SUCCESS;
 
592
}
 
593
 
 
594
ZEND_API int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...)
 
595
{
 
596
        va_list va;
 
597
        int retval;
 
598
        
 
599
        va_start(va, type_spec);
 
600
        retval = zend_parse_va_args(num_args, type_spec, &va, flags TSRMLS_CC);
 
601
        va_end(va);
 
602
 
 
603
        return retval;
 
604
}
 
605
 
 
606
ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...)
 
607
{
 
608
        va_list va;
 
609
        int retval;
 
610
        
 
611
        va_start(va, type_spec);
 
612
        retval = zend_parse_va_args(num_args, type_spec, &va, 0 TSRMLS_CC);
 
613
        va_end(va);
 
614
 
 
615
        return retval;
 
616
}
 
617
 
 
618
ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, ...)
 
619
{
 
620
        va_list va;
 
621
        int retval;
 
622
        char *p = type_spec;
 
623
        zval **object;
 
624
        zend_class_entry *ce;
 
625
 
 
626
        if (!this_ptr) {
 
627
                va_start(va, type_spec);
 
628
                retval = zend_parse_va_args(num_args, type_spec, &va, 0 TSRMLS_CC);
 
629
                va_end(va);
 
630
        } else {
 
631
                p++;
 
632
                va_start(va, type_spec);
 
633
 
 
634
                object = va_arg(va, zval **);
 
635
                ce = va_arg(va, zend_class_entry *);
 
636
                *object = this_ptr;
 
637
                if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) {
 
638
                        zend_error(E_CORE_ERROR, "%s::%s() must be derived from %s::%s",
 
639
                                ce->name, get_active_function_name(TSRMLS_C), Z_OBJCE_P(this_ptr)->name, get_active_function_name(TSRMLS_C));
 
640
                }
 
641
 
 
642
                retval = zend_parse_va_args(num_args, p, &va, 0 TSRMLS_CC);
 
643
                va_end(va);
 
644
        }
 
645
        return retval;
 
646
}
 
647
 
 
648
 
 
649
ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, ...)
 
650
{
 
651
        va_list va;
 
652
        int retval;
 
653
        char *p = type_spec;
 
654
        zval **object;
 
655
        zend_class_entry *ce;
 
656
        int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
 
657
 
 
658
        if (!this_ptr) {
 
659
                va_start(va, type_spec);
 
660
                retval = zend_parse_va_args(num_args, type_spec, &va, 0 TSRMLS_CC);
 
661
                va_end(va);
 
662
        } else {
 
663
                p++;
 
664
                va_start(va, type_spec);
 
665
 
 
666
                object = va_arg(va, zval **);
 
667
                ce = va_arg(va, zend_class_entry *);
 
668
                *object = this_ptr;
 
669
                if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) {
 
670
                        if (!quiet) {
 
671
                                zend_error(E_CORE_ERROR, "%s::%s() must be derived from %s::%s",
 
672
                                        ce->name, get_active_function_name(TSRMLS_C), Z_OBJCE_P(this_ptr)->name, get_active_function_name(TSRMLS_C));
 
673
                        }
 
674
                        return FAILURE;
 
675
                }
 
676
 
 
677
                retval = zend_parse_va_args(num_args, p, &va, flags TSRMLS_CC);
 
678
                va_end(va);
 
679
        }
 
680
        return retval;
 
681
}
 
682
 
 
683
 
 
684
/* Argument parsing API -- andrei */
 
685
 
 
686
 
 
687
ZEND_API int _array_init(zval *arg ZEND_FILE_LINE_DC)
 
688
{
 
689
        ALLOC_HASHTABLE_REL(arg->value.ht);
 
690
 
 
691
        _zend_hash_init(arg->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0 ZEND_FILE_LINE_RELAY_CC);
 
692
        arg->type = IS_ARRAY;
 
693
        return SUCCESS;
 
694
}
 
695
 
 
696
 
 
697
static int zend_merge_property(zval **value, int num_args, va_list args, zend_hash_key *hash_key)
 
698
{
 
699
        /* which name should a numeric property have ? */
 
700
        if (hash_key->nKeyLength) {
 
701
                zval *obj = va_arg(args, zval *);
 
702
                zend_object_handlers *obj_ht = va_arg(args, zend_object_handlers *);
 
703
                zval member;
 
704
                TSRMLS_FETCH();
 
705
 
 
706
                ZVAL_STRINGL(&member, hash_key->arKey, hash_key->nKeyLength-1, 0);
 
707
                obj_ht->write_property(obj, &member, *value TSRMLS_CC);
 
708
        }
 
709
        return ZEND_HASH_APPLY_KEEP;
 
710
}
 
711
 
 
712
 
 
713
/* This function should be called after the constructor has been called 
 
714
 * because it may call __set from the uninitialized object otherwise. */
 
715
ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destroy_ht TSRMLS_DC)
 
716
{
 
717
        zend_object_handlers *obj_ht = Z_OBJ_HT_P(obj);
 
718
        zend_class_entry *old_scope = EG(scope);
 
719
 
 
720
        EG(scope) = Z_OBJCE_P(obj);
 
721
        zend_hash_apply_with_arguments(properties, (apply_func_args_t)zend_merge_property, 2, obj, obj_ht);
 
722
        EG(scope) = old_scope;
 
723
 
 
724
        if (destroy_ht) {
 
725
                zend_hash_destroy(properties);
 
726
                FREE_HASHTABLE(properties);
 
727
        }
 
728
}
 
729
 
 
730
 
 
731
ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC)
 
732
{
 
733
        if (!class_type->constants_updated) {
 
734
                zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
 
735
                zend_class_entry *old_scope = *scope;
 
736
 
 
737
                *scope = class_type;
 
738
                zend_hash_apply_with_argument(&class_type->default_properties, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
 
739
                zend_hash_apply_with_argument(class_type->static_members, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
 
740
                *scope = old_scope;
 
741
                class_type->constants_updated = 1;
 
742
        }
 
743
}
 
744
 
 
745
 
 
746
/* This function requires 'properties' to contain all props declared in the
 
747
 * class and all props being public. If only a subset is given or the class 
 
748
 * has protected members then you need to merge the properties seperately by
 
749
 * calling zend_merge_properties(). */
 
750
ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC)
 
751
{
 
752
        zval *tmp;
 
753
        zend_object *object;
 
754
 
 
755
        if (class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
 
756
                char *what = class_type->ce_flags & ZEND_ACC_INTERFACE ? "interface" : "abstract class";
 
757
                zend_error(E_ERROR, "Cannot instantiate %s %s", what, class_type->name);
 
758
        }
 
759
 
 
760
        zend_update_class_constants(class_type TSRMLS_CC);
 
761
        
 
762
        arg->type = IS_OBJECT;
 
763
        if (class_type->create_object == NULL) {
 
764
                arg->value.obj = zend_objects_new(&object, class_type TSRMLS_CC);
 
765
                if (properties) {
 
766
                        object->properties = properties;
 
767
                } else {
 
768
                        ALLOC_HASHTABLE_REL(object->properties);
 
769
                        zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
 
770
                        zend_hash_copy(object->properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
 
771
                }
 
772
        } else {
 
773
                arg->value.obj = class_type->create_object(class_type TSRMLS_CC);
 
774
        }
 
775
        return SUCCESS;
 
776
}
 
777
 
 
778
ZEND_API int _object_init_ex(zval *arg, zend_class_entry *class_type ZEND_FILE_LINE_DC TSRMLS_DC)
 
779
{
 
780
        return _object_and_properties_init(arg, class_type, 0 ZEND_FILE_LINE_RELAY_CC TSRMLS_CC);
 
781
}
 
782
 
 
783
ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC TSRMLS_DC)
 
784
{
 
785
        return _object_init_ex(arg, zend_standard_class_def ZEND_FILE_LINE_RELAY_CC TSRMLS_CC);
 
786
}
 
787
 
 
788
 
 
789
ZEND_API int add_assoc_function(zval *arg, char *key, void (*function_ptr)(INTERNAL_FUNCTION_PARAMETERS))
 
790
{
 
791
        zend_error(E_WARNING, "add_assoc_function() is no longer supported");
 
792
        return FAILURE;
 
793
}
 
794
 
 
795
 
 
796
ZEND_API int add_assoc_long_ex(zval *arg, char *key, uint key_len, long n)
 
797
{
 
798
        zval *tmp;
 
799
 
 
800
        MAKE_STD_ZVAL(tmp);
 
801
        ZVAL_LONG(tmp, n);
 
802
        
 
803
        return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
 
804
}
 
805
 
 
806
ZEND_API int add_assoc_null_ex(zval *arg, char *key, uint key_len)
 
807
{
 
808
        zval *tmp;
 
809
        
 
810
        MAKE_STD_ZVAL(tmp);
 
811
        ZVAL_NULL(tmp);
 
812
        
 
813
        return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
 
814
}
 
815
 
 
816
ZEND_API int add_assoc_bool_ex(zval *arg, char *key, uint key_len, int b)
 
817
{
 
818
        zval *tmp;
 
819
        
 
820
        MAKE_STD_ZVAL(tmp);
 
821
        ZVAL_BOOL(tmp, b);
 
822
 
 
823
        return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
 
824
}
 
825
 
 
826
ZEND_API int add_assoc_resource_ex(zval *arg, char *key, uint key_len, int r)
 
827
{
 
828
        zval *tmp;
 
829
        
 
830
        MAKE_STD_ZVAL(tmp);
 
831
        ZVAL_RESOURCE(tmp, r);
 
832
        
 
833
        return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
 
834
}
 
835
 
 
836
 
 
837
ZEND_API int add_assoc_double_ex(zval *arg, char *key, uint key_len, double d)
 
838
{
 
839
        zval *tmp;
 
840
        
 
841
        MAKE_STD_ZVAL(tmp);
 
842
        ZVAL_DOUBLE(tmp, d);
 
843
 
 
844
        return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
 
845
}
 
846
 
 
847
 
 
848
ZEND_API int add_assoc_string_ex(zval *arg, char *key, uint key_len, char *str, int duplicate)
 
849
{
 
850
        zval *tmp;
 
851
        
 
852
        MAKE_STD_ZVAL(tmp);
 
853
        ZVAL_STRING(tmp, str, duplicate);
 
854
 
 
855
        return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
 
856
}
 
857
 
 
858
 
 
859
ZEND_API int add_assoc_stringl_ex(zval *arg, char *key, uint key_len, char *str, uint length, int duplicate)
 
860
{
 
861
        zval *tmp;
 
862
        
 
863
        MAKE_STD_ZVAL(tmp);
 
864
        ZVAL_STRINGL(tmp, str, length, duplicate);
 
865
 
 
866
        return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
 
867
}
 
868
 
 
869
ZEND_API int add_assoc_zval_ex(zval *arg, char *key, uint key_len, zval *value)
 
870
{
 
871
        return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &value, sizeof(zval *), NULL);
 
872
}
 
873
 
 
874
 
 
875
ZEND_API int add_index_long(zval *arg, uint index, long n)
 
876
{
 
877
        zval *tmp;
 
878
 
 
879
        MAKE_STD_ZVAL(tmp);
 
880
        ZVAL_LONG(tmp, n);
 
881
 
 
882
        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
 
883
}
 
884
 
 
885
 
 
886
ZEND_API int add_index_null(zval *arg, uint index)
 
887
{
 
888
        zval *tmp;
 
889
 
 
890
        MAKE_STD_ZVAL(tmp);
 
891
        ZVAL_NULL(tmp);
 
892
 
 
893
        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
 
894
}
 
895
 
 
896
ZEND_API int add_index_bool(zval *arg, uint index, int b)
 
897
{
 
898
        zval *tmp;
 
899
        
 
900
        MAKE_STD_ZVAL(tmp);
 
901
        ZVAL_BOOL(tmp, b);
 
902
        
 
903
        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
 
904
}
 
905
 
 
906
 
 
907
ZEND_API int add_index_resource(zval *arg, uint index, int r)
 
908
{
 
909
        zval *tmp;
 
910
        
 
911
        MAKE_STD_ZVAL(tmp);
 
912
        ZVAL_RESOURCE(tmp, r);
 
913
        
 
914
        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
 
915
}
 
916
 
 
917
 
 
918
ZEND_API int add_index_double(zval *arg, uint index, double d)
 
919
{
 
920
        zval *tmp;
 
921
        
 
922
        MAKE_STD_ZVAL(tmp);
 
923
        ZVAL_DOUBLE(tmp, d);
 
924
        
 
925
        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
 
926
}
 
927
 
 
928
 
 
929
ZEND_API int add_index_string(zval *arg, uint index, char *str, int duplicate)
 
930
{
 
931
        zval *tmp;
 
932
        
 
933
        MAKE_STD_ZVAL(tmp);
 
934
        ZVAL_STRING(tmp, str, duplicate);
 
935
 
 
936
        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
 
937
}
 
938
 
 
939
 
 
940
ZEND_API int add_index_stringl(zval *arg, uint index, char *str, uint length, int duplicate)
 
941
{
 
942
        zval *tmp;
 
943
        
 
944
        MAKE_STD_ZVAL(tmp);
 
945
        ZVAL_STRINGL(tmp, str, length, duplicate);
 
946
        
 
947
        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
 
948
}
 
949
 
 
950
 
 
951
ZEND_API int add_index_zval(zval *arg, uint index, zval *value)
 
952
{
 
953
        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &value, sizeof(zval *), NULL);
 
954
}
 
955
 
 
956
 
 
957
ZEND_API int add_next_index_long(zval *arg, long n)
 
958
{
 
959
        zval *tmp;
 
960
        
 
961
        MAKE_STD_ZVAL(tmp);
 
962
        ZVAL_LONG(tmp, n);
 
963
        
 
964
        return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
 
965
}
 
966
 
 
967
 
 
968
ZEND_API int add_next_index_null(zval *arg)
 
969
{
 
970
        zval *tmp;
 
971
        
 
972
        MAKE_STD_ZVAL(tmp);
 
973
        ZVAL_NULL(tmp);
 
974
        
 
975
        return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
 
976
}
 
977
 
 
978
 
 
979
ZEND_API int add_next_index_bool(zval *arg, int b)
 
980
{
 
981
        zval *tmp;
 
982
        
 
983
        MAKE_STD_ZVAL(tmp);
 
984
        ZVAL_BOOL(tmp, b);
 
985
        
 
986
        return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
 
987
}
 
988
 
 
989
 
 
990
ZEND_API int add_next_index_resource(zval *arg, int r)
 
991
{
 
992
        zval *tmp;
 
993
        
 
994
        MAKE_STD_ZVAL(tmp);
 
995
        ZVAL_RESOURCE(tmp, r);
 
996
        
 
997
        return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
 
998
}
 
999
 
 
1000
 
 
1001
ZEND_API int add_next_index_double(zval *arg, double d)
 
1002
{
 
1003
        zval *tmp;
 
1004
        
 
1005
        MAKE_STD_ZVAL(tmp);
 
1006
        ZVAL_DOUBLE(tmp, d);
 
1007
        
 
1008
        return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
 
1009
}
 
1010
 
 
1011
 
 
1012
ZEND_API int add_next_index_string(zval *arg, char *str, int duplicate)
 
1013
{
 
1014
        zval *tmp;
 
1015
 
 
1016
        MAKE_STD_ZVAL(tmp);
 
1017
        ZVAL_STRING(tmp, str, duplicate);
 
1018
 
 
1019
        return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
 
1020
}
 
1021
 
 
1022
 
 
1023
ZEND_API int add_next_index_stringl(zval *arg, char *str, uint length, int duplicate)
 
1024
{
 
1025
        zval *tmp;
 
1026
 
 
1027
        MAKE_STD_ZVAL(tmp);
 
1028
        ZVAL_STRINGL(tmp, str, length, duplicate);
 
1029
 
 
1030
        return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
 
1031
}
 
1032
 
 
1033
 
 
1034
ZEND_API int add_next_index_zval(zval *arg, zval *value)
 
1035
{
 
1036
        return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &value, sizeof(zval *), NULL);
 
1037
}
 
1038
 
 
1039
 
 
1040
ZEND_API int add_get_assoc_string_ex(zval *arg, char *key, uint key_len, char *str, void **dest, int duplicate)
 
1041
{
 
1042
        zval *tmp;
 
1043
        
 
1044
        MAKE_STD_ZVAL(tmp);
 
1045
        ZVAL_STRING(tmp, str, duplicate);
 
1046
        
 
1047
        return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), dest);
 
1048
}
 
1049
 
 
1050
 
 
1051
ZEND_API int add_get_assoc_stringl_ex(zval *arg, char *key, uint key_len, char *str, uint length, void **dest, int duplicate)
 
1052
{
 
1053
        zval *tmp;
 
1054
        
 
1055
        MAKE_STD_ZVAL(tmp);
 
1056
        ZVAL_STRINGL(tmp, str, length, duplicate);
 
1057
 
 
1058
        return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), dest);
 
1059
}
 
1060
 
 
1061
 
 
1062
ZEND_API int add_get_index_long(zval *arg, uint index, long l, void **dest)
 
1063
{
 
1064
        zval *tmp;
 
1065
        
 
1066
        MAKE_STD_ZVAL(tmp);
 
1067
        ZVAL_LONG(tmp, l);
 
1068
        
 
1069
        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
 
1070
}
 
1071
 
 
1072
 
 
1073
ZEND_API int add_get_index_double(zval *arg, uint index, double d, void **dest)
 
1074
{
 
1075
        zval *tmp;
 
1076
        
 
1077
        MAKE_STD_ZVAL(tmp);
 
1078
        ZVAL_DOUBLE(tmp, d);
 
1079
        
 
1080
        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
 
1081
}
 
1082
 
 
1083
 
 
1084
ZEND_API int add_get_index_string(zval *arg, uint index, char *str, void **dest, int duplicate)
 
1085
{
 
1086
        zval *tmp;
 
1087
        
 
1088
        MAKE_STD_ZVAL(tmp);
 
1089
        ZVAL_STRING(tmp, str, duplicate);
 
1090
        
 
1091
        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
 
1092
}
 
1093
 
 
1094
 
 
1095
ZEND_API int add_get_index_stringl(zval *arg, uint index, char *str, uint length, void **dest, int duplicate)
 
1096
{
 
1097
        zval *tmp;
 
1098
        
 
1099
        MAKE_STD_ZVAL(tmp);
 
1100
        ZVAL_STRINGL(tmp, str, length, duplicate);
 
1101
        
 
1102
        return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
 
1103
}
 
1104
 
 
1105
 
 
1106
ZEND_API int add_property_long_ex(zval *arg, char *key, uint key_len, long n TSRMLS_DC)
 
1107
{
 
1108
        zval *tmp;
 
1109
        zval z_key;
 
1110
 
 
1111
        MAKE_STD_ZVAL(tmp);
 
1112
        ZVAL_LONG(tmp, n);
 
1113
        ZVAL_STRINGL(&z_key, key, key_len-1, 0);
 
1114
 
 
1115
        Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, tmp TSRMLS_CC);
 
1116
        zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
 
1117
        return SUCCESS;
 
1118
}
 
1119
 
 
1120
ZEND_API int add_property_bool_ex(zval *arg, char *key, uint key_len, int b TSRMLS_DC)
 
1121
{
 
1122
        zval *tmp;
 
1123
        zval z_key;
 
1124
 
 
1125
        MAKE_STD_ZVAL(tmp);
 
1126
        ZVAL_BOOL(tmp, b);
 
1127
 
 
1128
        ZVAL_STRINGL(&z_key, key, key_len-1, 0);
 
1129
 
 
1130
        Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, tmp TSRMLS_CC);
 
1131
        zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
 
1132
        return SUCCESS;
 
1133
}
 
1134
 
 
1135
ZEND_API int add_property_null_ex(zval *arg, char *key, uint key_len TSRMLS_DC)
 
1136
{
 
1137
        zval *tmp;
 
1138
        zval z_key;
 
1139
        
 
1140
        MAKE_STD_ZVAL(tmp);
 
1141
        ZVAL_NULL(tmp);
 
1142
        
 
1143
        ZVAL_STRINGL(&z_key, key, key_len-1, 0);
 
1144
 
 
1145
        Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, tmp TSRMLS_CC);
 
1146
        zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
 
1147
        return SUCCESS;
 
1148
}
 
1149
 
 
1150
ZEND_API int add_property_resource_ex(zval *arg, char *key, uint key_len, long n TSRMLS_DC)
 
1151
{
 
1152
        zval *tmp;
 
1153
        zval z_key;
 
1154
        
 
1155
        MAKE_STD_ZVAL(tmp);
 
1156
        ZVAL_RESOURCE(tmp, n);
 
1157
        ZVAL_STRINGL(&z_key, key, key_len-1, 0);
 
1158
 
 
1159
        Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, tmp TSRMLS_CC);
 
1160
        zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
 
1161
        return SUCCESS;
 
1162
}
 
1163
 
 
1164
 
 
1165
ZEND_API int add_property_double_ex(zval *arg, char *key, uint key_len, double d TSRMLS_DC)
 
1166
{
 
1167
        zval *tmp;
 
1168
        zval z_key;
 
1169
 
 
1170
        MAKE_STD_ZVAL(tmp);
 
1171
        ZVAL_DOUBLE(tmp, d);
 
1172
        ZVAL_STRINGL(&z_key, key, key_len-1, 0);
 
1173
 
 
1174
        Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, tmp TSRMLS_CC);
 
1175
        zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
 
1176
        return SUCCESS;
 
1177
}
 
1178
 
 
1179
 
 
1180
ZEND_API int add_property_string_ex(zval *arg, char *key, uint key_len, char *str, int duplicate TSRMLS_DC)
 
1181
{
 
1182
        zval *tmp;
 
1183
        zval z_key;
 
1184
 
 
1185
        MAKE_STD_ZVAL(tmp);
 
1186
        ZVAL_STRING(tmp, str, duplicate);
 
1187
 
 
1188
        ZVAL_STRINGL(&z_key, key, key_len-1, 0);
 
1189
 
 
1190
        Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, tmp TSRMLS_CC);
 
1191
        zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
 
1192
        return SUCCESS;
 
1193
}
 
1194
 
 
1195
ZEND_API int add_property_stringl_ex(zval *arg, char *key, uint key_len, char *str, uint length, int duplicate TSRMLS_DC)
 
1196
{
 
1197
        zval *tmp;
 
1198
        zval z_key;
 
1199
 
 
1200
        MAKE_STD_ZVAL(tmp);
 
1201
        ZVAL_STRINGL(tmp, str, length, duplicate);
 
1202
 
 
1203
        ZVAL_STRINGL(&z_key, key, key_len-1, 0);
 
1204
 
 
1205
        Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, tmp TSRMLS_CC);
 
1206
        zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
 
1207
        return SUCCESS;
 
1208
}
 
1209
 
 
1210
ZEND_API int add_property_zval_ex(zval *arg, char *key, uint key_len, zval *value TSRMLS_DC)
 
1211
{
 
1212
        zval z_key;
 
1213
 
 
1214
        ZVAL_STRINGL(&z_key, key, key_len-1, 0);
 
1215
 
 
1216
        Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, value TSRMLS_CC);
 
1217
        return SUCCESS;
 
1218
}
 
1219
 
 
1220
ZEND_API int zend_register_module_ex(zend_module_entry *module TSRMLS_DC)
 
1221
{
 
1222
        int name_len;
 
1223
        char *lcname;
 
1224
        zend_module_entry *module_ptr;
 
1225
        
 
1226
        if (!module) {
 
1227
                return FAILURE;
 
1228
        }
 
1229
 
 
1230
#if 0
 
1231
        zend_printf("%s:  Registering module %d\n", module->name, module->module_number);
 
1232
#endif
 
1233
        name_len = strlen(module->name);
 
1234
        lcname = zend_str_tolower_dup(module->name, name_len);
 
1235
 
 
1236
        if (zend_hash_add(&module_registry, lcname, name_len+1, (void *)module, sizeof(zend_module_entry), (void**)&module_ptr)==FAILURE) {
 
1237
                zend_error(E_CORE_WARNING, "Module '%s' already loaded", module->name);
 
1238
                efree(lcname);
 
1239
                return FAILURE;
 
1240
        }
 
1241
        efree(lcname);
 
1242
        module = module_ptr;
 
1243
 
 
1244
        if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type TSRMLS_CC)==FAILURE) {
 
1245
                zend_error(E_CORE_WARNING,"%s:  Unable to register functions, unable to load", module->name);
 
1246
                return FAILURE;
 
1247
        }
 
1248
 
 
1249
        if (!module->module_started && module->module_startup_func) {
 
1250
                EG(current_module) = module;
 
1251
                if (module->module_startup_func(module->type, module->module_number TSRMLS_CC)==FAILURE) {
 
1252
                        zend_error(E_CORE_ERROR,"Unable to start %s module", module->name);
 
1253
                        EG(current_module) = NULL;
 
1254
                        return FAILURE;
 
1255
                }
 
1256
                EG(current_module) = NULL;
 
1257
        }
 
1258
 
 
1259
        module->module_started=1;
 
1260
 
 
1261
        return SUCCESS;
 
1262
}
 
1263
 
 
1264
ZEND_API int zend_startup_module(zend_module_entry *module)
 
1265
{
 
1266
        TSRMLS_FETCH();
 
1267
 
 
1268
        module->module_number = zend_next_free_module();
 
1269
        module->type = MODULE_PERSISTENT;
 
1270
        return zend_register_module_ex(module TSRMLS_CC);
 
1271
}
 
1272
 
 
1273
void zend_check_magic_method_implementation(zend_class_entry *ce, zend_function *fptr, int error_type TSRMLS_DC)
 
1274
{
 
1275
        char lcname[16];
 
1276
        int name_len;
 
1277
 
 
1278
        /* we don't care if the function name is longer, in fact lowercasing only 
 
1279
         * the beginning of the name speeds up the check process */
 
1280
        name_len = strlen(fptr->common.function_name);
 
1281
        zend_str_tolower_copy(lcname, fptr->common.function_name, MIN(name_len, sizeof(lcname)-1));
 
1282
        lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
 
1283
 
 
1284
        if (name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)) && fptr->common.num_args != 0) {
 
1285
                zend_error(error_type, "Destuctor %s::%s() cannot take arguments", ce->name, ZEND_DESTRUCTOR_FUNC_NAME);
 
1286
        } else if (name_len == sizeof(ZEND_CLONE_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)) && fptr->common.num_args != 0) {
 
1287
                zend_error(error_type, "Method %s::%s() cannot accept any arguments", ce->name, ZEND_CLONE_FUNC_NAME);
 
1288
        } else if (name_len == sizeof(ZEND_GET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)) && fptr->common.num_args != 1) {
 
1289
                zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_GET_FUNC_NAME);
 
1290
        } else if (name_len == sizeof(ZEND_SET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)) && fptr->common.num_args != 2) {
 
1291
                zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_SET_FUNC_NAME);
 
1292
        } else if (name_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)) && fptr->common.num_args != 2) {
 
1293
                zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_CALL_FUNC_NAME);
 
1294
        }
 
1295
}
 
1296
 
 
1297
/* registers all functions in *library_functions in the function hash */
 
1298
ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC)
 
1299
{
 
1300
        zend_function_entry *ptr = functions;
 
1301
        zend_function function, *reg_function;
 
1302
        zend_internal_function *internal_function = (zend_internal_function *)&function;
 
1303
        int count=0, unload=0;
 
1304
        HashTable *target_function_table = function_table;
 
1305
        int error_type;
 
1306
        zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__call = NULL;
 
1307
        char *lowercase_name;
 
1308
        int fname_len;
 
1309
        char *lc_class_name;
 
1310
        int class_name_len;
 
1311
 
 
1312
        if (type==MODULE_PERSISTENT) {
 
1313
                error_type = E_CORE_WARNING;
 
1314
        } else {
 
1315
                error_type = E_WARNING;
 
1316
        }
 
1317
 
 
1318
        if (!target_function_table) {
 
1319
                target_function_table = CG(function_table);
 
1320
        }
 
1321
        internal_function->type = ZEND_INTERNAL_FUNCTION;
 
1322
        
 
1323
        if (scope) {
 
1324
                class_name_len = strlen(scope->name);
 
1325
                lc_class_name = zend_str_tolower_dup(scope->name, class_name_len);
 
1326
        }
 
1327
 
 
1328
        while (ptr->fname) {
 
1329
                internal_function->handler = ptr->handler;
 
1330
                internal_function->function_name = ptr->fname;
 
1331
                internal_function->scope = scope;
 
1332
                internal_function->prototype = NULL;
 
1333
                if (ptr->arg_info) {
 
1334
                        internal_function->arg_info = ptr->arg_info+1;
 
1335
                        internal_function->num_args = ptr->num_args;
 
1336
                        /* Currently you cannot denote that the function can accept less arguments than num_args */
 
1337
                        if (ptr->arg_info[0].required_num_args == -1) {
 
1338
                                internal_function->required_num_args = ptr->num_args;
 
1339
                        } else {
 
1340
                                internal_function->required_num_args = ptr->arg_info[0].required_num_args;
 
1341
                        }
 
1342
                        internal_function->pass_rest_by_reference = ptr->arg_info[0].pass_by_reference;
 
1343
                        internal_function->return_reference = ptr->arg_info[0].return_reference;
 
1344
                } else {
 
1345
                        internal_function->arg_info = NULL;
 
1346
                        internal_function->num_args = 0;
 
1347
                        internal_function->required_num_args = 0;
 
1348
                        internal_function->pass_rest_by_reference = 0;
 
1349
                        internal_function->return_reference = 0;
 
1350
                }
 
1351
                if (ptr->flags) {
 
1352
                        if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
 
1353
                                zend_error(error_type, "Invalid access level for %s%s%s() - access must be exactly one of public, protected or private", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
 
1354
                                internal_function->fn_flags = ZEND_ACC_PUBLIC;
 
1355
                        } else {
 
1356
                                internal_function->fn_flags = ptr->flags;
 
1357
                        }
 
1358
                } else {
 
1359
                        internal_function->fn_flags = ZEND_ACC_PUBLIC;
 
1360
                }
 
1361
                if (ptr->flags & ZEND_ACC_ABSTRACT) {
 
1362
                        if (scope) {
 
1363
                                /* This is a class that must be abstract itself. Here we set the check info. */
 
1364
                                scope->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
 
1365
                                if (!(scope->ce_flags & ZEND_ACC_INTERFACE)) {
 
1366
                                        /* Since the class is not an interface it needs to be declared as a abstract class. */
 
1367
                                        /* Since here we are handling internal functions only we can add the keyword flag. */
 
1368
                                        /* This time we set the flag for the keyword 'abstratc'. */
 
1369
                                        scope->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
 
1370
                                }
 
1371
                        }
 
1372
                } else {
 
1373
                        if (scope && (scope->ce_flags & ZEND_ACC_INTERFACE)) {
 
1374
                                zend_error(error_type, "Interface %s cannot contain non abstract method %s()", scope->name, ptr->fname);
 
1375
                                return FAILURE;
 
1376
                        }
 
1377
                        if (!internal_function->handler) {
 
1378
                                zend_error(error_type, "Method %s%s%s() cannot be a NULL function", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
 
1379
                                zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
 
1380
                                return FAILURE;
 
1381
                        }
 
1382
                }
 
1383
                fname_len = strlen(ptr->fname);
 
1384
                lowercase_name = do_alloca(fname_len+1);
 
1385
                zend_str_tolower_copy(lowercase_name, ptr->fname, fname_len);
 
1386
                if (zend_hash_add(target_function_table, lowercase_name, fname_len+1, &function, sizeof(zend_function), (void**)&reg_function) == FAILURE) {
 
1387
                        unload=1;
 
1388
                        free_alloca(lowercase_name);
 
1389
                        break;
 
1390
                }
 
1391
                if (scope) {
 
1392
                        /* Look for ctor, dtor, clone
 
1393
                         * If it's an old-style constructor, store it only if we don't have
 
1394
                         * a constructor already.
 
1395
                         */
 
1396
                        if ((fname_len == class_name_len) && !memcmp(lowercase_name, lc_class_name, class_name_len+1) && !ctor) {
 
1397
                                ctor = reg_function;
 
1398
                        } else if ((fname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) {
 
1399
                                ctor = reg_function;
 
1400
                        } else if ((fname_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME))) {
 
1401
                                dtor = reg_function;
 
1402
                                if (internal_function->num_args) {
 
1403
                                        zend_error(error_type, "Destructor %s::%s() cannot take arguments", scope->name, ptr->fname);
 
1404
                                }
 
1405
                        } else if ((fname_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME))) {
 
1406
                                clone = reg_function;
 
1407
                        } else if ((fname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME))) {
 
1408
                                __call = reg_function;
 
1409
                        } else if ((fname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME))) {
 
1410
                                __get = reg_function;
 
1411
                        } else if ((fname_len == sizeof(ZEND_SET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME))) {
 
1412
                                __set = reg_function;
 
1413
                        } else {
 
1414
                                reg_function = NULL;
 
1415
                        }
 
1416
                        if (reg_function) {
 
1417
                                zend_check_magic_method_implementation(scope, reg_function, error_type TSRMLS_CC);
 
1418
                        }
 
1419
                }
 
1420
                ptr++;
 
1421
                count++;
 
1422
                free_alloca(lowercase_name);
 
1423
        }
 
1424
        if (unload) { /* before unloading, display all remaining bad function in the module */
 
1425
                if (scope) {
 
1426
                        efree(lc_class_name);
 
1427
                }
 
1428
                while (ptr->fname) {
 
1429
                        if (zend_hash_exists(target_function_table, ptr->fname, strlen(ptr->fname)+1)) {
 
1430
                                zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
 
1431
                        }
 
1432
                        ptr++;
 
1433
                }
 
1434
                zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
 
1435
                return FAILURE;
 
1436
        }
 
1437
        if (scope) {
 
1438
                scope->constructor = ctor;
 
1439
                scope->destructor = dtor;
 
1440
                scope->clone = clone;
 
1441
                scope->__call = __call;
 
1442
                scope->__get = __get;
 
1443
                scope->__set = __set;
 
1444
                if (ctor) {
 
1445
                        ctor->common.fn_flags |= ZEND_ACC_CTOR;
 
1446
                        if (ctor->common.fn_flags & ZEND_ACC_STATIC) {
 
1447
                                zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name, ctor->common.function_name);
 
1448
                        }
 
1449
                        ctor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
 
1450
                }
 
1451
                if (dtor) {
 
1452
                        dtor->common.fn_flags |= ZEND_ACC_DTOR;
 
1453
                        if (dtor->common.fn_flags & ZEND_ACC_STATIC) {
 
1454
                                zend_error(error_type, "Destructor %s::%s() cannot be static", scope->name, dtor->common.function_name);
 
1455
                        }
 
1456
                        dtor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
 
1457
                }
 
1458
                if (clone) {
 
1459
                        clone->common.fn_flags |= ZEND_ACC_CLONE;
 
1460
                        if (clone->common.fn_flags & ZEND_ACC_STATIC) {
 
1461
                                zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name, clone->common.function_name);
 
1462
                        }
 
1463
                        clone->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
 
1464
                }
 
1465
                if (__call) {
 
1466
                        if (__call->common.fn_flags & ZEND_ACC_STATIC) {
 
1467
                                zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __call->common.function_name);
 
1468
                        }
 
1469
                        __call->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
 
1470
                }
 
1471
                if (__get) {
 
1472
                        if (__get->common.fn_flags & ZEND_ACC_STATIC) {
 
1473
                                zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __get->common.function_name);
 
1474
                        }
 
1475
                        __get->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
 
1476
                }
 
1477
                if (__set) {
 
1478
                        if (__set->common.fn_flags & ZEND_ACC_STATIC) {
 
1479
                                zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __set->common.function_name);
 
1480
                        }
 
1481
                        __set->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
 
1482
                }
 
1483
                efree(lc_class_name);
 
1484
        }
 
1485
        return SUCCESS;
 
1486
}
 
1487
 
 
1488
/* count=-1 means erase all functions, otherwise, 
 
1489
 * erase the first count functions
 
1490
 */
 
1491
ZEND_API void zend_unregister_functions(zend_function_entry *functions, int count, HashTable *function_table TSRMLS_DC)
 
1492
{
 
1493
        zend_function_entry *ptr = functions;
 
1494
        int i=0;
 
1495
        HashTable *target_function_table = function_table;
 
1496
 
 
1497
        if (!target_function_table) {
 
1498
                target_function_table = CG(function_table);
 
1499
        }
 
1500
        while (ptr->fname) {
 
1501
                if (count!=-1 && i>=count) {
 
1502
                        break;
 
1503
                }
 
1504
#if 0
 
1505
                zend_printf("Unregistering %s()\n", ptr->fname);
 
1506
#endif
 
1507
                zend_hash_del(target_function_table, ptr->fname, strlen(ptr->fname)+1);
 
1508
                ptr++;
 
1509
                i++;
 
1510
        }
 
1511
}
 
1512
 
 
1513
 
 
1514
ZEND_API int zend_register_module(zend_module_entry *module)
 
1515
{
 
1516
        TSRMLS_FETCH();
 
1517
        
 
1518
        return zend_register_module_ex(module TSRMLS_CC);
 
1519
}
 
1520
 
 
1521
 
 
1522
ZEND_API int zend_get_module_started(char *module_name)
 
1523
{
 
1524
        zend_module_entry *module;
 
1525
        
 
1526
        return (zend_hash_find(&module_registry, module_name, strlen(module_name)+1, (void**)&module) == SUCCESS && module->module_started) ? SUCCESS : FAILURE;
 
1527
}
 
1528
 
 
1529
 
 
1530
void module_destructor(zend_module_entry *module)
 
1531
{
 
1532
        TSRMLS_FETCH();
 
1533
 
 
1534
        if (module->type == MODULE_TEMPORARY) {
 
1535
                zend_clean_module_rsrc_dtors(module->module_number TSRMLS_CC);
 
1536
                clean_module_constants(module->module_number TSRMLS_CC);
 
1537
        }
 
1538
 
 
1539
        if (module->module_started && module->module_shutdown_func) {
 
1540
#if 0
 
1541
                zend_printf("%s:  Module shutdown\n", module->name);
 
1542
#endif
 
1543
                module->module_shutdown_func(module->type, module->module_number TSRMLS_CC);
 
1544
        }
 
1545
        module->module_started=0;
 
1546
        if (module->functions) {
 
1547
                zend_unregister_functions(module->functions, -1, NULL TSRMLS_CC);
 
1548
        }
 
1549
 
 
1550
#if HAVE_LIBDL || defined(HAVE_MACH_O_DYLD_H)
 
1551
        if (module->handle) {
 
1552
                DL_UNLOAD(module->handle);
 
1553
        }
 
1554
#endif
 
1555
}
 
1556
 
 
1557
 
 
1558
/* call request startup for all modules */
 
1559
int module_registry_request_startup(zend_module_entry *module TSRMLS_DC)
 
1560
{
 
1561
        if (module->request_startup_func) {
 
1562
#if 0
 
1563
                zend_printf("%s:  Request startup\n", module->name);
 
1564
#endif
 
1565
                if (module->request_startup_func(module->type, module->module_number TSRMLS_CC)==FAILURE) {
 
1566
                        zend_error(E_WARNING, "request_startup() for %s module failed", module->name);
 
1567
                        exit(1);
 
1568
                }
 
1569
        }
 
1570
        return 0;
 
1571
}
 
1572
 
 
1573
 
 
1574
/* call request shutdown for all modules */
 
1575
int module_registry_cleanup(zend_module_entry *module TSRMLS_DC)
 
1576
{
 
1577
        if (module->request_shutdown_func) {
 
1578
#if 0
 
1579
                zend_printf("%s:  Request shutdown\n", module->name);
 
1580
#endif
 
1581
                module->request_shutdown_func(module->type, module->module_number TSRMLS_CC);
 
1582
        }
 
1583
        return 0;
 
1584
}
 
1585
 
 
1586
int module_registry_unload_temp(zend_module_entry *module TSRMLS_DC)
 
1587
{
 
1588
        switch (module->type) {
 
1589
                case MODULE_TEMPORARY:
 
1590
                        return 1;
 
1591
        }
 
1592
        return 0;
 
1593
}
 
1594
 
 
1595
 
 
1596
/* return the next free module number */
 
1597
int zend_next_free_module(void)
 
1598
{
 
1599
        return ++module_count;
 
1600
}
 
1601
 
 
1602
static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, zend_uint ce_flags TSRMLS_DC)
 
1603
{
 
1604
        zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
 
1605
        char *lowercase_name = malloc(orig_class_entry->name_length + 1);
 
1606
        *class_entry = *orig_class_entry;
 
1607
 
 
1608
        class_entry->type = ZEND_INTERNAL_CLASS;
 
1609
        zend_initialize_class_data(class_entry, 0 TSRMLS_CC);
 
1610
        class_entry->ce_flags = ce_flags;
 
1611
        class_entry->module = EG(current_module);
 
1612
 
 
1613
        if (class_entry->builtin_functions) {
 
1614
                zend_register_functions(class_entry, class_entry->builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC);
 
1615
        }
 
1616
 
 
1617
        zend_str_tolower_copy(lowercase_name, orig_class_entry->name, class_entry->name_length);
 
1618
        zend_hash_update(CG(class_table), lowercase_name, class_entry->name_length+1, &class_entry, sizeof(zend_class_entry *), NULL);
 
1619
        free(lowercase_name);
 
1620
        return class_entry;
 
1621
}
 
1622
 
 
1623
/* If parent_ce is not NULL then it inherits from parent_ce
 
1624
 * If parent_ce is NULL and parent_name isn't then it looks for the parent and inherits from it
 
1625
 * If both parent_ce and parent_name are NULL it does a regular class registration
 
1626
 * If parent_name is specified but not found NULL is returned
 
1627
 */
 
1628
ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce, char *parent_name TSRMLS_DC)
 
1629
{
 
1630
        zend_class_entry *register_class;
 
1631
 
 
1632
        if (!parent_ce && parent_name) {
 
1633
                zend_class_entry **pce;
 
1634
                if (zend_hash_find(CG(class_table), parent_name, strlen(parent_name)+1, (void **) &pce)==FAILURE) {
 
1635
                        return NULL;
 
1636
                } else {
 
1637
                        parent_ce = *pce;
 
1638
                }
 
1639
        }
 
1640
 
 
1641
        register_class = zend_register_internal_class(class_entry TSRMLS_CC);
 
1642
 
 
1643
        if (parent_ce) {
 
1644
                zend_do_inheritance(register_class, parent_ce TSRMLS_CC);
 
1645
        }
 
1646
        return register_class;
 
1647
}
 
1648
 
 
1649
ZEND_API void zend_class_implements(zend_class_entry *class_entry TSRMLS_DC, int num_interfaces, ...)
 
1650
{
 
1651
        zend_class_entry *interface_entry;
 
1652
        int ce_num = class_entry->num_interfaces, impl_num;
 
1653
        va_list interface_list;
 
1654
        va_start(interface_list, num_interfaces);
 
1655
 
 
1656
        if (class_entry->type & ZEND_INTERNAL_CLASS) {
 
1657
                class_entry->interfaces = realloc(class_entry->interfaces, sizeof(zend_class_entry*) * (class_entry->num_interfaces+num_interfaces));
 
1658
        } else {
 
1659
                class_entry->interfaces = erealloc(class_entry->interfaces, sizeof(zend_class_entry*) * (class_entry->num_interfaces+num_interfaces));
 
1660
        }
 
1661
        
 
1662
        while (num_interfaces--) {
 
1663
                interface_entry = va_arg(interface_list, zend_class_entry *);
 
1664
                class_entry->interfaces[class_entry->num_interfaces++] = interface_entry;
 
1665
        }
 
1666
        impl_num = class_entry->num_interfaces;
 
1667
        while(ce_num < impl_num) {
 
1668
                zend_do_implement_interface(class_entry, class_entry->interfaces[ce_num++] TSRMLS_CC);
 
1669
        }
 
1670
        va_end(interface_list);
 
1671
}
 
1672
 
 
1673
/* A class that contains at least one abstract method automatically becomes an abstract class.
 
1674
 */
 
1675
ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry TSRMLS_DC)
 
1676
{
 
1677
        return do_register_internal_class(orig_class_entry, 0 TSRMLS_CC);
 
1678
}
 
1679
 
 
1680
ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry TSRMLS_DC)
 
1681
{
 
1682
        return do_register_internal_class(orig_class_entry, ZEND_ACC_INTERFACE TSRMLS_CC);
 
1683
}
 
1684
 
 
1685
ZEND_API int zend_set_hash_symbol(zval *symbol, char *name, int name_length,
 
1686
                                  zend_bool is_ref, int num_symbol_tables, ...)
 
1687
{
 
1688
    HashTable  *symbol_table;
 
1689
    va_list     symbol_table_list;
 
1690
 
 
1691
    if (num_symbol_tables <= 0) return FAILURE;
 
1692
 
 
1693
    symbol->is_ref = is_ref;
 
1694
 
 
1695
    va_start(symbol_table_list, num_symbol_tables);
 
1696
    while (num_symbol_tables-- > 0) {
 
1697
        symbol_table = va_arg(symbol_table_list, HashTable *);
 
1698
        zend_hash_update(symbol_table, name, name_length + 1, &symbol, sizeof(zval *), NULL);
 
1699
        zval_add_ref(&symbol);
 
1700
    }
 
1701
    va_end(symbol_table_list);
 
1702
    return SUCCESS;
 
1703
}
 
1704
 
 
1705
 
 
1706
 
 
1707
 
 
1708
/* Disabled functions support */
 
1709
 
 
1710
ZEND_API ZEND_FUNCTION(display_disabled_function)
 
1711
{
 
1712
        zend_error(E_WARNING, "%s() has been disabled for security reasons", get_active_function_name(TSRMLS_C));
 
1713
}
 
1714
 
 
1715
 
 
1716
static zend_function_entry disabled_function[] =  {
 
1717
        ZEND_FE(display_disabled_function,                      NULL)
 
1718
        { NULL, NULL, NULL }
 
1719
};
 
1720
 
 
1721
 
 
1722
ZEND_API int zend_disable_function(char *function_name, uint function_name_length TSRMLS_DC)
 
1723
{
 
1724
        if (zend_hash_del(CG(function_table), function_name, function_name_length+1)==FAILURE) {
 
1725
                return FAILURE;
 
1726
        }
 
1727
        disabled_function[0].fname = function_name;
 
1728
        return zend_register_functions(NULL, disabled_function, CG(function_table), MODULE_PERSISTENT TSRMLS_CC);
 
1729
}
 
1730
 
 
1731
static zend_object_value display_disabled_class(zend_class_entry *class_type TSRMLS_DC)
 
1732
{
 
1733
        zend_object_value retval;
 
1734
        zend_object *intern;
 
1735
        retval = zend_objects_new(&intern, class_type TSRMLS_CC);
 
1736
        ALLOC_HASHTABLE(intern->properties);
 
1737
        zend_hash_init(intern->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
 
1738
        zend_error(E_WARNING, "%s() has been disabled for security reasons", class_type->name);
 
1739
        return retval;
 
1740
}
 
1741
 
 
1742
static zend_function_entry disabled_class_new[] =  {
 
1743
        { NULL, NULL, NULL }
 
1744
};
 
1745
 
 
1746
ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_DC)
 
1747
{
 
1748
        zend_class_entry *disabled_class;
 
1749
        disabled_class = (zend_class_entry *) emalloc(sizeof(zend_class_entry));
 
1750
        
 
1751
        zend_str_tolower(class_name, class_name_length);
 
1752
        if (zend_hash_del(CG(class_table), class_name, class_name_length+1)==FAILURE) {
 
1753
                return FAILURE;
 
1754
        }
 
1755
        INIT_CLASS_ENTRY((*disabled_class), class_name, disabled_class_new);
 
1756
        disabled_class->create_object = display_disabled_class;
 
1757
        zend_register_internal_class(disabled_class TSRMLS_CC);
 
1758
        return 1;
 
1759
}
 
1760
 
 
1761
ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **callable_name)
 
1762
{
 
1763
        char *lcname;
 
1764
        zend_bool retval = 0;
 
1765
        TSRMLS_FETCH();
 
1766
 
 
1767
        switch (Z_TYPE_P(callable)) {
 
1768
                case IS_STRING:
 
1769
                        if (callable_name) {
 
1770
                                *callable_name = estrndup(Z_STRVAL_P(callable), Z_STRLEN_P(callable));
 
1771
                        }
 
1772
                        if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
 
1773
                                return 1;
 
1774
                        }
 
1775
 
 
1776
                        lcname = zend_str_tolower_dup(Z_STRVAL_P(callable), Z_STRLEN_P(callable));
 
1777
                        if (zend_hash_exists(EG(function_table), lcname, Z_STRLEN_P(callable)+1)) {
 
1778
                                retval = 1;
 
1779
                        }
 
1780
                        efree(lcname);
 
1781
                        break;
 
1782
 
 
1783
                case IS_ARRAY:
 
1784
                        {
 
1785
                                zval **method;
 
1786
                                zval **obj;
 
1787
                                zend_class_entry *ce = NULL, **pce;
 
1788
                                zend_uint callable_name_len;
 
1789
                                
 
1790
                                if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2 &&
 
1791
                                        zend_hash_index_find(Z_ARRVAL_P(callable), 0, (void **) &obj) == SUCCESS &&
 
1792
                                        zend_hash_index_find(Z_ARRVAL_P(callable), 1, (void **) &method) == SUCCESS &&
 
1793
                                        (Z_TYPE_PP(obj) == IS_OBJECT || Z_TYPE_PP(obj) == IS_STRING) &&
 
1794
                                        Z_TYPE_PP(method) == IS_STRING) {
 
1795
 
 
1796
                                        if (Z_TYPE_PP(obj) == IS_STRING) {
 
1797
                                                if (callable_name) {
 
1798
                                                        char *ptr;
 
1799
 
 
1800
                                                        callable_name_len = Z_STRLEN_PP(obj) + Z_STRLEN_PP(method) + sizeof("::");
 
1801
                                                        ptr = *callable_name = emalloc(callable_name_len);
 
1802
                                                        memcpy(ptr, Z_STRVAL_PP(obj), Z_STRLEN_PP(obj));
 
1803
                                                        ptr += Z_STRLEN_PP(obj);
 
1804
                                                        memcpy(ptr, "::", sizeof("::") - 1);
 
1805
                                                        ptr += sizeof("::") - 1;
 
1806
                                                        memcpy(ptr, Z_STRVAL_PP(method), Z_STRLEN_PP(method) + 1);
 
1807
                                                }
 
1808
 
 
1809
                                                if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY)
 
1810
                                                        return 1;
 
1811
 
 
1812
                                                lcname = zend_str_tolower_dup(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj));
 
1813
 
 
1814
                                                if (EG(active_op_array) && strcmp(lcname, "self") == 0) {
 
1815
                                                        ce = EG(active_op_array)->scope;
 
1816
                                                } else if (strcmp(lcname, "parent") == 0 && EG(active_op_array) && EG(active_op_array)->scope) {
 
1817
                                                        ce = EG(active_op_array)->scope->parent;
 
1818
                                                } else if (zend_lookup_class(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), &pce TSRMLS_CC) == SUCCESS) {
 
1819
                                                        ce = *pce;
 
1820
                                                }
 
1821
                                                
 
1822
                                                efree(lcname);
 
1823
                                        } else {
 
1824
                                                ce = Z_OBJCE_PP(obj); /* TBFixed: what if it's overloaded? */
 
1825
 
 
1826
                                                if (callable_name) {
 
1827
                                                        char *ptr;
 
1828
 
 
1829
                                                        callable_name_len = ce->name_length + Z_STRLEN_PP(method) + sizeof("::");
 
1830
                                                        ptr = *callable_name = emalloc(callable_name_len);
 
1831
                                                        memcpy(ptr, ce->name, ce->name_length);
 
1832
                                                        ptr += ce->name_length;
 
1833
                                                        memcpy(ptr, "::", sizeof("::") - 1);
 
1834
                                                        ptr += sizeof("::") - 1;
 
1835
                                                        memcpy(ptr, Z_STRVAL_PP(method), Z_STRLEN_PP(method) + 1);
 
1836
                                                }
 
1837
 
 
1838
                                                if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY)
 
1839
                                                        return 1;
 
1840
                                        }
 
1841
 
 
1842
                                        if (ce) {
 
1843
                                                zend_function *fbc;
 
1844
 
 
1845
                                                lcname = zend_str_tolower_dup(Z_STRVAL_PP(method), Z_STRLEN_PP(method));
 
1846
                                                if (zend_hash_find(&ce->function_table, lcname, Z_STRLEN_PP(method)+1, (void **)&fbc) == SUCCESS) {
 
1847
                                                        retval = 1;
 
1848
                                                        if ((check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0) {
 
1849
                                                                if (fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) {
 
1850
                                                                        if (!zend_check_private(fbc, (Z_TYPE_PP(obj) == IS_STRING)?EG(scope):(*obj)->value.obj.handlers->get_class_entry(*obj TSRMLS_CC), lcname, Z_STRLEN_PP(method) TSRMLS_CC)) {
 
1851
                                                                                retval = 0;
 
1852
                                                                        }
 
1853
                                                                } else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) {
 
1854
                                                                        if (!zend_check_protected(fbc->common.scope, EG(scope))) {
 
1855
                                                                                retval = 0;
 
1856
                                                                        }
 
1857
                                                                }
 
1858
                                                        }
 
1859
                                                }
 
1860
                                                /* check for __call too */
 
1861
                                                if (retval == 0 && ce->__call != 0) {
 
1862
                                                        retval = 1;
 
1863
                                                }
 
1864
                                                efree(lcname);
 
1865
                                        }
 
1866
                                } else if (callable_name) {
 
1867
                                        *callable_name = estrndup("Array", sizeof("Array")-1);
 
1868
                                }
 
1869
                        }
 
1870
                        break;
 
1871
 
 
1872
                default:
 
1873
                        if (callable_name) {
 
1874
                                zval expr_copy;
 
1875
                                int use_copy;
 
1876
 
 
1877
                                zend_make_printable_zval(callable, &expr_copy, &use_copy);
 
1878
                                *callable_name = estrndup(Z_STRVAL(expr_copy), Z_STRLEN(expr_copy));
 
1879
                                zval_dtor(&expr_copy);
 
1880
                        }
 
1881
                        break;
 
1882
        }
 
1883
 
 
1884
        return retval;
 
1885
}
 
1886
 
 
1887
 
 
1888
ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRMLS_DC)
 
1889
{
 
1890
        char *lcname, *func, *class_name;
 
1891
        zend_bool retval = 0;
 
1892
        zend_class_entry **pce;
 
1893
        int class_name_len;
 
1894
 
 
1895
        if (zend_is_callable(callable, 0, callable_name)) {
 
1896
                return 1;
 
1897
        }
 
1898
        switch (Z_TYPE_P(callable)) {
 
1899
                case IS_STRING:
 
1900
                        lcname = zend_str_tolower_dup(Z_STRVAL_P(callable), Z_STRLEN_P(callable));
 
1901
 
 
1902
                        if ((func = strstr(lcname, "::")) != NULL) {
 
1903
                                *func = '\0';
 
1904
                                class_name_len = func - lcname;
 
1905
                                class_name = estrndup(Z_STRVAL_P(callable), class_name_len);
 
1906
                                if (zend_lookup_class(class_name, class_name_len, &pce TSRMLS_CC) == SUCCESS) {
 
1907
                                        zval_dtor(callable);
 
1908
                                        array_init(callable);
 
1909
                                        add_next_index_stringl(callable, lcname, class_name_len, 1);
 
1910
                                        func += 2;
 
1911
                                        add_next_index_stringl(callable, func, strlen(func), 1);
 
1912
                                        retval = 1; 
 
1913
                                }
 
1914
                                efree(class_name);
 
1915
                        }
 
1916
                        efree(lcname);
 
1917
                        break;
 
1918
        }
 
1919
        return retval;
 
1920
}
 
1921
 
 
1922
 
 
1923
ZEND_API char *zend_get_module_version(char *module_name)
 
1924
{
 
1925
        zend_module_entry *module;
 
1926
 
 
1927
        if (zend_hash_find(&module_registry, module_name, strlen(module_name) + 1,
 
1928
                       (void**)&module) == FAILURE) {
 
1929
                return NULL;
 
1930
        }
 
1931
    return module->version;
 
1932
}
 
1933
 
 
1934
 
 
1935
ZEND_API int zend_declare_property(zend_class_entry *ce, char *name, int name_length, zval *property, int access_type TSRMLS_DC)
 
1936
{
 
1937
        zend_property_info property_info;
 
1938
        HashTable *target_symbol_table;
 
1939
 
 
1940
        if (!(access_type & ZEND_ACC_PPP_MASK)) {
 
1941
                access_type |= ZEND_ACC_PUBLIC;
 
1942
        }
 
1943
        if (access_type & ZEND_ACC_STATIC) {
 
1944
                target_symbol_table = ce->static_members;
 
1945
        } else {
 
1946
                target_symbol_table = &ce->default_properties;
 
1947
        }
 
1948
        if (ce->type & ZEND_INTERNAL_CLASS) {
 
1949
                switch(Z_TYPE_P(property)) {
 
1950
                        case IS_ARRAY:
 
1951
                        case IS_CONSTANT_ARRAY:
 
1952
                        case IS_OBJECT:
 
1953
                        case IS_RESOURCE:
 
1954
                                zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
 
1955
                                break;
 
1956
                        default:
 
1957
                                break;
 
1958
                }
 
1959
        }
 
1960
        switch (access_type & ZEND_ACC_PPP_MASK) {
 
1961
                case ZEND_ACC_PRIVATE: {
 
1962
                                char *priv_name;
 
1963
                                int priv_name_length;
 
1964
 
 
1965
                                zend_mangle_property_name(&priv_name, &priv_name_length, ce->name, ce->name_length, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
 
1966
                                zend_hash_update(target_symbol_table, priv_name, priv_name_length+1, &property, sizeof(zval *), NULL);
 
1967
                                property_info.name = priv_name;
 
1968
                                property_info.name_length = priv_name_length;
 
1969
                        }
 
1970
                        break;
 
1971
                case ZEND_ACC_PROTECTED: {
 
1972
                                char *prot_name;
 
1973
                                int prot_name_length;
 
1974
 
 
1975
                                zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
 
1976
                                zend_hash_update(target_symbol_table, prot_name, prot_name_length+1, &property, sizeof(zval *), NULL);
 
1977
                                property_info.name = prot_name;
 
1978
                                property_info.name_length = prot_name_length;
 
1979
                        }
 
1980
                        break;
 
1981
                case ZEND_ACC_PUBLIC:
 
1982
                        if (ce->parent) {
 
1983
                                char *prot_name;
 
1984
                                int prot_name_length;
 
1985
 
 
1986
                                zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
 
1987
                                zend_hash_del(target_symbol_table, prot_name, prot_name_length+1);
 
1988
                                pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
 
1989
                        }
 
1990
                        zend_hash_update(target_symbol_table, name, name_length+1, &property, sizeof(zval *), NULL);
 
1991
                        property_info.name = ce->type & ZEND_INTERNAL_CLASS ? zend_strndup(name, name_length) : estrndup(name, name_length);
 
1992
                        property_info.name_length = name_length;
 
1993
                        break;
 
1994
        }
 
1995
        property_info.flags = access_type;
 
1996
        property_info.h = zend_get_hash_value(property_info.name, property_info.name_length+1);
 
1997
 
 
1998
        zend_hash_update(&ce->properties_info, name, name_length + 1, &property_info, sizeof(zend_property_info), NULL);
 
1999
 
 
2000
        return SUCCESS;
 
2001
}
 
2002
 
 
2003
ZEND_API int zend_declare_property_null(zend_class_entry *ce, char *name, int name_length, int access_type TSRMLS_DC)
 
2004
{
 
2005
        zval *property;
 
2006
        
 
2007
        if (ce->type & ZEND_INTERNAL_CLASS) {
 
2008
                property = malloc(sizeof(zval));
 
2009
        } else {
 
2010
                ALLOC_ZVAL(property);
 
2011
        }
 
2012
        INIT_ZVAL(*property);
 
2013
        return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
 
2014
}
 
2015
 
 
2016
ZEND_API int zend_declare_property_long(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC)
 
2017
{
 
2018
        zval *property;
 
2019
        
 
2020
        if (ce->type & ZEND_INTERNAL_CLASS) {
 
2021
                property = malloc(sizeof(zval));
 
2022
        } else {
 
2023
                ALLOC_ZVAL(property);
 
2024
        }
 
2025
        INIT_PZVAL(property);
 
2026
        ZVAL_LONG(property, value);
 
2027
        return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
 
2028
}
 
2029
 
 
2030
ZEND_API int zend_declare_property_string(zend_class_entry *ce, char *name, int name_length, char *value, int access_type TSRMLS_DC)
 
2031
{
 
2032
        zval *property;
 
2033
        int len = strlen(value);
 
2034
        
 
2035
        if (ce->type & ZEND_INTERNAL_CLASS) {
 
2036
                property = malloc(sizeof(zval));
 
2037
                ZVAL_STRINGL(property, zend_strndup(value, len), len, 0);
 
2038
        } else {
 
2039
                ALLOC_ZVAL(property);
 
2040
                ZVAL_STRINGL(property, value, len, 1);
 
2041
        }
 
2042
        INIT_PZVAL(property);
 
2043
        return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
 
2044
}
 
2045
 
 
2046
ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char *name, int name_length, zval *value TSRMLS_DC)
 
2047
{
 
2048
        zval property;
 
2049
        zend_class_entry *old_scope = EG(scope);
 
2050
        
 
2051
        EG(scope) = scope;
 
2052
 
 
2053
        if (!Z_OBJ_HT_P(object)->write_property) {
 
2054
                char *class_name;
 
2055
                zend_uint class_name_len;
 
2056
 
 
2057
                zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC);
 
2058
                
 
2059
                zend_error(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, class_name);
 
2060
        }
 
2061
        ZVAL_STRINGL(&property, name, name_length, 0);
 
2062
        Z_OBJ_HT_P(object)->write_property(object, &property, value TSRMLS_CC);
 
2063
 
 
2064
        EG(scope) = old_scope;
 
2065
}
 
2066
 
 
2067
ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, char *name, int name_length TSRMLS_DC)
 
2068
{
 
2069
        zval *tmp;
 
2070
 
 
2071
        ALLOC_ZVAL(tmp);
 
2072
        tmp->is_ref = 0;
 
2073
        tmp->refcount = 0;
 
2074
        ZVAL_NULL(tmp);
 
2075
        zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
 
2076
}
 
2077
 
 
2078
ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC)
 
2079
{
 
2080
        zval *tmp;
 
2081
        
 
2082
        ALLOC_ZVAL(tmp);
 
2083
        tmp->is_ref = 0;
 
2084
        tmp->refcount = 0;
 
2085
        ZVAL_LONG(tmp, value);
 
2086
        zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
 
2087
}
 
2088
 
 
2089
ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, char *name, int name_length, char *value TSRMLS_DC)
 
2090
{
 
2091
        zval *tmp;
 
2092
        
 
2093
        ALLOC_ZVAL(tmp);
 
2094
        tmp->is_ref = 0;
 
2095
        tmp->refcount = 0;
 
2096
        ZVAL_STRING(tmp, value, 1);
 
2097
        zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
 
2098
}
 
2099
 
 
2100
ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *name, int name_length, zend_bool silent TSRMLS_DC)
 
2101
{
 
2102
        zval property, *value;
 
2103
        zend_class_entry *old_scope = EG(scope);
 
2104
        
 
2105
        EG(scope) = scope;
 
2106
 
 
2107
        if (!Z_OBJ_HT_P(object)->read_property) {
 
2108
                char *class_name;
 
2109
                zend_uint class_name_len;
 
2110
 
 
2111
                zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC);
 
2112
                zend_error(E_CORE_ERROR, "Property %s of class %s cannot be read", name, class_name);
 
2113
        }
 
2114
        ZVAL_STRINGL(&property, name, name_length, 0);
 
2115
        value = Z_OBJ_HT_P(object)->read_property(object, &property, silent TSRMLS_CC);
 
2116
 
 
2117
        EG(scope) = old_scope;
 
2118
        return value;
 
2119
}
 
2120
 
 
2121
/*
 
2122
 * Local variables:
 
2123
 * tab-width: 4
 
2124
 * c-basic-offset: 4
 
2125
 * indent-tabs-mode: t
 
2126
 * End:
 
2127
 */