PageRenderTime 56ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/Zend/zend_API.c

http://github.com/infusion/PHP
C | 3561 lines | 2851 code | 478 blank | 232 comment | 721 complexity | 7ac15605f35356bce15a1814ce6d9a67 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-3-Clause
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend Engine |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1998-2011 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. /* $Id: zend_API.c 307424 2011-01-12 22:17:10Z felipe $ */
  21. #include "zend.h"
  22. #include "zend_execute.h"
  23. #include "zend_API.h"
  24. #include "zend_modules.h"
  25. #include "zend_constants.h"
  26. #include "zend_exceptions.h"
  27. #include "zend_closures.h"
  28. #ifdef HAVE_STDARG_H
  29. #include <stdarg.h>
  30. #endif
  31. /* these variables are true statics/globals, and have to be mutex'ed on every access */
  32. static int module_count=0;
  33. ZEND_API HashTable module_registry;
  34. /* this function doesn't check for too many parameters */
  35. ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
  36. {
  37. void **p;
  38. int arg_count;
  39. va_list ptr;
  40. zval **param, *param_ptr;
  41. TSRMLS_FETCH();
  42. p = zend_vm_stack_top(TSRMLS_C) - 1;
  43. arg_count = (int)(zend_uintptr_t) *p;
  44. if (param_count>arg_count) {
  45. return FAILURE;
  46. }
  47. va_start(ptr, param_count);
  48. while (param_count-->0) {
  49. param = va_arg(ptr, zval **);
  50. param_ptr = *(p-arg_count);
  51. if (!PZVAL_IS_REF(param_ptr) && Z_REFCOUNT_P(param_ptr) > 1) {
  52. zval *new_tmp;
  53. ALLOC_ZVAL(new_tmp);
  54. *new_tmp = *param_ptr;
  55. zval_copy_ctor(new_tmp);
  56. INIT_PZVAL(new_tmp);
  57. param_ptr = new_tmp;
  58. Z_DELREF_P((zval *) *(p-arg_count));
  59. *(p-arg_count) = param_ptr;
  60. }
  61. *param = param_ptr;
  62. arg_count--;
  63. }
  64. va_end(ptr);
  65. return SUCCESS;
  66. }
  67. /* }}} */
  68. ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval **argument_array TSRMLS_DC) /* {{{ */
  69. {
  70. void **p;
  71. int arg_count;
  72. zval *param_ptr;
  73. p = zend_vm_stack_top(TSRMLS_C) - 1;
  74. arg_count = (int)(zend_uintptr_t) *p;
  75. if (param_count>arg_count) {
  76. return FAILURE;
  77. }
  78. while (param_count-->0) {
  79. param_ptr = *(p-arg_count);
  80. if (!PZVAL_IS_REF(param_ptr) && Z_REFCOUNT_P(param_ptr) > 1) {
  81. zval *new_tmp;
  82. ALLOC_ZVAL(new_tmp);
  83. *new_tmp = *param_ptr;
  84. zval_copy_ctor(new_tmp);
  85. INIT_PZVAL(new_tmp);
  86. param_ptr = new_tmp;
  87. Z_DELREF_P((zval *) *(p-arg_count));
  88. *(p-arg_count) = param_ptr;
  89. }
  90. *(argument_array++) = param_ptr;
  91. arg_count--;
  92. }
  93. return SUCCESS;
  94. }
  95. /* }}} */
  96. /* Zend-optimized Extended functions */
  97. /* this function doesn't check for too many parameters */
  98. ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */
  99. {
  100. void **p;
  101. int arg_count;
  102. va_list ptr;
  103. zval ***param;
  104. TSRMLS_FETCH();
  105. p = zend_vm_stack_top(TSRMLS_C) - 1;
  106. arg_count = (int)(zend_uintptr_t) *p;
  107. if (param_count>arg_count) {
  108. return FAILURE;
  109. }
  110. va_start(ptr, param_count);
  111. while (param_count-->0) {
  112. param = va_arg(ptr, zval ***);
  113. *param = (zval **) p-(arg_count--);
  114. }
  115. va_end(ptr);
  116. return SUCCESS;
  117. }
  118. /* }}} */
  119. ZEND_API int _zend_get_parameters_array_ex(int param_count, zval ***argument_array TSRMLS_DC) /* {{{ */
  120. {
  121. void **p;
  122. int arg_count;
  123. p = zend_vm_stack_top(TSRMLS_C) - 1;
  124. arg_count = (int)(zend_uintptr_t) *p;
  125. if (param_count>arg_count) {
  126. return FAILURE;
  127. }
  128. while (param_count-->0) {
  129. zval **value = (zval**)(p-arg_count);
  130. *(argument_array++) = value;
  131. arg_count--;
  132. }
  133. return SUCCESS;
  134. }
  135. /* }}} */
  136. ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TSRMLS_DC) /* {{{ */
  137. {
  138. void **p;
  139. int arg_count;
  140. p = zend_vm_stack_top(TSRMLS_C) - 1;
  141. arg_count = (int)(zend_uintptr_t) *p;
  142. if (param_count>arg_count) {
  143. return FAILURE;
  144. }
  145. while (param_count-->0) {
  146. zval **param = (zval **) p-(arg_count--);
  147. zval_add_ref(param);
  148. add_next_index_zval(argument_array, *param);
  149. }
  150. return SUCCESS;
  151. }
  152. /* }}} */
  153. ZEND_API void zend_wrong_param_count(TSRMLS_D) /* {{{ */
  154. {
  155. char *space;
  156. char *class_name = get_active_class_name(&space TSRMLS_CC);
  157. zend_error(E_WARNING, "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name(TSRMLS_C));
  158. }
  159. /* }}} */
  160. /* Argument parsing API -- andrei */
  161. ZEND_API char *zend_get_type_by_const(int type) /* {{{ */
  162. {
  163. switch(type) {
  164. case IS_BOOL:
  165. return "boolean";
  166. case IS_LONG:
  167. return "integer";
  168. case IS_DOUBLE:
  169. return "double";
  170. case IS_STRING:
  171. return "string";
  172. case IS_OBJECT:
  173. return "object";
  174. case IS_RESOURCE:
  175. return "resource";
  176. case IS_NULL:
  177. return "null";
  178. case IS_ARRAY:
  179. return "array";
  180. default:
  181. return "unknown";
  182. }
  183. }
  184. /* }}} */
  185. ZEND_API char *zend_zval_type_name(const zval *arg) /* {{{ */
  186. {
  187. return zend_get_type_by_const(Z_TYPE_P(arg));
  188. }
  189. /* }}} */
  190. ZEND_API zend_class_entry *zend_get_class_entry(const zval *zobject TSRMLS_DC) /* {{{ */
  191. {
  192. if (Z_OBJ_HT_P(zobject)->get_class_entry) {
  193. return Z_OBJ_HT_P(zobject)->get_class_entry(zobject TSRMLS_CC);
  194. } else {
  195. zend_error(E_ERROR, "Class entry requested for an object without PHP class");
  196. return NULL;
  197. }
  198. }
  199. /* }}} */
  200. /* returns 1 if you need to copy result, 0 if it's already a copy */
  201. ZEND_API int zend_get_object_classname(const zval *object, char **class_name, zend_uint *class_name_len TSRMLS_DC) /* {{{ */
  202. {
  203. if (Z_OBJ_HT_P(object)->get_class_name == NULL ||
  204. Z_OBJ_HT_P(object)->get_class_name(object, class_name, class_name_len, 0 TSRMLS_CC) != SUCCESS) {
  205. zend_class_entry *ce = Z_OBJCE_P(object);
  206. *class_name = ce->name;
  207. *class_name_len = ce->name_length;
  208. return 1;
  209. }
  210. return 0;
  211. }
  212. /* }}} */
  213. static int parse_arg_object_to_string(zval **arg TSRMLS_DC) /* {{{ */
  214. {
  215. if (Z_OBJ_HANDLER_PP(arg, cast_object)) {
  216. SEPARATE_ZVAL_IF_NOT_REF(arg);
  217. if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, IS_STRING TSRMLS_CC) == SUCCESS) {
  218. return SUCCESS;
  219. }
  220. }
  221. /* Standard PHP objects */
  222. if (Z_OBJ_HT_PP(arg) == &std_object_handlers || !Z_OBJ_HANDLER_PP(arg, cast_object)) {
  223. SEPARATE_ZVAL_IF_NOT_REF(arg);
  224. if (zend_std_cast_object_tostring(*arg, *arg, IS_STRING TSRMLS_CC) == SUCCESS) {
  225. return SUCCESS;
  226. }
  227. }
  228. if (!Z_OBJ_HANDLER_PP(arg, cast_object) && Z_OBJ_HANDLER_PP(arg, get)) {
  229. int use_copy;
  230. zval *z = Z_OBJ_HANDLER_PP(arg, get)(*arg TSRMLS_CC);
  231. Z_ADDREF_P(z);
  232. if(Z_TYPE_P(z) != IS_OBJECT) {
  233. zval_dtor(*arg);
  234. Z_TYPE_P(*arg) = IS_NULL;
  235. zend_make_printable_zval(z, *arg, &use_copy);
  236. if (!use_copy) {
  237. ZVAL_ZVAL(*arg, z, 1, 1);
  238. }
  239. return SUCCESS;
  240. }
  241. zval_ptr_dtor(&z);
  242. }
  243. return FAILURE;
  244. }
  245. /* }}} */
  246. static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **spec, char **error, int *severity TSRMLS_DC) /* {{{ */
  247. {
  248. char *spec_walk = *spec;
  249. char c = *spec_walk++;
  250. int return_null = 0;
  251. /* scan through modifiers */
  252. while (1) {
  253. if (*spec_walk == '/') {
  254. SEPARATE_ZVAL_IF_NOT_REF(arg);
  255. } else if (*spec_walk == '!') {
  256. if (Z_TYPE_PP(arg) == IS_NULL) {
  257. return_null = 1;
  258. }
  259. } else {
  260. break;
  261. }
  262. spec_walk++;
  263. }
  264. switch (c) {
  265. case 'l':
  266. case 'L':
  267. {
  268. long *p = va_arg(*va, long *);
  269. switch (Z_TYPE_PP(arg)) {
  270. case IS_STRING:
  271. {
  272. double d;
  273. int type;
  274. if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), p, &d, -1)) == 0) {
  275. return "long";
  276. } else if (type == IS_DOUBLE) {
  277. if (c == 'L') {
  278. if (d > LONG_MAX) {
  279. *p = LONG_MAX;
  280. break;
  281. } else if (d < LONG_MIN) {
  282. *p = LONG_MIN;
  283. break;
  284. }
  285. }
  286. *p = zend_dval_to_lval(d);
  287. }
  288. }
  289. break;
  290. case IS_DOUBLE:
  291. if (c == 'L') {
  292. if (Z_DVAL_PP(arg) > LONG_MAX) {
  293. *p = LONG_MAX;
  294. break;
  295. } else if (Z_DVAL_PP(arg) < LONG_MIN) {
  296. *p = LONG_MIN;
  297. break;
  298. }
  299. }
  300. case IS_NULL:
  301. case IS_LONG:
  302. case IS_BOOL:
  303. convert_to_long_ex(arg);
  304. *p = Z_LVAL_PP(arg);
  305. break;
  306. case IS_ARRAY:
  307. case IS_OBJECT:
  308. case IS_RESOURCE:
  309. default:
  310. return "long";
  311. }
  312. }
  313. break;
  314. case 'd':
  315. {
  316. double *p = va_arg(*va, double *);
  317. switch (Z_TYPE_PP(arg)) {
  318. case IS_STRING:
  319. {
  320. long l;
  321. int type;
  322. if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &l, p, -1)) == 0) {
  323. return "double";
  324. } else if (type == IS_LONG) {
  325. *p = (double) l;
  326. }
  327. }
  328. break;
  329. case IS_NULL:
  330. case IS_LONG:
  331. case IS_DOUBLE:
  332. case IS_BOOL:
  333. convert_to_double_ex(arg);
  334. *p = Z_DVAL_PP(arg);
  335. break;
  336. case IS_ARRAY:
  337. case IS_OBJECT:
  338. case IS_RESOURCE:
  339. default:
  340. return "double";
  341. }
  342. }
  343. break;
  344. case 's':
  345. {
  346. char **p = va_arg(*va, char **);
  347. int *pl = va_arg(*va, int *);
  348. switch (Z_TYPE_PP(arg)) {
  349. case IS_NULL:
  350. if (return_null) {
  351. *p = NULL;
  352. *pl = 0;
  353. break;
  354. }
  355. /* break omitted intentionally */
  356. case IS_STRING:
  357. case IS_LONG:
  358. case IS_DOUBLE:
  359. case IS_BOOL:
  360. convert_to_string_ex(arg);
  361. if (UNEXPECTED(Z_ISREF_PP(arg) != 0)) {
  362. /* it's dangerous to return pointers to string
  363. buffer of referenced variable, because it can
  364. be clobbered throug magic callbacks */
  365. SEPARATE_ZVAL(arg);
  366. }
  367. *p = Z_STRVAL_PP(arg);
  368. *pl = Z_STRLEN_PP(arg);
  369. break;
  370. case IS_OBJECT:
  371. case IS_ARRAY:
  372. case IS_RESOURCE:
  373. default:
  374. return "string";
  375. }
  376. }
  377. break;
  378. case 'b':
  379. {
  380. zend_bool *p = va_arg(*va, zend_bool *);
  381. switch (Z_TYPE_PP(arg)) {
  382. case IS_NULL:
  383. case IS_STRING:
  384. case IS_LONG:
  385. case IS_DOUBLE:
  386. case IS_BOOL:
  387. convert_to_boolean_ex(arg);
  388. *p = Z_BVAL_PP(arg);
  389. break;
  390. case IS_ARRAY:
  391. case IS_OBJECT:
  392. case IS_RESOURCE:
  393. default:
  394. return "boolean";
  395. }
  396. }
  397. break;
  398. case 'r':
  399. {
  400. zval **p = va_arg(*va, zval **);
  401. if (return_null) {
  402. *p = NULL;
  403. break;
  404. }
  405. if (Z_TYPE_PP(arg) == IS_RESOURCE) {
  406. *p = *arg;
  407. } else {
  408. return "resource";
  409. }
  410. }
  411. break;
  412. case 'A':
  413. case 'a':
  414. {
  415. zval **p = va_arg(*va, zval **);
  416. if (return_null) {
  417. *p = NULL;
  418. break;
  419. }
  420. if (Z_TYPE_PP(arg) == IS_ARRAY || (c == 'A' && Z_TYPE_PP(arg) == IS_OBJECT)) {
  421. *p = *arg;
  422. } else {
  423. return "array";
  424. }
  425. }
  426. break;
  427. case 'H':
  428. case 'h':
  429. {
  430. HashTable **p = va_arg(*va, HashTable **);
  431. if (return_null) {
  432. *p = NULL;
  433. break;
  434. }
  435. if (Z_TYPE_PP(arg) == IS_ARRAY) {
  436. *p = Z_ARRVAL_PP(arg);
  437. } else if(c == 'H' && Z_TYPE_PP(arg) == IS_OBJECT) {
  438. *p = HASH_OF(*arg);
  439. if(*p == NULL) {
  440. return "array";
  441. }
  442. } else {
  443. return "array";
  444. }
  445. }
  446. break;
  447. case 'o':
  448. {
  449. zval **p = va_arg(*va, zval **);
  450. if (return_null) {
  451. *p = NULL;
  452. break;
  453. }
  454. if (Z_TYPE_PP(arg) == IS_OBJECT) {
  455. *p = *arg;
  456. } else {
  457. return "object";
  458. }
  459. }
  460. break;
  461. case 'O':
  462. {
  463. zval **p = va_arg(*va, zval **);
  464. zend_class_entry *ce = va_arg(*va, zend_class_entry *);
  465. if (return_null) {
  466. *p = NULL;
  467. break;
  468. }
  469. if (Z_TYPE_PP(arg) == IS_OBJECT &&
  470. (!ce || instanceof_function(Z_OBJCE_PP(arg), ce TSRMLS_CC))) {
  471. *p = *arg;
  472. } else {
  473. if (ce) {
  474. return ce->name;
  475. } else {
  476. return "object";
  477. }
  478. }
  479. }
  480. break;
  481. case 'C':
  482. {
  483. zend_class_entry **lookup, **pce = va_arg(*va, zend_class_entry **);
  484. zend_class_entry *ce_base = *pce;
  485. if (return_null) {
  486. *pce = NULL;
  487. break;
  488. }
  489. convert_to_string_ex(arg);
  490. if (zend_lookup_class(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &lookup TSRMLS_CC) == FAILURE) {
  491. *pce = NULL;
  492. } else {
  493. *pce = *lookup;
  494. }
  495. if (ce_base) {
  496. if ((!*pce || !instanceof_function(*pce, ce_base TSRMLS_CC))) {
  497. zend_spprintf(error, 0, "to be a class name derived from %s, '%s' given",
  498. ce_base->name, Z_STRVAL_PP(arg));
  499. *pce = NULL;
  500. return "";
  501. }
  502. }
  503. if (!*pce) {
  504. zend_spprintf(error, 0, "to be a valid class name, '%s' given",
  505. Z_STRVAL_PP(arg));
  506. return "";
  507. }
  508. break;
  509. }
  510. break;
  511. case 'f':
  512. {
  513. zend_fcall_info *fci = va_arg(*va, zend_fcall_info *);
  514. zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *);
  515. char *is_callable_error = NULL;
  516. if (return_null) {
  517. fci->size = 0;
  518. fcc->initialized = 0;
  519. break;
  520. }
  521. if (zend_fcall_info_init(*arg, 0, fci, fcc, NULL, &is_callable_error TSRMLS_CC) == SUCCESS) {
  522. if (is_callable_error) {
  523. *severity = E_STRICT;
  524. zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error);
  525. efree(is_callable_error);
  526. *spec = spec_walk;
  527. return "";
  528. }
  529. break;
  530. } else {
  531. if (is_callable_error) {
  532. *severity = E_WARNING;
  533. zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error);
  534. efree(is_callable_error);
  535. return "";
  536. } else {
  537. return "valid callback";
  538. }
  539. }
  540. }
  541. case 'z':
  542. {
  543. zval **p = va_arg(*va, zval **);
  544. if (return_null) {
  545. *p = NULL;
  546. } else {
  547. *p = *arg;
  548. }
  549. }
  550. break;
  551. case 'Z':
  552. {
  553. zval ***p = va_arg(*va, zval ***);
  554. if (return_null) {
  555. *p = NULL;
  556. } else {
  557. *p = arg;
  558. }
  559. }
  560. break;
  561. default:
  562. return "unknown";
  563. }
  564. *spec = spec_walk;
  565. return NULL;
  566. }
  567. /* }}} */
  568. static int zend_parse_arg(int arg_num, zval **arg, va_list *va, char **spec, int quiet TSRMLS_DC) /* {{{ */
  569. {
  570. char *expected_type = NULL, *error = NULL;
  571. int severity = E_WARNING;
  572. expected_type = zend_parse_arg_impl(arg_num, arg, va, spec, &error, &severity TSRMLS_CC);
  573. if (expected_type) {
  574. if (!quiet && (*expected_type || error)) {
  575. char *space;
  576. char *class_name = get_active_class_name(&space TSRMLS_CC);
  577. if (error) {
  578. zend_error(severity, "%s%s%s() expects parameter %d %s",
  579. class_name, space, get_active_function_name(TSRMLS_C), arg_num, error);
  580. efree(error);
  581. } else {
  582. zend_error(severity, "%s%s%s() expects parameter %d to be %s, %s given",
  583. class_name, space, get_active_function_name(TSRMLS_C), arg_num, expected_type,
  584. zend_zval_type_name(*arg));
  585. }
  586. }
  587. if (severity != E_STRICT) {
  588. return FAILURE;
  589. }
  590. }
  591. return SUCCESS;
  592. }
  593. /* }}} */
  594. static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int flags TSRMLS_DC) /* {{{ */
  595. {
  596. char *spec_walk;
  597. int c, i;
  598. int min_num_args = -1;
  599. int max_num_args = 0;
  600. int post_varargs = 0;
  601. zval **arg;
  602. int arg_count = (int)(zend_uintptr_t) *(zend_vm_stack_top(TSRMLS_C) - 1);
  603. int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
  604. zend_bool have_varargs = 0;
  605. zval ****varargs = NULL;
  606. int *n_varargs = NULL;
  607. for (spec_walk = type_spec; *spec_walk; spec_walk++) {
  608. c = *spec_walk;
  609. switch (c) {
  610. case 's':
  611. if (max_num_args < arg_count) {
  612. arg = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count - max_num_args));
  613. if (Z_TYPE_PP(arg) == IS_OBJECT) {
  614. parse_arg_object_to_string(arg TSRMLS_CC);
  615. }
  616. }
  617. /* break missing intentionally */
  618. case 'l': case 'd':
  619. case 'H': case 'b':
  620. case 'r': case 'a':
  621. case 'o': case 'O':
  622. case 'z': case 'Z':
  623. case 'C': case 'h':
  624. case 'f': case 'A':
  625. max_num_args++;
  626. break;
  627. case '|':
  628. min_num_args = max_num_args;
  629. break;
  630. case '/':
  631. case '!':
  632. /* Pass */
  633. break;
  634. case '*':
  635. case '+':
  636. if (have_varargs) {
  637. if (!quiet) {
  638. zend_function *active_function = EG(current_execute_data)->function_state.function;
  639. char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
  640. zend_error(E_WARNING, "%s%s%s(): only one varargs specifier (* or +) is permitted",
  641. class_name,
  642. class_name[0] ? "::" : "",
  643. active_function->common.function_name);
  644. }
  645. return FAILURE;
  646. }
  647. have_varargs = 1;
  648. /* we expect at least one parameter in varargs */
  649. if (c == '+') {
  650. max_num_args++;
  651. }
  652. /* mark the beginning of varargs */
  653. post_varargs = max_num_args;
  654. break;
  655. default:
  656. if (!quiet) {
  657. zend_function *active_function = EG(current_execute_data)->function_state.function;
  658. char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
  659. zend_error(E_WARNING, "%s%s%s(): bad type specifier while parsing parameters",
  660. class_name,
  661. class_name[0] ? "::" : "",
  662. active_function->common.function_name);
  663. }
  664. return FAILURE;
  665. }
  666. }
  667. if (min_num_args < 0) {
  668. min_num_args = max_num_args;
  669. }
  670. if (have_varargs) {
  671. /* calculate how many required args are at the end of the specifier list */
  672. post_varargs = max_num_args - post_varargs;
  673. max_num_args = -1;
  674. }
  675. if (num_args < min_num_args || (num_args > max_num_args && max_num_args > 0)) {
  676. if (!quiet) {
  677. zend_function *active_function = EG(current_execute_data)->function_state.function;
  678. char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
  679. zend_error(E_WARNING, "%s%s%s() expects %s %d parameter%s, %d given",
  680. class_name,
  681. class_name[0] ? "::" : "",
  682. active_function->common.function_name,
  683. min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
  684. num_args < min_num_args ? min_num_args : max_num_args,
  685. (num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
  686. num_args);
  687. }
  688. return FAILURE;
  689. }
  690. if (num_args > arg_count) {
  691. zend_error(E_WARNING, "%s(): could not obtain parameters for parsing",
  692. get_active_function_name(TSRMLS_C));
  693. return FAILURE;
  694. }
  695. i = 0;
  696. while (num_args-- > 0) {
  697. if (*type_spec == '|') {
  698. type_spec++;
  699. }
  700. if (*type_spec == '*' || *type_spec == '+') {
  701. int num_varargs = num_args + 1 - post_varargs;
  702. /* eat up the passed in storage even if it won't be filled in with varargs */
  703. varargs = va_arg(*va, zval ****);
  704. n_varargs = va_arg(*va, int *);
  705. type_spec++;
  706. if (num_varargs > 0) {
  707. int iv = 0;
  708. zval **p = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count - i));
  709. *n_varargs = num_varargs;
  710. /* allocate space for array and store args */
  711. *varargs = safe_emalloc(num_varargs, sizeof(zval **), 0);
  712. while (num_varargs-- > 0) {
  713. (*varargs)[iv++] = p++;
  714. }
  715. /* adjust how many args we have left and restart loop */
  716. num_args = num_args + 1 - iv;
  717. i += iv;
  718. continue;
  719. } else {
  720. *varargs = NULL;
  721. *n_varargs = 0;
  722. }
  723. }
  724. arg = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count-i));
  725. if (zend_parse_arg(i+1, arg, va, &type_spec, quiet TSRMLS_CC) == FAILURE) {
  726. /* clean up varargs array if it was used */
  727. if (varargs && *varargs) {
  728. efree(*varargs);
  729. *varargs = NULL;
  730. }
  731. return FAILURE;
  732. }
  733. i++;
  734. }
  735. return SUCCESS;
  736. }
  737. /* }}} */
  738. #define RETURN_IF_ZERO_ARGS(num_args, type_spec, quiet) { \
  739. int __num_args = (num_args); \
  740. \
  741. if (0 == (type_spec)[0] && 0 != __num_args && !(quiet)) { \
  742. char *__space; \
  743. char * __class_name = get_active_class_name(&__space TSRMLS_CC); \
  744. zend_error(E_WARNING, "%s%s%s() expects exactly 0 parameters, %d given", \
  745. __class_name, __space, \
  746. get_active_function_name(TSRMLS_C), __num_args); \
  747. return FAILURE; \
  748. }\
  749. }
  750. ZEND_API int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...) /* {{{ */
  751. {
  752. va_list va;
  753. int retval;
  754. RETURN_IF_ZERO_ARGS(num_args, type_spec, flags & ZEND_PARSE_PARAMS_QUIET);
  755. va_start(va, type_spec);
  756. retval = zend_parse_va_args(num_args, type_spec, &va, flags TSRMLS_CC);
  757. va_end(va);
  758. return retval;
  759. }
  760. /* }}} */
  761. ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...) /* {{{ */
  762. {
  763. va_list va;
  764. int retval;
  765. RETURN_IF_ZERO_ARGS(num_args, type_spec, 0);
  766. va_start(va, type_spec);
  767. retval = zend_parse_va_args(num_args, type_spec, &va, 0 TSRMLS_CC);
  768. va_end(va);
  769. return retval;
  770. }
  771. /* }}} */
  772. ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, ...) /* {{{ */
  773. {
  774. va_list va;
  775. int retval;
  776. char *p = type_spec;
  777. zval **object;
  778. zend_class_entry *ce;
  779. if (!this_ptr) {
  780. RETURN_IF_ZERO_ARGS(num_args, p, 0);
  781. va_start(va, type_spec);
  782. retval = zend_parse_va_args(num_args, type_spec, &va, 0 TSRMLS_CC);
  783. va_end(va);
  784. } else {
  785. p++;
  786. RETURN_IF_ZERO_ARGS(num_args, p, 0);
  787. va_start(va, type_spec);
  788. object = va_arg(va, zval **);
  789. ce = va_arg(va, zend_class_entry *);
  790. *object = this_ptr;
  791. if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) {
  792. zend_error(E_CORE_ERROR, "%s::%s() must be derived from %s::%s",
  793. ce->name, get_active_function_name(TSRMLS_C), Z_OBJCE_P(this_ptr)->name, get_active_function_name(TSRMLS_C));
  794. }
  795. retval = zend_parse_va_args(num_args, p, &va, 0 TSRMLS_CC);
  796. va_end(va);
  797. }
  798. return retval;
  799. }
  800. /* }}} */
  801. ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, ...) /* {{{ */
  802. {
  803. va_list va;
  804. int retval;
  805. char *p = type_spec;
  806. zval **object;
  807. zend_class_entry *ce;
  808. int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
  809. if (!this_ptr) {
  810. RETURN_IF_ZERO_ARGS(num_args, p, quiet);
  811. va_start(va, type_spec);
  812. retval = zend_parse_va_args(num_args, type_spec, &va, flags TSRMLS_CC);
  813. va_end(va);
  814. } else {
  815. p++;
  816. RETURN_IF_ZERO_ARGS(num_args, p, quiet);
  817. va_start(va, type_spec);
  818. object = va_arg(va, zval **);
  819. ce = va_arg(va, zend_class_entry *);
  820. *object = this_ptr;
  821. if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) {
  822. if (!quiet) {
  823. zend_error(E_CORE_ERROR, "%s::%s() must be derived from %s::%s",
  824. ce->name, get_active_function_name(TSRMLS_C), Z_OBJCE_P(this_ptr)->name, get_active_function_name(TSRMLS_C));
  825. }
  826. return FAILURE;
  827. }
  828. retval = zend_parse_va_args(num_args, p, &va, flags TSRMLS_CC);
  829. va_end(va);
  830. }
  831. return retval;
  832. }
  833. /* }}} */
  834. /* Argument parsing API -- andrei */
  835. ZEND_API int _array_init(zval *arg, uint size ZEND_FILE_LINE_DC) /* {{{ */
  836. {
  837. ALLOC_HASHTABLE_REL(Z_ARRVAL_P(arg));
  838. _zend_hash_init(Z_ARRVAL_P(arg), size, NULL, ZVAL_PTR_DTOR, 0 ZEND_FILE_LINE_RELAY_CC);
  839. Z_TYPE_P(arg) = IS_ARRAY;
  840. return SUCCESS;
  841. }
  842. /* }}} */
  843. static int zend_merge_property(zval **value TSRMLS_DC, int num_args, va_list args, const zend_hash_key *hash_key) /* {{{ */
  844. {
  845. /* which name should a numeric property have ? */
  846. if (hash_key->nKeyLength) {
  847. zval *obj = va_arg(args, zval *);
  848. zend_object_handlers *obj_ht = va_arg(args, zend_object_handlers *);
  849. zval *member;
  850. MAKE_STD_ZVAL(member);
  851. ZVAL_STRINGL(member, hash_key->arKey, hash_key->nKeyLength-1, 1);
  852. obj_ht->write_property(obj, member, *value TSRMLS_CC);
  853. zval_ptr_dtor(&member);
  854. }
  855. return ZEND_HASH_APPLY_KEEP;
  856. }
  857. /* }}} */
  858. /* This function should be called after the constructor has been called
  859. * because it may call __set from the uninitialized object otherwise. */
  860. ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destroy_ht TSRMLS_DC) /* {{{ */
  861. {
  862. zend_object_handlers *obj_ht = Z_OBJ_HT_P(obj);
  863. zend_class_entry *old_scope = EG(scope);
  864. EG(scope) = Z_OBJCE_P(obj);
  865. zend_hash_apply_with_arguments(properties TSRMLS_CC, (apply_func_args_t)zend_merge_property, 2, obj, obj_ht);
  866. EG(scope) = old_scope;
  867. if (destroy_ht) {
  868. zend_hash_destroy(properties);
  869. FREE_HASHTABLE(properties);
  870. }
  871. }
  872. /* }}} */
  873. ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
  874. {
  875. if (!class_type->constants_updated || !CE_STATIC_MEMBERS(class_type)) {
  876. zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
  877. zend_class_entry *old_scope = *scope;
  878. *scope = class_type;
  879. zend_hash_apply_with_argument(&class_type->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC);
  880. zend_hash_apply_with_argument(&class_type->default_properties, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
  881. if (!CE_STATIC_MEMBERS(class_type)) {
  882. HashPosition pos;
  883. zval **p;
  884. if (class_type->parent) {
  885. zend_update_class_constants(class_type->parent TSRMLS_CC);
  886. }
  887. #if ZTS
  888. ALLOC_HASHTABLE(CG(static_members)[(zend_intptr_t)(class_type->static_members)]);
  889. #else
  890. ALLOC_HASHTABLE(class_type->static_members);
  891. #endif
  892. zend_hash_init(CE_STATIC_MEMBERS(class_type), zend_hash_num_elements(&class_type->default_static_members), NULL, ZVAL_PTR_DTOR, 0);
  893. zend_hash_internal_pointer_reset_ex(&class_type->default_static_members, &pos);
  894. while (zend_hash_get_current_data_ex(&class_type->default_static_members, (void**)&p, &pos) == SUCCESS) {
  895. char *str_index;
  896. uint str_length;
  897. ulong num_index;
  898. zval **q;
  899. zend_hash_get_current_key_ex(&class_type->default_static_members, &str_index, &str_length, &num_index, 0, &pos);
  900. if (Z_ISREF_PP(p) &&
  901. class_type->parent &&
  902. zend_hash_find(&class_type->parent->default_static_members, str_index, str_length, (void**)&q) == SUCCESS &&
  903. *p == *q &&
  904. zend_hash_find(CE_STATIC_MEMBERS(class_type->parent), str_index, str_length, (void**)&q) == SUCCESS
  905. ) {
  906. Z_ADDREF_PP(q);
  907. Z_SET_ISREF_PP(q);
  908. zend_hash_add(CE_STATIC_MEMBERS(class_type), str_index, str_length, (void**)q, sizeof(zval*), NULL);
  909. } else {
  910. zval *r;
  911. ALLOC_ZVAL(r);
  912. *r = **p;
  913. INIT_PZVAL(r);
  914. zval_copy_ctor(r);
  915. zend_hash_add(CE_STATIC_MEMBERS(class_type), str_index, str_length, (void**)&r, sizeof(zval*), NULL);
  916. }
  917. zend_hash_move_forward_ex(&class_type->default_static_members, &pos);
  918. }
  919. }
  920. zend_hash_apply_with_argument(CE_STATIC_MEMBERS(class_type), (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
  921. *scope = old_scope;
  922. class_type->constants_updated = 1;
  923. }
  924. }
  925. /* }}} */
  926. /* This function requires 'properties' to contain all props declared in the
  927. * class and all props being public. If only a subset is given or the class
  928. * has protected members then you need to merge the properties seperately by
  929. * calling zend_merge_properties(). */
  930. ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
  931. {
  932. zval *tmp;
  933. zend_object *object;
  934. if (class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
  935. char *what = class_type->ce_flags & ZEND_ACC_INTERFACE ? "interface" : "abstract class";
  936. zend_error(E_ERROR, "Cannot instantiate %s %s", what, class_type->name);
  937. }
  938. zend_update_class_constants(class_type TSRMLS_CC);
  939. Z_TYPE_P(arg) = IS_OBJECT;
  940. if (class_type->create_object == NULL) {
  941. Z_OBJVAL_P(arg) = zend_objects_new(&object, class_type TSRMLS_CC);
  942. if (properties) {
  943. object->properties = properties;
  944. } else {
  945. ALLOC_HASHTABLE_REL(object->properties);
  946. zend_hash_init(object->properties, zend_hash_num_elements(&class_type->default_properties), NULL, ZVAL_PTR_DTOR, 0);
  947. zend_hash_copy(object->properties, &class_type->default_properties, zval_copy_property_ctor(class_type), (void *) &tmp, sizeof(zval *));
  948. }
  949. } else {
  950. Z_OBJVAL_P(arg) = class_type->create_object(class_type TSRMLS_CC);
  951. }
  952. return SUCCESS;
  953. }
  954. /* }}} */
  955. ZEND_API int _object_init_ex(zval *arg, zend_class_entry *class_type ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
  956. {
  957. return _object_and_properties_init(arg, class_type, 0 ZEND_FILE_LINE_RELAY_CC TSRMLS_CC);
  958. }
  959. /* }}} */
  960. ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
  961. {
  962. return _object_init_ex(arg, zend_standard_class_def ZEND_FILE_LINE_RELAY_CC TSRMLS_CC);
  963. }
  964. /* }}} */
  965. ZEND_API int add_assoc_function(zval *arg, const char *key, void (*function_ptr)(INTERNAL_FUNCTION_PARAMETERS)) /* {{{ */
  966. {
  967. zend_error(E_WARNING, "add_assoc_function() is no longer supported");
  968. return FAILURE;
  969. }
  970. /* }}} */
  971. ZEND_API int add_assoc_long_ex(zval *arg, const char *key, uint key_len, long n) /* {{{ */
  972. {
  973. zval *tmp;
  974. MAKE_STD_ZVAL(tmp);
  975. ZVAL_LONG(tmp, n);
  976. return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
  977. }
  978. /* }}} */
  979. ZEND_API int add_assoc_null_ex(zval *arg, const char *key, uint key_len) /* {{{ */
  980. {
  981. zval *tmp;
  982. MAKE_STD_ZVAL(tmp);
  983. ZVAL_NULL(tmp);
  984. return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
  985. }
  986. /* }}} */
  987. ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, uint key_len, int b) /* {{{ */
  988. {
  989. zval *tmp;
  990. MAKE_STD_ZVAL(tmp);
  991. ZVAL_BOOL(tmp, b);
  992. return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
  993. }
  994. /* }}} */
  995. ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, uint key_len, int r) /* {{{ */
  996. {
  997. zval *tmp;
  998. MAKE_STD_ZVAL(tmp);
  999. ZVAL_RESOURCE(tmp, r);
  1000. return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
  1001. }
  1002. /* }}} */
  1003. ZEND_API int add_assoc_double_ex(zval *arg, const char *key, uint key_len, double d) /* {{{ */
  1004. {
  1005. zval *tmp;
  1006. MAKE_STD_ZVAL(tmp);
  1007. ZVAL_DOUBLE(tmp, d);
  1008. return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
  1009. }
  1010. /* }}} */
  1011. ZEND_API int add_assoc_string_ex(zval *arg, const char *key, uint key_len, char *str, int duplicate) /* {{{ */
  1012. {
  1013. zval *tmp;
  1014. MAKE_STD_ZVAL(tmp);
  1015. ZVAL_STRING(tmp, str, duplicate);
  1016. return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
  1017. }
  1018. /* }}} */
  1019. ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, uint key_len, char *str, uint length, int duplicate) /* {{{ */
  1020. {
  1021. zval *tmp;
  1022. MAKE_STD_ZVAL(tmp);
  1023. ZVAL_STRINGL(tmp, str, length, duplicate);
  1024. return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
  1025. }
  1026. /* }}} */
  1027. ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, uint key_len, zval *value) /* {{{ */
  1028. {
  1029. return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &value, sizeof(zval *), NULL);
  1030. }
  1031. /* }}} */
  1032. ZEND_API int add_index_long(zval *arg, ulong index, long n) /* {{{ */
  1033. {
  1034. zval *tmp;
  1035. MAKE_STD_ZVAL(tmp);
  1036. ZVAL_LONG(tmp, n);
  1037. return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
  1038. }
  1039. /* }}} */
  1040. ZEND_API int add_index_null(zval *arg, ulong index) /* {{{ */
  1041. {
  1042. zval *tmp;
  1043. MAKE_STD_ZVAL(tmp);
  1044. ZVAL_NULL(tmp);
  1045. return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
  1046. }
  1047. /* }}} */
  1048. ZEND_API int add_index_bool(zval *arg, ulong index, int b) /* {{{ */
  1049. {
  1050. zval *tmp;
  1051. MAKE_STD_ZVAL(tmp);
  1052. ZVAL_BOOL(tmp, b);
  1053. return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
  1054. }
  1055. /* }}} */
  1056. ZEND_API int add_index_resource(zval *arg, ulong index, int r) /* {{{ */
  1057. {
  1058. zval *tmp;
  1059. MAKE_STD_ZVAL(tmp);
  1060. ZVAL_RESOURCE(tmp, r);
  1061. return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
  1062. }
  1063. /* }}} */
  1064. ZEND_API int add_index_double(zval *arg, ulong index, double d) /* {{{ */
  1065. {
  1066. zval *tmp;
  1067. MAKE_STD_ZVAL(tmp);
  1068. ZVAL_DOUBLE(tmp, d);
  1069. return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
  1070. }
  1071. /* }}} */
  1072. ZEND_API int add_index_string(zval *arg, ulong index, const char *str, int duplicate) /* {{{ */
  1073. {
  1074. zval *tmp;
  1075. MAKE_STD_ZVAL(tmp);
  1076. ZVAL_STRING(tmp, str, duplicate);
  1077. return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
  1078. }
  1079. /* }}} */
  1080. ZEND_API int add_index_stringl(zval *arg, ulong index, const char *str, uint length, int duplicate) /* {{{ */
  1081. {
  1082. zval *tmp;
  1083. MAKE_STD_ZVAL(tmp);
  1084. ZVAL_STRINGL(tmp, str, length, duplicate);
  1085. return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
  1086. }
  1087. /* }}} */
  1088. ZEND_API int add_index_zval(zval *arg, ulong index, zval *value) /* {{{ */
  1089. {
  1090. return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &value, sizeof(zval *), NULL);
  1091. }
  1092. /* }}} */
  1093. ZEND_API int add_next_index_long(zval *arg, long n) /* {{{ */
  1094. {
  1095. zval *tmp;
  1096. MAKE_STD_ZVAL(tmp);
  1097. ZVAL_LONG(tmp, n);
  1098. return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
  1099. }
  1100. /* }}} */
  1101. ZEND_API int add_next_index_null(zval *arg) /* {{{ */
  1102. {
  1103. zval *tmp;
  1104. MAKE_STD_ZVAL(tmp);
  1105. ZVAL_NULL(tmp);
  1106. return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
  1107. }
  1108. /* }}} */
  1109. ZEND_API int add_next_index_bool(zval *arg, int b) /* {{{ */
  1110. {
  1111. zval *tmp;
  1112. MAKE_STD_ZVAL(tmp);
  1113. ZVAL_BOOL(tmp, b);
  1114. return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
  1115. }
  1116. /* }}} */
  1117. ZEND_API int add_next_index_resource(zval *arg, int r) /* {{{ */
  1118. {
  1119. zval *tmp;
  1120. MAKE_STD_ZVAL(tmp);
  1121. ZVAL_RESOURCE(tmp, r);
  1122. return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
  1123. }
  1124. /* }}} */
  1125. ZEND_API int add_next_index_double(zval *arg, double d) /* {{{ */
  1126. {
  1127. zval *tmp;
  1128. MAKE_STD_ZVAL(tmp);
  1129. ZVAL_DOUBLE(tmp, d);
  1130. return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
  1131. }
  1132. /* }}} */
  1133. ZEND_API int add_next_index_string(zval *arg, const char *str, int duplicate) /* {{{ */
  1134. {
  1135. zval *tmp;
  1136. MAKE_STD_ZVAL(tmp);
  1137. ZVAL_STRING(tmp, str, duplicate);
  1138. return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
  1139. }
  1140. /* }}} */
  1141. ZEND_API int add_next_index_stringl(zval *arg, const char *str, uint length, int duplicate) /* {{{ */
  1142. {
  1143. zval *tmp;
  1144. MAKE_STD_ZVAL(tmp);
  1145. ZVAL_STRINGL(tmp, str, length, duplicate);
  1146. return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
  1147. }
  1148. /* }}} */
  1149. ZEND_API int add_next_index_zval(zval *arg, zval *value) /* {{{ */
  1150. {
  1151. return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &value, sizeof(zval *), NULL);
  1152. }
  1153. /* }}} */
  1154. ZEND_API int add_get_assoc_string_ex(zval *arg, const char *key, uint key_len, const char *str, void **dest, int duplicate) /* {{{ */
  1155. {
  1156. zval *tmp;
  1157. MAKE_STD_ZVAL(tmp);
  1158. ZVAL_STRING(tmp, str, duplicate);
  1159. return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), dest);
  1160. }
  1161. /* }}} */
  1162. ZEND_API int add_get_assoc_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, uint length, void **dest, int duplicate) /* {{{ */
  1163. {
  1164. zval *tmp;
  1165. MAKE_STD_ZVAL(tmp);
  1166. ZVAL_STRINGL(tmp, str, length, duplicate);
  1167. return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), dest);
  1168. }
  1169. /* }}} */
  1170. ZEND_API int add_get_index_long(zval *arg, ulong index, long l, void **dest) /* {{{ */
  1171. {
  1172. zval *tmp;
  1173. MAKE_STD_ZVAL(tmp);
  1174. ZVAL_LONG(tmp, l);
  1175. return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
  1176. }
  1177. /* }}} */
  1178. ZEND_API int add_get_index_double(zval *arg, ulong index, double d, void **dest) /* {{{ */
  1179. {
  1180. zval *tmp;
  1181. MAKE_STD_ZVAL(tmp);
  1182. ZVAL_DOUBLE(tmp, d);
  1183. return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
  1184. }
  1185. /* }}} */
  1186. ZEND_API int add_get_index_string(zval *arg, ulong index, const char *str, void **dest, int duplicate) /* {{{ */
  1187. {
  1188. zval *tmp;
  1189. MAKE_STD_ZVAL(tmp);
  1190. ZVAL_STRING(tmp, str, duplicate);
  1191. return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
  1192. }
  1193. /* }}} */
  1194. ZEND_API int add_get_index_stringl(zval *arg, ulong index, const char *str, uint length, void **dest, int duplicate) /* {{{ */
  1195. {
  1196. zval *tmp;
  1197. MAKE_STD_ZVAL(tmp);
  1198. ZVAL_STRINGL(tmp, str, length, duplicate);
  1199. return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
  1200. }
  1201. /* }}} */
  1202. ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, long n TSRMLS_DC) /* {{{ */
  1203. {
  1204. zval *tmp;
  1205. zval *z_key;
  1206. MAKE_STD_ZVAL(tmp);
  1207. ZVAL_LONG(tmp, n);
  1208. MAKE_STD_ZVAL(z_key);
  1209. ZVAL_STRINGL(z_key, key, key_len-1, 1);
  1210. Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
  1211. zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
  1212. zval_ptr_dtor(&z_key);
  1213. return SUCCESS;
  1214. }
  1215. /* }}} */
  1216. ZEND_API int add_property_bool_ex(zval *arg, const char *key, uint key_len, int b TSRMLS_DC) /* {{{ */
  1217. {
  1218. zval *tmp;
  1219. zval *z_key;
  1220. MAKE_STD_ZVAL(tmp);
  1221. ZVAL_BOOL(tmp, b);
  1222. MAKE_STD_ZVAL(z_key);
  1223. ZVAL_STRINGL(z_key, key, key_len-1, 1);
  1224. Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
  1225. zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
  1226. zval_ptr_dtor(&z_key);
  1227. return SUCCESS;
  1228. }
  1229. /* }}} */
  1230. ZEND_API int add_property_null_ex(zval *arg, const char *key, uint key_len TSRMLS_DC) /* {{{ */
  1231. {
  1232. zval *tmp;
  1233. zval *z_key;
  1234. MAKE_STD_ZVAL(tmp);
  1235. ZVAL_NULL(tmp);
  1236. MAKE_STD_ZVAL(z_key);
  1237. ZVAL_STRINGL(z_key, key, key_len-1, 1);
  1238. Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
  1239. zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
  1240. zval_ptr_dtor(&z_key);
  1241. return SUCCESS;
  1242. }
  1243. /* }}} */
  1244. ZEND_API int add_property_resource_ex(zval *arg, const char *key, uint key_len, long n TSRMLS_DC) /* {{{ */
  1245. {
  1246. zval *tmp;
  1247. zval *z_key;
  1248. MAKE_STD_ZVAL(tmp);
  1249. ZVAL_RESOURCE(tmp, n);
  1250. MAKE_STD_ZVAL(z_key);
  1251. ZVAL_STRINGL(z_key, key, key_len-1, 1);
  1252. Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
  1253. zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
  1254. zval_ptr_dtor(&z_key);
  1255. return SUCCESS;
  1256. }
  1257. /* }}} */
  1258. ZEND_API int add_property_double_ex(zval *arg, const char *key, uint key_len, double d TSRMLS_DC) /* {{{ */
  1259. {
  1260. zval *tmp;
  1261. zval *z_key;
  1262. MAKE_STD_ZVAL(tmp);
  1263. ZVAL_DOUBLE(tmp, d);
  1264. MAKE_STD_ZVAL(z_key);
  1265. ZVAL_STRINGL(z_key, key, key_len-1, 1);
  1266. Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
  1267. zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
  1268. zval_ptr_dtor(&z_key);
  1269. return SUCCESS;
  1270. }
  1271. /* }}} */
  1272. ZEND_API int add_property_string_ex(zval *arg, const char *key, uint key_len, char *str, int duplicate TSRMLS_DC) /* {{{ */
  1273. {
  1274. zval *tmp;
  1275. zval *z_key;
  1276. MAKE_STD_ZVAL(tmp);
  1277. ZVAL_STRING(tmp, str, duplicate);
  1278. MAKE_STD_ZVAL(z_key);
  1279. ZVAL_STRINGL(z_key, key, key_len-1, 1);
  1280. Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
  1281. zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
  1282. zval_ptr_dtor(&z_key);
  1283. return SUCCESS;
  1284. }
  1285. /* }}} */
  1286. ZEND_API int add_property_stringl_ex(zval *arg, const char *key, uint key_len, char *str, uint length, int duplicate TSRMLS_DC) /* {{{ */
  1287. {
  1288. zval *tmp;
  1289. zval *z_key;
  1290. MAKE_STD_ZVAL(tmp);
  1291. ZVAL_STRINGL(tmp, str, length, duplicate);
  1292. MAKE_STD_ZVAL(z_key);
  1293. ZVAL_STRINGL(z_key, key, key_len-1, 1);
  1294. Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
  1295. zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
  1296. zval_ptr_dtor(&z_key);
  1297. return SUCCESS;
  1298. }
  1299. /* }}} */
  1300. ZEND_API int add_property_zval_ex(zval *arg, const char *key, uint key_len, zval *value TSRMLS_DC) /* {{{ */
  1301. {
  1302. zval *z_key;
  1303. MAKE_STD_ZVAL(z_key);
  1304. ZVAL_STRINGL(z_key, key, key_len-1, 1);
  1305. Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, value TSRMLS_CC);
  1306. zval_ptr_dtor(&z_key);
  1307. return SUCCESS;
  1308. }
  1309. /* }}} */
  1310. ZEND_API int zend_startup_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */
  1311. {
  1312. int name_len;
  1313. char *lcname;
  1314. if (module->module_started) {
  1315. return SUCCESS;
  1316. }
  1317. module->module_started = 1;
  1318. /* Check module dependencies */
  1319. if (module->deps) {
  1320. const zend_module_dep *dep = module->deps;
  1321. while (dep->name) {
  1322. if (dep->type == MODULE_DEP_REQUIRED) {
  1323. zend_module_entry *req_mod;
  1324. name_len = strlen(dep->name);
  1325. lcname = zend_str_tolower_dup(dep->name, name_len);
  1326. if (zend_hash_find(&module_registry, lcname, name_len+1, (void**)&req_mod) == FAILURE || !req_mod->module_started) {
  1327. efree(lcname);
  1328. /* TODO: Check version relationship */
  1329. zend_error(E_CORE_WARNING, "Cannot load module '%s' because required module '%s' is not loaded", module->name, dep->name);
  1330. module->module_started = 0;
  1331. return FAILURE;
  1332. }
  1333. efree(lcname);
  1334. }
  1335. ++dep;
  1336. }
  1337. }
  1338. /* Initialize module globals */
  1339. if (module->globals_size) {
  1340. #ifdef ZTS
  1341. ts_allocate_id(module->globals_id_ptr, module->globals_size, (ts_allocate_ctor) module->globals_ctor, (ts_allocate_dtor) module->globals_dtor);
  1342. #else
  1343. if (module->globals_ctor) {
  1344. module->globals_ctor(module->globals_ptr TSRMLS_CC);
  1345. }
  1346. #endif
  1347. }
  1348. if (module->module_startup_func) {
  1349. EG(current_module) = module;
  1350. if (module->module_startup_func(module->type, module->module_number TSRMLS_CC)==FAILURE) {
  1351. zend_error(E_CORE_ERROR,"Unable to start %s module", module->name);
  1352. EG(current_module) = NULL;
  1353. return FAILURE;
  1354. }
  1355. EG(current_module) = NULL;
  1356. }
  1357. return SUCCESS;
  1358. }
  1359. /* }}} */
  1360. static void zend_sort_modules(void *base, size_t count, size_t siz, compare_func_t compare TSRMLS_DC) /* {{{ */
  1361. {
  1362. Bucket **b1 = base;
  1363. Bucket **b2;
  1364. Bucket **end = b1 + count;
  1365. Bucket *tmp;
  1366. zend_module_entry *m, *r;
  1367. while (b1 < end) {
  1368. try_again:
  1369. m = (zend_module_entry*)(*b1)->pData;
  1370. if (!m->module_started && m->deps) {
  1371. const zend_module_dep *dep = m->deps;
  1372. while (dep->name) {
  1373. if (dep->type == MODULE_DEP_REQUIRED || dep->type == MODULE_DEP_OPTIONAL) {
  1374. b2 = b1 + 1;
  1375. while (b2 < end) {
  1376. r = (zend_module_entry*)(*b2)->pData;
  1377. if (strcasecmp(dep->name, r->name) == 0) {
  1378. tmp = *b1;
  1379. *b1 = *b2;
  1380. *b2 = tmp;
  1381. goto try_again;
  1382. }
  1383. b2++;
  1384. }
  1385. }
  1386. dep++;
  1387. }
  1388. }
  1389. b1++;
  1390. }
  1391. }
  1392. /* }}} */
  1393. ZEND_API int zend_startup_modules(TSRMLS_D) /* {{{ */
  1394. {
  1395. zend_hash_sort(&module_registry, zend_sort_modules, NULL, 0 TSRMLS_CC);
  1396. zend_hash_apply(&module_registry, (apply_func_t)zend_startup_module_ex TSRMLS_CC);
  1397. return SUCCESS;
  1398. }
  1399. /* }}} */
  1400. ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */
  1401. {
  1402. int name_len;
  1403. char *lcname;
  1404. zend_module_entry *module_ptr;
  1405. if (!module) {
  1406. return NULL;
  1407. }
  1408. #if 0
  1409. zend_printf("%s: Registering module %d\n", module->name, module->module_number);
  1410. #endif
  1411. /* Check module dependencies */
  1412. if (module->deps) {
  1413. const zend_module_dep *dep = module->deps;
  1414. while (dep->name) {
  1415. if (dep->type == MODULE_DEP_CONFLICTS) {
  1416. name_len = strlen(dep->name);
  1417. lcname = zend_str_tolower_dup(dep->name, name_len);
  1418. if (zend_hash_exists(&module_registry, lcname, name_len+1)) {
  1419. efree(lcname);
  1420. /* TODO: Check version relationship */
  1421. zend_error(E_CORE_WARNING, "Cannot load module '%s' because conflicting module '%s' is already loaded", module->name, dep->name);
  1422. return NULL;
  1423. }
  1424. efree(lcname);
  1425. }
  1426. ++dep;
  1427. }
  1428. }
  1429. name_len = strlen(module->name);
  1430. lcname = zend_str_tolower_dup(module->name, name_len);
  1431. if (zend_hash_add(&module_registry, lcname, name_len+1, (void *)module, sizeof(zend_module_entry), (void**)&module_ptr)==FAILURE) {
  1432. zend_error(E_CORE_WARNING, "Module '%s' already loaded", module->name);
  1433. efree(lcname);
  1434. return NULL;
  1435. }
  1436. efree(lcname);
  1437. module = module_ptr;
  1438. EG(current_module) = module;
  1439. if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type TSRMLS_CC)==FAILURE) {
  1440. EG(current_module) = NULL;
  1441. zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name);
  1442. return NULL;
  1443. }
  1444. EG(current_module) = NULL;
  1445. return module;
  1446. }
  1447. /* }}} */
  1448. ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *module TSRMLS_DC) /* {{{ */
  1449. {
  1450. module->module_number = zend_next_free_module();
  1451. module->type = MODULE_PERSISTENT;
  1452. return zend_register_module_ex(module TSRMLS_CC);
  1453. }
  1454. /* }}} */
  1455. ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, int error_type TSRMLS_DC) /* {{{ */
  1456. {
  1457. char lcname[16];
  1458. int name_len;
  1459. /* we don't care if the function name is longer, in fact lowercasing only
  1460. * the beginning of the name speeds up the check process */
  1461. name_len = strlen(fptr->common.function_name);
  1462. zend_str_tolower_copy(lcname, fptr->common.function_name, MIN(name_len, sizeof(lcname)-1));
  1463. lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
  1464. 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) {
  1465. zend_error(error_type, "Destructor %s::%s() cannot take arguments", ce->name, ZEND_DESTRUCTOR_FUNC_NAME);
  1466. } 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) {
  1467. zend_error(error_type, "Method %s::%s() cannot accept any arguments", ce->name, ZEND_CLONE_FUNC_NAME);
  1468. } else if (name_len == sizeof(ZEND_GET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME))) {
  1469. if (fptr->common.num_args != 1) {
  1470. zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_GET_FUNC_NAME);
  1471. } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
  1472. zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_GET_FUNC_NAME);
  1473. }
  1474. } else if (name_len == sizeof(ZEND_SET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME))) {
  1475. if (fptr->common.num_args != 2) {
  1476. zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_SET_FUNC_NAME);
  1477. } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
  1478. zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_SET_FUNC_NAME);
  1479. }
  1480. } else if (name_len == sizeof(ZEND_UNSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME))) {
  1481. if (fptr->common.num_args != 1) {
  1482. zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_UNSET_FUNC_NAME);
  1483. } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
  1484. zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_UNSET_FUNC_NAME);
  1485. }
  1486. } else if (name_len == sizeof(ZEND_ISSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME))) {
  1487. if (fptr->common.num_args != 1) {
  1488. zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_ISSET_FUNC_NAME);
  1489. } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
  1490. zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_ISSET_FUNC_NAME);
  1491. }
  1492. } else if (name_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME))) {
  1493. if (fptr->common.num_args != 2) {
  1494. zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_CALL_FUNC_NAME);
  1495. } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
  1496. zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_CALL_FUNC_NAME);
  1497. }
  1498. } else if (name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1 &&
  1499. !memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1)
  1500. ) {
  1501. if (fptr->common.num_args != 2) {
  1502. zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_CALLSTATIC_FUNC_NAME);
  1503. } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
  1504. zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_CALLSTATIC_FUNC_NAME);
  1505. }
  1506. } else if (name_len == sizeof(ZEND_TOSTRING_FUNC_NAME) - 1 &&
  1507. !memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && fptr->common.num_args != 0
  1508. ) {
  1509. zend_error(error_type, "Method %s::%s() cannot take arguments", ce->name, ZEND_TOSTRING_FUNC_NAME);
  1510. }
  1511. }
  1512. /* }}} */
  1513. /* registers all functions in *library_functions in the function hash */
  1514. ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC) /* {{{ */
  1515. {
  1516. const zend_function_entry *ptr = functions;
  1517. zend_function function, *reg_function;
  1518. zend_internal_function *internal_function = (zend_internal_function *)&function;
  1519. int count=0, unload=0;
  1520. HashTable *target_function_table = function_table;
  1521. int error_type;
  1522. zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__callstatic = NULL, *__tostring = NULL;
  1523. char *lowercase_name;
  1524. int fname_len;
  1525. char *lc_class_name = NULL;
  1526. int class_name_len = 0;
  1527. if (type==MODULE_PERSISTENT) {
  1528. error_type = E_CORE_WARNING;
  1529. } else {
  1530. error_type = E_WARNING;
  1531. }
  1532. if (!target_function_table) {
  1533. target_function_table = CG(function_table);
  1534. }
  1535. internal_function->type = ZEND_INTERNAL_FUNCTION;
  1536. internal_function->module = EG(current_module);
  1537. if (scope) {
  1538. class_name_len = strlen(scope->name);
  1539. if ((lc_class_name = zend_memrchr(scope->name, '\\', class_name_len))) {
  1540. ++lc_class_name;
  1541. class_name_len -= (lc_class_name - scope->name);
  1542. lc_class_name = zend_str_tolower_dup(lc_class_name, class_name_len);
  1543. } else {
  1544. lc_class_name = zend_str_tolower_dup(scope->name, class_name_len);
  1545. }
  1546. }
  1547. while (ptr->fname) {
  1548. internal_function->handler = ptr->handler;
  1549. internal_function->function_name = (char*)ptr->fname;
  1550. internal_function->scope = scope;
  1551. internal_function->prototype = NULL;
  1552. if (ptr->arg_info) {
  1553. internal_function->arg_info = (zend_arg_info*)ptr->arg_info+1;
  1554. internal_function->num_args = ptr->num_args;
  1555. /* Currently you cannot denote that the function can accept less arguments than num_args */
  1556. if (ptr->arg_info[0].required_num_args == -1) {
  1557. internal_function->required_num_args = ptr->num_args;
  1558. } else {
  1559. internal_function->required_num_args = ptr->arg_info[0].required_num_args;
  1560. }
  1561. internal_function->pass_rest_by_reference = ptr->arg_info[0].pass_by_reference;
  1562. internal_function->return_reference = ptr->arg_info[0].return_reference;
  1563. } else {
  1564. internal_function->arg_info = NULL;
  1565. internal_function->num_args = 0;
  1566. internal_function->required_num_args = 0;
  1567. internal_function->pass_rest_by_reference = 0;
  1568. internal_function->return_reference = 0;
  1569. }
  1570. if (ptr->flags) {
  1571. if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
  1572. if (ptr->flags != ZEND_ACC_DEPRECATED || scope) {
  1573. 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);
  1574. }
  1575. internal_function->fn_flags = ZEND_ACC_PUBLIC | ptr->flags;
  1576. } else {
  1577. internal_function->fn_flags = ptr->flags;
  1578. }
  1579. } else {
  1580. internal_function->fn_flags = ZEND_ACC_PUBLIC;
  1581. }
  1582. if (ptr->flags & ZEND_ACC_ABSTRACT) {
  1583. if (scope) {
  1584. /* This is a class that must be abstract itself. Here we set the check info. */
  1585. scope->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
  1586. if (!(scope->ce_flags & ZEND_ACC_INTERFACE)) {
  1587. /* Since the class is not an interface it needs to be declared as a abstract class. */
  1588. /* Since here we are handling internal functions only we can add the keyword flag. */
  1589. /* This time we set the flag for the keyword 'abstract'. */
  1590. scope->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
  1591. }
  1592. }
  1593. if (ptr->flags & ZEND_ACC_STATIC && (!scope || !(scope->ce_flags & ZEND_ACC_INTERFACE))) {
  1594. zend_error(error_type, "Static function %s%s%s() cannot be abstract", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
  1595. }
  1596. } else {
  1597. if (scope && (scope->ce_flags & ZEND_ACC_INTERFACE)) {
  1598. efree(lc_class_name);
  1599. zend_error(error_type, "Interface %s cannot contain non abstract method %s()", scope->name, ptr->fname);
  1600. return FAILURE;
  1601. }
  1602. if (!internal_function->handler) {
  1603. if (scope) {
  1604. efree(lc_class_name);
  1605. }
  1606. zend_error(error_type, "Method %s%s%s() cannot be a NULL function", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
  1607. zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
  1608. return FAILURE;
  1609. }
  1610. }
  1611. fname_len = strlen(ptr->fname);
  1612. lowercase_name = zend_str_tolower_dup(ptr->fname, fname_len);
  1613. if (zend_hash_add(target_function_table, lowercase_name, fname_len+1, &function, sizeof(zend_function), (void**)&reg_function) == FAILURE) {
  1614. unload=1;
  1615. efree(lowercase_name);
  1616. break;
  1617. }
  1618. if (scope) {
  1619. /* Look for ctor, dtor, clone
  1620. * If it's an old-style constructor, store it only if we don't have
  1621. * a constructor already.
  1622. */
  1623. if ((fname_len == class_name_len) && !memcmp(lowercase_name, lc_class_name, class_name_len+1) && !ctor) {
  1624. ctor = reg_function;
  1625. } else if ((fname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) {
  1626. ctor = reg_function;
  1627. } else if ((fname_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME))) {
  1628. dtor = reg_function;
  1629. if (internal_function->num_args) {
  1630. zend_error(error_type, "Destructor %s::%s() cannot take arguments", scope->name, ptr->fname);
  1631. }
  1632. } else if ((fname_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME))) {
  1633. clone = reg_function;
  1634. } else if ((fname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME))) {
  1635. __call = reg_function;
  1636. } else if ((fname_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME))) {
  1637. __callstatic = reg_function;
  1638. } else if ((fname_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME))) {
  1639. __tostring = reg_function;
  1640. } else if ((fname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME))) {
  1641. __get = reg_function;
  1642. } else if ((fname_len == sizeof(ZEND_SET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME))) {
  1643. __set = reg_function;
  1644. } else if ((fname_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME))) {
  1645. __unset = reg_function;
  1646. } else if ((fname_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME))) {
  1647. __isset = reg_function;
  1648. } else {
  1649. reg_function = NULL;
  1650. }
  1651. if (reg_function) {
  1652. zend_check_magic_method_implementation(scope, reg_function, error_type TSRMLS_CC);
  1653. }
  1654. }
  1655. ptr++;
  1656. count++;
  1657. efree(lowercase_name);
  1658. }
  1659. if (unload) { /* before unloading, display all remaining bad function in the module */
  1660. if (scope) {
  1661. efree(lc_class_name);
  1662. }
  1663. while (ptr->fname) {
  1664. fname_len = strlen(ptr->fname);
  1665. lowercase_name = zend_str_tolower_dup(ptr->fname, fname_len);
  1666. if (zend_hash_exists(target_function_table, lowercase_name, fname_len+1)) {
  1667. zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
  1668. }
  1669. efree(lowercase_name);
  1670. ptr++;
  1671. }
  1672. zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
  1673. return FAILURE;
  1674. }
  1675. if (scope) {
  1676. scope->constructor = ctor;
  1677. scope->destructor = dtor;
  1678. scope->clone = clone;
  1679. scope->__call = __call;
  1680. scope->__callstatic = __callstatic;
  1681. scope->__tostring = __tostring;
  1682. scope->__get = __get;
  1683. scope->__set = __set;
  1684. scope->__unset = __unset;
  1685. scope->__isset = __isset;
  1686. if (ctor) {
  1687. ctor->common.fn_flags |= ZEND_ACC_CTOR;
  1688. if (ctor->common.fn_flags & ZEND_ACC_STATIC) {
  1689. zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name, ctor->common.function_name);
  1690. }
  1691. ctor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
  1692. }
  1693. if (dtor) {
  1694. dtor->common.fn_flags |= ZEND_ACC_DTOR;
  1695. if (dtor->common.fn_flags & ZEND_ACC_STATIC) {
  1696. zend_error(error_type, "Destructor %s::%s() cannot be static", scope->name, dtor->common.function_name);
  1697. }
  1698. dtor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
  1699. }
  1700. if (clone) {
  1701. clone->common.fn_flags |= ZEND_ACC_CLONE;
  1702. if (clone->common.fn_flags & ZEND_ACC_STATIC) {
  1703. zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name, clone->common.function_name);
  1704. }
  1705. clone->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
  1706. }
  1707. if (__call) {
  1708. if (__call->common.fn_flags & ZEND_ACC_STATIC) {
  1709. zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __call->common.function_name);
  1710. }
  1711. __call->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
  1712. }
  1713. if (__callstatic) {
  1714. if (!(__callstatic->common.fn_flags & ZEND_ACC_STATIC)) {
  1715. zend_error(error_type, "Method %s::%s() must be static", scope->name, __callstatic->common.function_name);
  1716. }
  1717. __callstatic->common.fn_flags |= ZEND_ACC_STATIC;
  1718. }
  1719. if (__tostring) {
  1720. if (__tostring->common.fn_flags & ZEND_ACC_STATIC) {
  1721. zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __tostring->common.function_name);
  1722. }
  1723. __tostring->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
  1724. }
  1725. if (__get) {
  1726. if (__get->common.fn_flags & ZEND_ACC_STATIC) {
  1727. zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __get->common.function_name);
  1728. }
  1729. __get->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
  1730. }
  1731. if (__set) {
  1732. if (__set->common.fn_flags & ZEND_ACC_STATIC) {
  1733. zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __set->common.function_name);
  1734. }
  1735. __set->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
  1736. }
  1737. if (__unset) {
  1738. if (__unset->common.fn_flags & ZEND_ACC_STATIC) {
  1739. zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __unset->common.function_name);
  1740. }
  1741. __unset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
  1742. }
  1743. if (__isset) {
  1744. if (__isset->common.fn_flags & ZEND_ACC_STATIC) {
  1745. zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __isset->common.function_name);
  1746. }
  1747. __isset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
  1748. }
  1749. efree(lc_class_name);
  1750. }
  1751. return SUCCESS;
  1752. }
  1753. /* }}} */
  1754. /* count=-1 means erase all functions, otherwise,
  1755. * erase the first count functions
  1756. */
  1757. ZEND_API void zend_unregister_functions(const zend_function_entry *functions, int count, HashTable *function_table TSRMLS_DC) /* {{{ */
  1758. {
  1759. const zend_function_entry *ptr = functions;
  1760. int i=0;
  1761. HashTable *target_function_table = function_table;
  1762. if (!target_function_table) {
  1763. target_function_table = CG(function_table);
  1764. }
  1765. while (ptr->fname) {
  1766. if (count!=-1 && i>=count) {
  1767. break;
  1768. }
  1769. #if 0
  1770. zend_printf("Unregistering %s()\n", ptr->fname);
  1771. #endif
  1772. zend_hash_del(target_function_table, ptr->fname, strlen(ptr->fname)+1);
  1773. ptr++;
  1774. i++;
  1775. }
  1776. }
  1777. /* }}} */
  1778. ZEND_API int zend_startup_module(zend_module_entry *module) /* {{{ */
  1779. {
  1780. TSRMLS_FETCH();
  1781. if ((module = zend_register_internal_module(module TSRMLS_CC)) != NULL && zend_startup_module_ex(module TSRMLS_CC) == SUCCESS) {
  1782. return SUCCESS;
  1783. }
  1784. return FAILURE;
  1785. }
  1786. /* }}} */
  1787. ZEND_API int zend_get_module_started(const char *module_name) /* {{{ */
  1788. {
  1789. zend_module_entry *module;
  1790. return (zend_hash_find(&module_registry, module_name, strlen(module_name)+1, (void**)&module) == SUCCESS && module->module_started) ? SUCCESS : FAILURE;
  1791. }
  1792. /* }}} */
  1793. void module_destructor(zend_module_entry *module) /* {{{ */
  1794. {
  1795. TSRMLS_FETCH();
  1796. if (module->type == MODULE_TEMPORARY) {
  1797. zend_clean_module_rsrc_dtors(module->module_number TSRMLS_CC);
  1798. clean_module_constants(module->module_number TSRMLS_CC);
  1799. }
  1800. if (module->module_started && module->module_shutdown_func) {
  1801. #if 0
  1802. zend_printf("%s: Module shutdown\n", module->name);
  1803. #endif
  1804. module->module_shutdown_func(module->type, module->module_number TSRMLS_CC);
  1805. }
  1806. /* Deinitilaise module globals */
  1807. if (module->globals_size) {
  1808. #ifdef ZTS
  1809. ts_free_id(*module->globals_id_ptr);
  1810. #else
  1811. if (module->globals_dtor) {
  1812. module->globals_dtor(module->globals_ptr TSRMLS_CC);
  1813. }
  1814. #endif
  1815. }
  1816. module->module_started=0;
  1817. if (module->functions) {
  1818. zend_unregister_functions(module->functions, -1, NULL TSRMLS_CC);
  1819. }
  1820. #if HAVE_LIBDL
  1821. #if !(defined(NETWARE) && defined(APACHE_1_BUILD))
  1822. if (module->handle) {
  1823. DL_UNLOAD(module->handle);
  1824. }
  1825. #endif
  1826. #endif
  1827. }
  1828. /* }}} */
  1829. /* call request startup for all modules */
  1830. int module_registry_request_startup(zend_module_entry *module TSRMLS_DC) /* {{{ */
  1831. {
  1832. if (module->request_startup_func) {
  1833. #if 0
  1834. zend_printf("%s: Request startup\n", module->name);
  1835. #endif
  1836. if (module->request_startup_func(module->type, module->module_number TSRMLS_CC)==FAILURE) {
  1837. zend_error(E_WARNING, "request_startup() for %s module failed", module->name);
  1838. exit(1);
  1839. }
  1840. }
  1841. return 0;
  1842. }
  1843. /* }}} */
  1844. /* call request shutdown for all modules */
  1845. int module_registry_cleanup(zend_module_entry *module TSRMLS_DC) /* {{{ */
  1846. {
  1847. if (module->request_shutdown_func) {
  1848. #if 0
  1849. zend_printf("%s: Request shutdown\n", module->name);
  1850. #endif
  1851. module->request_shutdown_func(module->type, module->module_number TSRMLS_CC);
  1852. }
  1853. return 0;
  1854. }
  1855. /* }}} */
  1856. int module_registry_unload_temp(const zend_module_entry *module TSRMLS_DC) /* {{{ */
  1857. {
  1858. return (module->type == MODULE_TEMPORARY) ? ZEND_HASH_APPLY_REMOVE : ZEND_HASH_APPLY_STOP;
  1859. }
  1860. /* }}} */
  1861. /* return the next free module number */
  1862. int zend_next_free_module(void) /* {{{ */
  1863. {
  1864. return ++module_count;
  1865. }
  1866. /* }}} */
  1867. static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, zend_uint ce_flags TSRMLS_DC) /* {{{ */
  1868. {
  1869. zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
  1870. char *lowercase_name = malloc(orig_class_entry->name_length + 1);
  1871. *class_entry = *orig_class_entry;
  1872. class_entry->type = ZEND_INTERNAL_CLASS;
  1873. zend_initialize_class_data(class_entry, 0 TSRMLS_CC);
  1874. class_entry->ce_flags = ce_flags;
  1875. class_entry->module = EG(current_module);
  1876. if (class_entry->builtin_functions) {
  1877. zend_register_functions(class_entry, class_entry->builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC);
  1878. }
  1879. zend_str_tolower_copy(lowercase_name, orig_class_entry->name, class_entry->name_length);
  1880. zend_hash_update(CG(class_table), lowercase_name, class_entry->name_length+1, &class_entry, sizeof(zend_class_entry *), NULL);
  1881. free(lowercase_name);
  1882. return class_entry;
  1883. }
  1884. /* }}} */
  1885. /* If parent_ce is not NULL then it inherits from parent_ce
  1886. * If parent_ce is NULL and parent_name isn't then it looks for the parent and inherits from it
  1887. * If both parent_ce and parent_name are NULL it does a regular class registration
  1888. * If parent_name is specified but not found NULL is returned
  1889. */
  1890. 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) /* {{{ */
  1891. {
  1892. zend_class_entry *register_class;
  1893. if (!parent_ce && parent_name) {
  1894. zend_class_entry **pce;
  1895. if (zend_hash_find(CG(class_table), parent_name, strlen(parent_name)+1, (void **) &pce)==FAILURE) {
  1896. return NULL;
  1897. } else {
  1898. parent_ce = *pce;
  1899. }
  1900. }
  1901. register_class = zend_register_internal_class(class_entry TSRMLS_CC);
  1902. if (parent_ce) {
  1903. zend_do_inheritance(register_class, parent_ce TSRMLS_CC);
  1904. }
  1905. return register_class;
  1906. }
  1907. /* }}} */
  1908. ZEND_API void zend_class_implements(zend_class_entry *class_entry TSRMLS_DC, int num_interfaces, ...) /* {{{ */
  1909. {
  1910. zend_class_entry *interface_entry;
  1911. va_list interface_list;
  1912. va_start(interface_list, num_interfaces);
  1913. while (num_interfaces--) {
  1914. interface_entry = va_arg(interface_list, zend_class_entry *);
  1915. zend_do_implement_interface(class_entry, interface_entry TSRMLS_CC);
  1916. }
  1917. va_end(interface_list);
  1918. }
  1919. /* }}} */
  1920. /* A class that contains at least one abstract method automatically becomes an abstract class.
  1921. */
  1922. ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry TSRMLS_DC) /* {{{ */
  1923. {
  1924. return do_register_internal_class(orig_class_entry, 0 TSRMLS_CC);
  1925. }
  1926. /* }}} */
  1927. ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry TSRMLS_DC) /* {{{ */
  1928. {
  1929. return do_register_internal_class(orig_class_entry, ZEND_ACC_INTERFACE TSRMLS_CC);
  1930. }
  1931. /* }}} */
  1932. ZEND_API int zend_register_class_alias_ex(const char *name, int name_len, zend_class_entry *ce TSRMLS_DC) /* {{{ */
  1933. {
  1934. char *lcname = zend_str_tolower_dup(name, name_len);
  1935. int ret;
  1936. ret = zend_hash_add(CG(class_table), lcname, name_len+1, &ce, sizeof(zend_class_entry *), NULL);
  1937. efree(lcname);
  1938. if (ret == SUCCESS) {
  1939. ce->refcount++;
  1940. }
  1941. return ret;
  1942. }
  1943. /* }}} */
  1944. ZEND_API int zend_set_hash_symbol(zval *symbol, const char *name, int name_length, zend_bool is_ref, int num_symbol_tables, ...) /* {{{ */
  1945. {
  1946. HashTable *symbol_table;
  1947. va_list symbol_table_list;
  1948. if (num_symbol_tables <= 0) return FAILURE;
  1949. Z_SET_ISREF_TO_P(symbol, is_ref);
  1950. va_start(symbol_table_list, num_symbol_tables);
  1951. while (num_symbol_tables-- > 0) {
  1952. symbol_table = va_arg(symbol_table_list, HashTable *);
  1953. zend_hash_update(symbol_table, name, name_length + 1, &symbol, sizeof(zval *), NULL);
  1954. zval_add_ref(&symbol);
  1955. }
  1956. va_end(symbol_table_list);
  1957. return SUCCESS;
  1958. }
  1959. /* }}} */
  1960. static int zend_is_callable_check_class(const char *name, int name_len, zend_fcall_info_cache *fcc, int *strict_class, char **error TSRMLS_DC) /* {{{ */
  1961. {
  1962. int ret = 0;
  1963. zend_class_entry **pce;
  1964. char *lcname = zend_str_tolower_dup(name, name_len);
  1965. *strict_class = 0;
  1966. if (name_len == sizeof("self") - 1 &&
  1967. !memcmp(lcname, "self", sizeof("self") - 1)) {
  1968. if (!EG(scope)) {
  1969. if (error) *error = estrdup("cannot access self:: when no class scope is active");
  1970. } else {
  1971. fcc->called_scope = EG(called_scope);
  1972. fcc->calling_scope = EG(scope);
  1973. if (!fcc->object_ptr) {
  1974. fcc->object_ptr = EG(This);
  1975. }
  1976. ret = 1;
  1977. }
  1978. } else if (name_len == sizeof("parent") - 1 &&
  1979. !memcmp(lcname, "parent", sizeof("parent") - 1)) {
  1980. if (!EG(scope)) {
  1981. if (error) *error = estrdup("cannot access parent:: when no class scope is active");
  1982. } else if (!EG(scope)->parent) {
  1983. if (error) *error = estrdup("cannot access parent:: when current class scope has no parent");
  1984. } else {
  1985. fcc->called_scope = EG(called_scope);
  1986. fcc->calling_scope = EG(scope)->parent;
  1987. if (!fcc->object_ptr) {
  1988. fcc->object_ptr = EG(This);
  1989. }
  1990. *strict_class = 1;
  1991. ret = 1;
  1992. }
  1993. } else if (name_len == sizeof("static") - 1 &&
  1994. !memcmp(lcname, "static", sizeof("static") - 1)) {
  1995. if (!EG(called_scope)) {
  1996. if (error) *error = estrdup("cannot access static:: when no class scope is active");
  1997. } else {
  1998. fcc->called_scope = EG(called_scope);
  1999. fcc->calling_scope = EG(called_scope);
  2000. if (!fcc->object_ptr) {
  2001. fcc->object_ptr = EG(This);
  2002. }
  2003. *strict_class = 1;
  2004. ret = 1;
  2005. }
  2006. } else if (zend_lookup_class_ex(name, name_len, 1, &pce TSRMLS_CC) == SUCCESS) {
  2007. zend_class_entry *scope = EG(active_op_array) ? EG(active_op_array)->scope : NULL;
  2008. fcc->calling_scope = *pce;
  2009. if (scope && !fcc->object_ptr && EG(This) &&
  2010. instanceof_function(Z_OBJCE_P(EG(This)), scope TSRMLS_CC) &&
  2011. instanceof_function(scope, fcc->calling_scope TSRMLS_CC)) {
  2012. fcc->object_ptr = EG(This);
  2013. fcc->called_scope = Z_OBJCE_P(fcc->object_ptr);
  2014. } else {
  2015. fcc->called_scope = fcc->object_ptr ? Z_OBJCE_P(fcc->object_ptr) : fcc->calling_scope;
  2016. }
  2017. *strict_class = 1;
  2018. ret = 1;
  2019. } else {
  2020. if (error) zend_spprintf(error, 0, "class '%.*s' not found", name_len, name);
  2021. }
  2022. efree(lcname);
  2023. return ret;
  2024. }
  2025. /* }}} */
  2026. static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fcall_info_cache *fcc, int strict_class, char **error TSRMLS_DC) /* {{{ */
  2027. {
  2028. zend_class_entry *ce_org = fcc->calling_scope;
  2029. int retval = 0;
  2030. char *mname, *lmname, *colon;
  2031. int clen, mlen;
  2032. zend_class_entry *last_scope;
  2033. HashTable *ftable;
  2034. int call_via_handler = 0;
  2035. if (error) {
  2036. *error = NULL;
  2037. }
  2038. fcc->calling_scope = NULL;
  2039. fcc->function_handler = NULL;
  2040. if (!ce_org) {
  2041. /* Skip leading \ */
  2042. if (Z_STRVAL_P(callable)[0] == '\\') {
  2043. mlen = Z_STRLEN_P(callable) - 1;
  2044. mname = Z_STRVAL_P(callable) + 1;
  2045. lmname = zend_str_tolower_dup(Z_STRVAL_P(callable) + 1, mlen);
  2046. } else {
  2047. mlen = Z_STRLEN_P(callable);
  2048. mname = Z_STRVAL_P(callable);
  2049. lmname = zend_str_tolower_dup(Z_STRVAL_P(callable), mlen);
  2050. }
  2051. /* Check if function with given name exists.
  2052. * This may be a compound name that includes namespace name */
  2053. if (zend_hash_find(EG(function_table), lmname, mlen+1, (void**)&fcc->function_handler) == SUCCESS) {
  2054. efree(lmname);
  2055. return 1;
  2056. }
  2057. efree(lmname);
  2058. }
  2059. /* Split name into class/namespace and method/function names */
  2060. if ((colon = zend_memrchr(Z_STRVAL_P(callable), ':', Z_STRLEN_P(callable))) != NULL &&
  2061. colon > Z_STRVAL_P(callable) &&
  2062. *(colon-1) == ':'
  2063. ) {
  2064. colon--;
  2065. clen = colon - Z_STRVAL_P(callable);
  2066. mlen = Z_STRLEN_P(callable) - clen - 2;
  2067. if (colon == Z_STRVAL_P(callable)) {
  2068. if (error) zend_spprintf(error, 0, "invalid function name");
  2069. return 0;
  2070. }
  2071. /* This is a compound name.
  2072. * Try to fetch class and then find static method. */
  2073. last_scope = EG(scope);
  2074. if (ce_org) {
  2075. EG(scope) = ce_org;
  2076. }
  2077. if (!zend_is_callable_check_class(Z_STRVAL_P(callable), clen, fcc, &strict_class, error TSRMLS_CC)) {
  2078. EG(scope) = last_scope;
  2079. return 0;
  2080. }
  2081. EG(scope) = last_scope;
  2082. ftable = &fcc->calling_scope->function_table;
  2083. if (ce_org && !instanceof_function(ce_org, fcc->calling_scope TSRMLS_CC)) {
  2084. if (error) zend_spprintf(error, 0, "class '%s' is not a subclass of '%s'", ce_org->name, fcc->calling_scope->name);
  2085. return 0;
  2086. }
  2087. mname = Z_STRVAL_P(callable) + clen + 2;
  2088. } else if (ce_org) {
  2089. /* Try to fetch find static method of given class. */
  2090. mlen = Z_STRLEN_P(callable);
  2091. mname = Z_STRVAL_P(callable);
  2092. ftable = &ce_org->function_table;
  2093. fcc->calling_scope = ce_org;
  2094. } else {
  2095. /* We already checked for plain function before. */
  2096. if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) {
  2097. zend_spprintf(error, 0, "function '%s' not found or invalid function name", Z_STRVAL_P(callable));
  2098. }
  2099. return 0;
  2100. }
  2101. lmname = zend_str_tolower_dup(mname, mlen);
  2102. if (strict_class &&
  2103. fcc->calling_scope &&
  2104. mlen == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1 &&
  2105. !memcmp(lmname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) {
  2106. fcc->function_handler = fcc->calling_scope->constructor;
  2107. if (fcc->function_handler) {
  2108. retval = 1;
  2109. }
  2110. } else if (zend_hash_find(ftable, lmname, mlen+1, (void**)&fcc->function_handler) == SUCCESS) {
  2111. retval = 1;
  2112. if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) &&
  2113. EG(scope) &&
  2114. instanceof_function(fcc->function_handler->common.scope, EG(scope) TSRMLS_CC)) {
  2115. zend_function *priv_fbc;
  2116. if (zend_hash_find(&EG(scope)->function_table, lmname, mlen+1, (void **) &priv_fbc)==SUCCESS
  2117. && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE
  2118. && priv_fbc->common.scope == EG(scope)) {
  2119. fcc->function_handler = priv_fbc;
  2120. }
  2121. }
  2122. if ((check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0 &&
  2123. (fcc->calling_scope &&
  2124. (fcc->calling_scope->__call ||
  2125. fcc->calling_scope->__callstatic))) {
  2126. if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
  2127. if (!zend_check_private(fcc->function_handler, fcc->object_ptr ? Z_OBJCE_P(fcc->object_ptr) : EG(scope), lmname, mlen TSRMLS_CC)) {
  2128. retval = 0;
  2129. fcc->function_handler = NULL;
  2130. goto get_function_via_handler;
  2131. }
  2132. } else if (fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED) {
  2133. if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) {
  2134. retval = 0;
  2135. fcc->function_handler = NULL;
  2136. goto get_function_via_handler;
  2137. }
  2138. }
  2139. }
  2140. } else {
  2141. get_function_via_handler:
  2142. if (fcc->object_ptr && fcc->calling_scope == ce_org) {
  2143. if (strict_class && ce_org->__call) {
  2144. fcc->function_handler = emalloc(sizeof(zend_internal_function));
  2145. fcc->function_handler->internal_function.type = ZEND_INTERNAL_FUNCTION;
  2146. fcc->function_handler->internal_function.module = ce_org->module;
  2147. fcc->function_handler->internal_function.handler = zend_std_call_user_call;
  2148. fcc->function_handler->internal_function.arg_info = NULL;
  2149. fcc->function_handler->internal_function.num_args = 0;
  2150. fcc->function_handler->internal_function.scope = ce_org;
  2151. fcc->function_handler->internal_function.fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
  2152. fcc->function_handler->internal_function.function_name = estrndup(mname, mlen);
  2153. fcc->function_handler->internal_function.pass_rest_by_reference = 0;
  2154. fcc->function_handler->internal_function.return_reference = ZEND_RETURN_VALUE;
  2155. call_via_handler = 1;
  2156. retval = 1;
  2157. } else if (Z_OBJ_HT_P(fcc->object_ptr)->get_method) {
  2158. fcc->function_handler = Z_OBJ_HT_P(fcc->object_ptr)->get_method(&fcc->object_ptr, mname, mlen TSRMLS_CC);
  2159. if (fcc->function_handler) {
  2160. if (strict_class &&
  2161. (!fcc->function_handler->common.scope ||
  2162. !instanceof_function(ce_org, fcc->function_handler->common.scope TSRMLS_CC))) {
  2163. if ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0) {
  2164. if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
  2165. efree(fcc->function_handler->common.function_name);
  2166. }
  2167. efree(fcc->function_handler);
  2168. }
  2169. } else {
  2170. retval = 1;
  2171. call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
  2172. }
  2173. }
  2174. }
  2175. } else if (fcc->calling_scope) {
  2176. if (fcc->calling_scope->get_static_method) {
  2177. fcc->function_handler = fcc->calling_scope->get_static_method(fcc->calling_scope, mname, mlen TSRMLS_CC);
  2178. } else {
  2179. fcc->function_handler = zend_std_get_static_method(fcc->calling_scope, mname, mlen TSRMLS_CC);
  2180. }
  2181. if (fcc->function_handler) {
  2182. retval = 1;
  2183. call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
  2184. }
  2185. }
  2186. }
  2187. if (retval) {
  2188. if (fcc->calling_scope && !call_via_handler) {
  2189. if (!fcc->object_ptr && !(fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) {
  2190. int severity;
  2191. char *verb;
  2192. if (fcc->function_handler->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
  2193. severity = E_STRICT;
  2194. verb = "should not";
  2195. } else {
  2196. /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
  2197. severity = E_ERROR;
  2198. verb = "cannot";
  2199. }
  2200. if ((check_flags & IS_CALLABLE_CHECK_IS_STATIC) != 0) {
  2201. retval = 0;
  2202. }
  2203. if (EG(This) && instanceof_function(Z_OBJCE_P(EG(This)), fcc->calling_scope TSRMLS_CC)) {
  2204. fcc->object_ptr = EG(This);
  2205. if (error) {
  2206. zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically, assuming $this from compatible context %s", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb, Z_OBJCE_P(EG(This))->name);
  2207. if (severity == E_ERROR) {
  2208. retval = 0;
  2209. }
  2210. } else if (retval) {
  2211. zend_error(severity, "Non-static method %s::%s() %s be called statically, assuming $this from compatible context %s", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb, Z_OBJCE_P(EG(This))->name);
  2212. }
  2213. } else {
  2214. if (error) {
  2215. zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb);
  2216. if (severity == E_ERROR) {
  2217. retval = 0;
  2218. }
  2219. } else if (retval) {
  2220. zend_error(severity, "Non-static method %s::%s() %s be called statically", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb);
  2221. }
  2222. }
  2223. }
  2224. if (retval && (check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0) {
  2225. if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
  2226. if (!zend_check_private(fcc->function_handler, fcc->object_ptr ? Z_OBJCE_P(fcc->object_ptr) : EG(scope), lmname, mlen TSRMLS_CC)) {
  2227. if (error) {
  2228. if (*error) {
  2229. efree(*error);
  2230. }
  2231. zend_spprintf(error, 0, "cannot access private method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
  2232. }
  2233. retval = 0;
  2234. }
  2235. } else if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED)) {
  2236. if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) {
  2237. if (error) {
  2238. if (*error) {
  2239. efree(*error);
  2240. }
  2241. zend_spprintf(error, 0, "cannot access protected method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
  2242. }
  2243. retval = 0;
  2244. }
  2245. }
  2246. }
  2247. }
  2248. } else if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) {
  2249. if (fcc->calling_scope) {
  2250. if (error) zend_spprintf(error, 0, "class '%s' does not have a method '%s'", fcc->calling_scope->name, mname);
  2251. } else {
  2252. if (error) zend_spprintf(error, 0, "function '%s' does not exist", mname);
  2253. }
  2254. }
  2255. efree(lmname);
  2256. if (fcc->object_ptr) {
  2257. fcc->called_scope = Z_OBJCE_P(fcc->object_ptr);
  2258. }
  2259. if (retval) {
  2260. fcc->initialized = 1;
  2261. }
  2262. return retval;
  2263. }
  2264. /* }}} */
  2265. ZEND_API zend_bool zend_is_callable_ex(zval *callable, zval *object_ptr, uint check_flags, char **callable_name, int *callable_name_len, zend_fcall_info_cache *fcc, char **error TSRMLS_DC) /* {{{ */
  2266. {
  2267. zend_bool ret;
  2268. int callable_name_len_local;
  2269. zend_fcall_info_cache fcc_local;
  2270. if (callable_name) {
  2271. *callable_name = NULL;
  2272. }
  2273. if (callable_name_len == NULL) {
  2274. callable_name_len = &callable_name_len_local;
  2275. }
  2276. if (fcc == NULL) {
  2277. fcc = &fcc_local;
  2278. }
  2279. if (error) {
  2280. *error = NULL;
  2281. }
  2282. fcc->initialized = 0;
  2283. fcc->calling_scope = NULL;
  2284. fcc->called_scope = NULL;
  2285. fcc->function_handler = NULL;
  2286. fcc->calling_scope = NULL;
  2287. fcc->object_ptr = NULL;
  2288. if (object_ptr && Z_TYPE_P(object_ptr) != IS_OBJECT) {
  2289. object_ptr = NULL;
  2290. }
  2291. if (object_ptr &&
  2292. (!EG(objects_store).object_buckets ||
  2293. !EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(object_ptr)].valid)) {
  2294. return 0;
  2295. }
  2296. switch (Z_TYPE_P(callable)) {
  2297. case IS_STRING:
  2298. if (object_ptr) {
  2299. fcc->object_ptr = object_ptr;
  2300. fcc->calling_scope = Z_OBJCE_P(object_ptr);
  2301. if (callable_name) {
  2302. char *ptr;
  2303. *callable_name_len = fcc->calling_scope->name_length + Z_STRLEN_P(callable) + sizeof("::") - 1;
  2304. ptr = *callable_name = emalloc(*callable_name_len + 1);
  2305. memcpy(ptr, fcc->calling_scope->name, fcc->calling_scope->name_length);
  2306. ptr += fcc->calling_scope->name_length;
  2307. memcpy(ptr, "::", sizeof("::") - 1);
  2308. ptr += sizeof("::") - 1;
  2309. memcpy(ptr, Z_STRVAL_P(callable), Z_STRLEN_P(callable) + 1);
  2310. }
  2311. } else if (callable_name) {
  2312. *callable_name = estrndup(Z_STRVAL_P(callable), Z_STRLEN_P(callable));
  2313. *callable_name_len = Z_STRLEN_P(callable);
  2314. }
  2315. if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
  2316. fcc->called_scope = fcc->calling_scope;
  2317. return 1;
  2318. }
  2319. ret = zend_is_callable_check_func(check_flags, callable, fcc, 0, error TSRMLS_CC);
  2320. if (fcc == &fcc_local &&
  2321. fcc->function_handler &&
  2322. ((fcc->function_handler->type == ZEND_INTERNAL_FUNCTION &&
  2323. (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) ||
  2324. fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
  2325. fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
  2326. if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
  2327. efree(fcc->function_handler->common.function_name);
  2328. }
  2329. efree(fcc->function_handler);
  2330. }
  2331. return ret;
  2332. case IS_ARRAY:
  2333. {
  2334. zval **method = NULL;
  2335. zval **obj = NULL;
  2336. int strict_class = 0;
  2337. if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
  2338. zend_hash_index_find(Z_ARRVAL_P(callable), 0, (void **) &obj);
  2339. zend_hash_index_find(Z_ARRVAL_P(callable), 1, (void **) &method);
  2340. }
  2341. if (obj && method &&
  2342. (Z_TYPE_PP(obj) == IS_OBJECT ||
  2343. Z_TYPE_PP(obj) == IS_STRING) &&
  2344. Z_TYPE_PP(method) == IS_STRING) {
  2345. if (Z_TYPE_PP(obj) == IS_STRING) {
  2346. if (callable_name) {
  2347. char *ptr;
  2348. *callable_name_len = Z_STRLEN_PP(obj) + Z_STRLEN_PP(method) + sizeof("::") - 1;
  2349. ptr = *callable_name = emalloc(*callable_name_len + 1);
  2350. memcpy(ptr, Z_STRVAL_PP(obj), Z_STRLEN_PP(obj));
  2351. ptr += Z_STRLEN_PP(obj);
  2352. memcpy(ptr, "::", sizeof("::") - 1);
  2353. ptr += sizeof("::") - 1;
  2354. memcpy(ptr, Z_STRVAL_PP(method), Z_STRLEN_PP(method) + 1);
  2355. }
  2356. if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
  2357. return 1;
  2358. }
  2359. if (!zend_is_callable_check_class(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), fcc, &strict_class, error TSRMLS_CC)) {
  2360. return 0;
  2361. }
  2362. } else {
  2363. if (!EG(objects_store).object_buckets ||
  2364. !EG(objects_store).object_buckets[Z_OBJ_HANDLE_PP(obj)].valid) {
  2365. return 0;
  2366. }
  2367. fcc->calling_scope = Z_OBJCE_PP(obj); /* TBFixed: what if it's overloaded? */
  2368. fcc->object_ptr = *obj;
  2369. if (callable_name) {
  2370. char *ptr;
  2371. *callable_name_len = fcc->calling_scope->name_length + Z_STRLEN_PP(method) + sizeof("::") - 1;
  2372. ptr = *callable_name = emalloc(*callable_name_len + 1);
  2373. memcpy(ptr, fcc->calling_scope->name, fcc->calling_scope->name_length);
  2374. ptr += fcc->calling_scope->name_length;
  2375. memcpy(ptr, "::", sizeof("::") - 1);
  2376. ptr += sizeof("::") - 1;
  2377. memcpy(ptr, Z_STRVAL_PP(method), Z_STRLEN_PP(method) + 1);
  2378. }
  2379. if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
  2380. fcc->called_scope = fcc->calling_scope;
  2381. return 1;
  2382. }
  2383. }
  2384. ret = zend_is_callable_check_func(check_flags, *method, fcc, strict_class, error TSRMLS_CC);
  2385. if (fcc == &fcc_local &&
  2386. fcc->function_handler &&
  2387. ((fcc->function_handler->type == ZEND_INTERNAL_FUNCTION &&
  2388. (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) ||
  2389. fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
  2390. fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
  2391. if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
  2392. efree(fcc->function_handler->common.function_name);
  2393. }
  2394. efree(fcc->function_handler);
  2395. }
  2396. return ret;
  2397. } else {
  2398. if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
  2399. if (!obj || (Z_TYPE_PP(obj) != IS_STRING && Z_TYPE_PP(obj) != IS_OBJECT)) {
  2400. if (error) zend_spprintf(error, 0, "first array member is not a valid class name or object");
  2401. } else {
  2402. if (error) zend_spprintf(error, 0, "second array member is not a valid method");
  2403. }
  2404. } else {
  2405. if (error) zend_spprintf(error, 0, "array must have exactly two members");
  2406. }
  2407. if (callable_name) {
  2408. *callable_name = estrndup("Array", sizeof("Array")-1);
  2409. *callable_name_len = sizeof("Array") - 1;
  2410. }
  2411. }
  2412. }
  2413. return 0;
  2414. case IS_OBJECT:
  2415. if (Z_OBJ_HANDLER_P(callable, get_closure) && Z_OBJ_HANDLER_P(callable, get_closure)(callable, &fcc->calling_scope, &fcc->function_handler, &fcc->object_ptr TSRMLS_CC) == SUCCESS) {
  2416. fcc->called_scope = fcc->calling_scope;
  2417. if (callable_name) {
  2418. zend_class_entry *ce = Z_OBJCE_P(callable); /* TBFixed: what if it's overloaded? */
  2419. *callable_name_len = ce->name_length + sizeof("::__invoke") - 1;
  2420. *callable_name = emalloc(*callable_name_len + 1);
  2421. memcpy(*callable_name, ce->name, ce->name_length);
  2422. memcpy((*callable_name) + ce->name_length, "::__invoke", sizeof("::__invoke"));
  2423. }
  2424. return 1;
  2425. }
  2426. /* break missing intentionally */
  2427. default:
  2428. if (callable_name) {
  2429. zval expr_copy;
  2430. int use_copy;
  2431. zend_make_printable_zval(callable, &expr_copy, &use_copy);
  2432. *callable_name = estrndup(Z_STRVAL(expr_copy), Z_STRLEN(expr_copy));
  2433. *callable_name_len = Z_STRLEN(expr_copy);
  2434. zval_dtor(&expr_copy);
  2435. }
  2436. if (error) zend_spprintf(error, 0, "no array or string given");
  2437. return 0;
  2438. }
  2439. }
  2440. /* }}} */
  2441. ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **callable_name TSRMLS_DC) /* {{{ */
  2442. {
  2443. return zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, NULL, NULL TSRMLS_CC);
  2444. }
  2445. /* }}} */
  2446. ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRMLS_DC) /* {{{ */
  2447. {
  2448. zend_fcall_info_cache fcc;
  2449. if (zend_is_callable_ex(callable, NULL, IS_CALLABLE_STRICT, callable_name, NULL, &fcc, NULL TSRMLS_CC)) {
  2450. if (Z_TYPE_P(callable) == IS_STRING && fcc.calling_scope) {
  2451. zval_dtor(callable);
  2452. array_init(callable);
  2453. add_next_index_string(callable, fcc.calling_scope->name, 1);
  2454. add_next_index_string(callable, fcc.function_handler->common.function_name, 1);
  2455. }
  2456. if (fcc.function_handler &&
  2457. ((fcc.function_handler->type == ZEND_INTERNAL_FUNCTION &&
  2458. (fcc.function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) ||
  2459. fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
  2460. fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
  2461. if (fcc.function_handler->type != ZEND_OVERLOADED_FUNCTION) {
  2462. efree(fcc.function_handler->common.function_name);
  2463. }
  2464. efree(fcc.function_handler);
  2465. }
  2466. return 1;
  2467. }
  2468. return 0;
  2469. }
  2470. /* }}} */
  2471. ZEND_API int zend_fcall_info_init(zval *callable, uint check_flags, zend_fcall_info *fci, zend_fcall_info_cache *fcc, char **callable_name, char **error TSRMLS_DC) /* {{{ */
  2472. {
  2473. if (!zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, fcc, error TSRMLS_CC)) {
  2474. return FAILURE;
  2475. }
  2476. fci->size = sizeof(*fci);
  2477. fci->function_table = fcc->calling_scope ? &fcc->calling_scope->function_table : EG(function_table);
  2478. fci->object_ptr = fcc->object_ptr;
  2479. fci->function_name = callable;
  2480. fci->retval_ptr_ptr = NULL;
  2481. fci->param_count = 0;
  2482. fci->params = NULL;
  2483. fci->no_separation = 1;
  2484. fci->symbol_table = NULL;
  2485. return SUCCESS;
  2486. }
  2487. /* }}} */
  2488. ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, int free_mem) /* {{{ */
  2489. {
  2490. if (fci->params) {
  2491. if (free_mem) {
  2492. efree(fci->params);
  2493. fci->params = NULL;
  2494. }
  2495. }
  2496. fci->param_count = 0;
  2497. }
  2498. /* }}} */
  2499. ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, int *param_count, zval ****params) /* {{{ */
  2500. {
  2501. *param_count = fci->param_count;
  2502. *params = fci->params;
  2503. fci->param_count = 0;
  2504. fci->params = NULL;
  2505. }
  2506. /* }}} */
  2507. ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, int param_count, zval ***params) /* {{{ */
  2508. {
  2509. zend_fcall_info_args_clear(fci, 1);
  2510. fci->param_count = param_count;
  2511. fci->params = params;
  2512. }
  2513. /* }}} */
  2514. ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC) /* {{{ */
  2515. {
  2516. HashPosition pos;
  2517. zval **arg, ***params;
  2518. zend_fcall_info_args_clear(fci, !args);
  2519. if (!args) {
  2520. return SUCCESS;
  2521. }
  2522. if (Z_TYPE_P(args) != IS_ARRAY) {
  2523. return FAILURE;
  2524. }
  2525. fci->param_count = zend_hash_num_elements(Z_ARRVAL_P(args));
  2526. fci->params = params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **));
  2527. zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(args), &pos);
  2528. while (zend_hash_get_current_data_ex(Z_ARRVAL_P(args), (void *) &arg, &pos) == SUCCESS) {
  2529. *params++ = arg;
  2530. zend_hash_move_forward_ex(Z_ARRVAL_P(args), &pos);
  2531. }
  2532. return SUCCESS;
  2533. }
  2534. /* }}} */
  2535. ZEND_API int zend_fcall_info_argp(zend_fcall_info *fci TSRMLS_DC, int argc, zval ***argv) /* {{{ */
  2536. {
  2537. int i;
  2538. if (argc < 0) {
  2539. return FAILURE;
  2540. }
  2541. zend_fcall_info_args_clear(fci, !argc);
  2542. if (argc) {
  2543. fci->param_count = argc;
  2544. fci->params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **));
  2545. for (i = 0; i < argc; ++i) {
  2546. fci->params[i] = argv[i];
  2547. }
  2548. }
  2549. return SUCCESS;
  2550. }
  2551. /* }}} */
  2552. ZEND_API int zend_fcall_info_argv(zend_fcall_info *fci TSRMLS_DC, int argc, va_list *argv) /* {{{ */
  2553. {
  2554. int i;
  2555. zval **arg;
  2556. if (argc < 0) {
  2557. return FAILURE;
  2558. }
  2559. zend_fcall_info_args_clear(fci, !argc);
  2560. if (argc) {
  2561. fci->param_count = argc;
  2562. fci->params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **));
  2563. for (i = 0; i < argc; ++i) {
  2564. arg = va_arg(*argv, zval **);
  2565. fci->params[i] = arg;
  2566. }
  2567. }
  2568. return SUCCESS;
  2569. }
  2570. /* }}} */
  2571. ZEND_API int zend_fcall_info_argn(zend_fcall_info *fci TSRMLS_DC, int argc, ...) /* {{{ */
  2572. {
  2573. int ret;
  2574. va_list argv;
  2575. va_start(argv, argc);
  2576. ret = zend_fcall_info_argv(fci TSRMLS_CC, argc, &argv);
  2577. va_end(argv);
  2578. return ret;
  2579. }
  2580. /* }}} */
  2581. ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval **retval_ptr_ptr, zval *args TSRMLS_DC) /* {{{ */
  2582. {
  2583. zval *retval, ***org_params = NULL;
  2584. int result, org_count = 0;
  2585. fci->retval_ptr_ptr = retval_ptr_ptr ? retval_ptr_ptr : &retval;
  2586. if (args) {
  2587. zend_fcall_info_args_save(fci, &org_count, &org_params);
  2588. zend_fcall_info_args(fci, args TSRMLS_CC);
  2589. }
  2590. result = zend_call_function(fci, fcc TSRMLS_CC);
  2591. if (!retval_ptr_ptr && retval) {
  2592. zval_ptr_dtor(&retval);
  2593. }
  2594. if (args) {
  2595. zend_fcall_info_args_restore(fci, org_count, org_params);
  2596. }
  2597. return result;
  2598. }
  2599. /* }}} */
  2600. ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */
  2601. {
  2602. char *lname;
  2603. int name_len = strlen(module_name);
  2604. zend_module_entry *module;
  2605. lname = zend_str_tolower_dup(module_name, name_len);
  2606. if (zend_hash_find(&module_registry, lname, name_len + 1, (void**)&module) == FAILURE) {
  2607. efree(lname);
  2608. return NULL;
  2609. }
  2610. efree(lname);
  2611. return module->version;
  2612. }
  2613. /* }}} */
  2614. ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type, char *doc_comment, int doc_comment_len TSRMLS_DC) /* {{{ */
  2615. {
  2616. zend_property_info property_info;
  2617. HashTable *target_symbol_table;
  2618. if (!(access_type & ZEND_ACC_PPP_MASK)) {
  2619. access_type |= ZEND_ACC_PUBLIC;
  2620. }
  2621. if (access_type & ZEND_ACC_STATIC) {
  2622. target_symbol_table = &ce->default_static_members;
  2623. } else {
  2624. target_symbol_table = &ce->default_properties;
  2625. }
  2626. if (ce->type & ZEND_INTERNAL_CLASS) {
  2627. switch(Z_TYPE_P(property)) {
  2628. case IS_ARRAY:
  2629. case IS_CONSTANT_ARRAY:
  2630. case IS_OBJECT:
  2631. case IS_RESOURCE:
  2632. zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
  2633. break;
  2634. default:
  2635. break;
  2636. }
  2637. }
  2638. switch (access_type & ZEND_ACC_PPP_MASK) {
  2639. case ZEND_ACC_PRIVATE: {
  2640. char *priv_name;
  2641. int priv_name_length;
  2642. zend_mangle_property_name(&priv_name, &priv_name_length, ce->name, ce->name_length, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
  2643. zend_hash_update(target_symbol_table, priv_name, priv_name_length+1, &property, sizeof(zval *), NULL);
  2644. property_info.name = priv_name;
  2645. property_info.name_length = priv_name_length;
  2646. }
  2647. break;
  2648. case ZEND_ACC_PROTECTED: {
  2649. char *prot_name;
  2650. int prot_name_length;
  2651. zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
  2652. zend_hash_update(target_symbol_table, prot_name, prot_name_length+1, &property, sizeof(zval *), NULL);
  2653. property_info.name = prot_name;
  2654. property_info.name_length = prot_name_length;
  2655. }
  2656. break;
  2657. case ZEND_ACC_PUBLIC:
  2658. if (ce->parent) {
  2659. char *prot_name;
  2660. int prot_name_length;
  2661. zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
  2662. zend_hash_del(target_symbol_table, prot_name, prot_name_length+1);
  2663. pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
  2664. }
  2665. zend_hash_update(target_symbol_table, name, name_length+1, &property, sizeof(zval *), NULL);
  2666. property_info.name = ce->type & ZEND_INTERNAL_CLASS ? zend_strndup(name, name_length) : estrndup(name, name_length);
  2667. property_info.name_length = name_length;
  2668. break;
  2669. }
  2670. property_info.flags = access_type;
  2671. property_info.h = zend_get_hash_value(property_info.name, property_info.name_length+1);
  2672. property_info.doc_comment = doc_comment;
  2673. property_info.doc_comment_len = doc_comment_len;
  2674. property_info.ce = ce;
  2675. zend_hash_update(&ce->properties_info, name, name_length + 1, &property_info, sizeof(zend_property_info), NULL);
  2676. return SUCCESS;
  2677. }
  2678. /* }}} */
  2679. ZEND_API int zend_declare_property(zend_class_entry *ce, char *name, int name_length, zval *property, int access_type TSRMLS_DC) /* {{{ */
  2680. {
  2681. return zend_declare_property_ex(ce, name, name_length, property, access_type, NULL, 0 TSRMLS_CC);
  2682. }
  2683. /* }}} */
  2684. ZEND_API int zend_declare_property_null(zend_class_entry *ce, char *name, int name_length, int access_type TSRMLS_DC) /* {{{ */
  2685. {
  2686. zval *property;
  2687. if (ce->type & ZEND_INTERNAL_CLASS) {
  2688. ALLOC_PERMANENT_ZVAL(property);
  2689. } else {
  2690. ALLOC_ZVAL(property);
  2691. }
  2692. INIT_ZVAL(*property);
  2693. return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
  2694. }
  2695. /* }}} */
  2696. ZEND_API int zend_declare_property_bool(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC) /* {{{ */
  2697. {
  2698. zval *property;
  2699. if (ce->type & ZEND_INTERNAL_CLASS) {
  2700. ALLOC_PERMANENT_ZVAL(property);
  2701. } else {
  2702. ALLOC_ZVAL(property);
  2703. }
  2704. INIT_PZVAL(property);
  2705. ZVAL_BOOL(property, value);
  2706. return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
  2707. }
  2708. /* }}} */
  2709. ZEND_API int zend_declare_property_long(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC) /* {{{ */
  2710. {
  2711. zval *property;
  2712. if (ce->type & ZEND_INTERNAL_CLASS) {
  2713. ALLOC_PERMANENT_ZVAL(property);
  2714. } else {
  2715. ALLOC_ZVAL(property);
  2716. }
  2717. INIT_PZVAL(property);
  2718. ZVAL_LONG(property, value);
  2719. return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
  2720. }
  2721. /* }}} */
  2722. ZEND_API int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC) /* {{{ */
  2723. {
  2724. zval *property;
  2725. if (ce->type & ZEND_INTERNAL_CLASS) {
  2726. ALLOC_PERMANENT_ZVAL(property);
  2727. } else {
  2728. ALLOC_ZVAL(property);
  2729. }
  2730. INIT_PZVAL(property);
  2731. ZVAL_DOUBLE(property, value);
  2732. return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
  2733. }
  2734. /* }}} */
  2735. ZEND_API int zend_declare_property_string(zend_class_entry *ce, char *name, int name_length, char *value, int access_type TSRMLS_DC) /* {{{ */
  2736. {
  2737. zval *property;
  2738. int len = strlen(value);
  2739. if (ce->type & ZEND_INTERNAL_CLASS) {
  2740. ALLOC_PERMANENT_ZVAL(property);
  2741. ZVAL_STRINGL(property, zend_strndup(value, len), len, 0);
  2742. } else {
  2743. ALLOC_ZVAL(property);
  2744. ZVAL_STRINGL(property, value, len, 1);
  2745. }
  2746. INIT_PZVAL(property);
  2747. return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
  2748. }
  2749. /* }}} */
  2750. ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, char *name, int name_length, char *value, int value_len, int access_type TSRMLS_DC) /* {{{ */
  2751. {
  2752. zval *property;
  2753. if (ce->type & ZEND_INTERNAL_CLASS) {
  2754. ALLOC_PERMANENT_ZVAL(property);
  2755. ZVAL_STRINGL(property, zend_strndup(value, value_len), value_len, 0);
  2756. } else {
  2757. ALLOC_ZVAL(property);
  2758. ZVAL_STRINGL(property, value, value_len, 1);
  2759. }
  2760. INIT_PZVAL(property);
  2761. return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
  2762. }
  2763. /* }}} */
  2764. ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value TSRMLS_DC) /* {{{ */
  2765. {
  2766. return zend_hash_update(&ce->constants_table, name, name_length+1, &value, sizeof(zval *), NULL);
  2767. }
  2768. /* }}} */
  2769. ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length TSRMLS_DC) /* {{{ */
  2770. {
  2771. zval *constant;
  2772. if (ce->type & ZEND_INTERNAL_CLASS) {
  2773. ALLOC_PERMANENT_ZVAL(constant);
  2774. } else {
  2775. ALLOC_ZVAL(constant);
  2776. }
  2777. ZVAL_NULL(constant);
  2778. INIT_PZVAL(constant);
  2779. return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
  2780. }
  2781. /* }}} */
  2782. ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, long value TSRMLS_DC) /* {{{ */
  2783. {
  2784. zval *constant;
  2785. if (ce->type & ZEND_INTERNAL_CLASS) {
  2786. ALLOC_PERMANENT_ZVAL(constant);
  2787. } else {
  2788. ALLOC_ZVAL(constant);
  2789. }
  2790. ZVAL_LONG(constant, value);
  2791. INIT_PZVAL(constant);
  2792. return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
  2793. }
  2794. /* }}} */
  2795. ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_bool value TSRMLS_DC) /* {{{ */
  2796. {
  2797. zval *constant;
  2798. if (ce->type & ZEND_INTERNAL_CLASS) {
  2799. ALLOC_PERMANENT_ZVAL(constant);
  2800. } else {
  2801. ALLOC_ZVAL(constant);
  2802. }
  2803. ZVAL_BOOL(constant, value);
  2804. INIT_PZVAL(constant);
  2805. return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
  2806. }
  2807. /* }}} */
  2808. ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value TSRMLS_DC) /* {{{ */
  2809. {
  2810. zval *constant;
  2811. if (ce->type & ZEND_INTERNAL_CLASS) {
  2812. ALLOC_PERMANENT_ZVAL(constant);
  2813. } else {
  2814. ALLOC_ZVAL(constant);
  2815. }
  2816. ZVAL_DOUBLE(constant, value);
  2817. INIT_PZVAL(constant);
  2818. return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
  2819. }
  2820. /* }}} */
  2821. ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_length TSRMLS_DC) /* {{{ */
  2822. {
  2823. zval *constant;
  2824. if (ce->type & ZEND_INTERNAL_CLASS) {
  2825. ALLOC_PERMANENT_ZVAL(constant);
  2826. ZVAL_STRINGL(constant, zend_strndup(value, value_length), value_length, 0);
  2827. } else {
  2828. ALLOC_ZVAL(constant);
  2829. ZVAL_STRINGL(constant, value, value_length, 1);
  2830. }
  2831. INIT_PZVAL(constant);
  2832. return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
  2833. }
  2834. /* }}} */
  2835. ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value TSRMLS_DC) /* {{{ */
  2836. {
  2837. return zend_declare_class_constant_stringl(ce, name, name_length, value, strlen(value) TSRMLS_CC);
  2838. }
  2839. /* }}} */
  2840. ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char *name, int name_length, zval *value TSRMLS_DC) /* {{{ */
  2841. {
  2842. zval *property;
  2843. zend_class_entry *old_scope = EG(scope);
  2844. EG(scope) = scope;
  2845. if (!Z_OBJ_HT_P(object)->write_property) {
  2846. char *class_name;
  2847. zend_uint class_name_len;
  2848. zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC);
  2849. zend_error(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, class_name);
  2850. }
  2851. MAKE_STD_ZVAL(property);
  2852. ZVAL_STRINGL(property, name, name_length, 1);
  2853. Z_OBJ_HT_P(object)->write_property(object, property, value TSRMLS_CC);
  2854. zval_ptr_dtor(&property);
  2855. EG(scope) = old_scope;
  2856. }
  2857. /* }}} */
  2858. ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, char *name, int name_length TSRMLS_DC) /* {{{ */
  2859. {
  2860. zval *tmp;
  2861. ALLOC_ZVAL(tmp);
  2862. Z_UNSET_ISREF_P(tmp);
  2863. Z_SET_REFCOUNT_P(tmp, 0);
  2864. ZVAL_NULL(tmp);
  2865. zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
  2866. }
  2867. /* }}} */
  2868. ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC) /* {{{ */
  2869. {
  2870. zval *tmp;
  2871. ALLOC_ZVAL(tmp);
  2872. Z_UNSET_ISREF_P(tmp);
  2873. Z_SET_REFCOUNT_P(tmp, 0);
  2874. ZVAL_BOOL(tmp, value);
  2875. zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
  2876. }
  2877. /* }}} */
  2878. ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC) /* {{{ */
  2879. {
  2880. zval *tmp;
  2881. ALLOC_ZVAL(tmp);
  2882. Z_UNSET_ISREF_P(tmp);
  2883. Z_SET_REFCOUNT_P(tmp, 0);
  2884. ZVAL_LONG(tmp, value);
  2885. zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
  2886. }
  2887. /* }}} */
  2888. ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, char *name, int name_length, double value TSRMLS_DC) /* {{{ */
  2889. {
  2890. zval *tmp;
  2891. ALLOC_ZVAL(tmp);
  2892. Z_UNSET_ISREF_P(tmp);
  2893. Z_SET_REFCOUNT_P(tmp, 0);
  2894. ZVAL_DOUBLE(tmp, value);
  2895. zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
  2896. }
  2897. /* }}} */
  2898. ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, char *name, int name_length, const char *value TSRMLS_DC) /* {{{ */
  2899. {
  2900. zval *tmp;
  2901. ALLOC_ZVAL(tmp);
  2902. Z_UNSET_ISREF_P(tmp);
  2903. Z_SET_REFCOUNT_P(tmp, 0);
  2904. ZVAL_STRING(tmp, value, 1);
  2905. zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
  2906. }
  2907. /* }}} */
  2908. ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, char *name, int name_length, const char *value, int value_len TSRMLS_DC) /* {{{ */
  2909. {
  2910. zval *tmp;
  2911. ALLOC_ZVAL(tmp);
  2912. Z_UNSET_ISREF_P(tmp);
  2913. Z_SET_REFCOUNT_P(tmp, 0);
  2914. ZVAL_STRINGL(tmp, value, value_len, 1);
  2915. zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
  2916. }
  2917. /* }}} */
  2918. ZEND_API int zend_update_static_property(zend_class_entry *scope, char *name, int name_length, zval *value TSRMLS_DC) /* {{{ */
  2919. {
  2920. zval **property;
  2921. zend_class_entry *old_scope = EG(scope);
  2922. EG(scope) = scope;
  2923. property = zend_std_get_static_property(scope, name, name_length, 0 TSRMLS_CC);
  2924. EG(scope) = old_scope;
  2925. if (!property) {
  2926. return FAILURE;
  2927. } else {
  2928. if (*property != value) {
  2929. if (PZVAL_IS_REF(*property)) {
  2930. zval_dtor(*property);
  2931. Z_TYPE_PP(property) = Z_TYPE_P(value);
  2932. (*property)->value = value->value;
  2933. if (Z_REFCOUNT_P(value) > 0) {
  2934. zval_copy_ctor(*property);
  2935. }
  2936. } else {
  2937. zval *garbage = *property;
  2938. Z_ADDREF_P(value);
  2939. if (PZVAL_IS_REF(value)) {
  2940. SEPARATE_ZVAL(&value);
  2941. }
  2942. *property = value;
  2943. zval_ptr_dtor(&garbage);
  2944. }
  2945. }
  2946. return SUCCESS;
  2947. }
  2948. }
  2949. /* }}} */
  2950. ZEND_API int zend_update_static_property_null(zend_class_entry *scope, char *name, int name_length TSRMLS_DC) /* {{{ */
  2951. {
  2952. zval *tmp;
  2953. ALLOC_ZVAL(tmp);
  2954. Z_UNSET_ISREF_P(tmp);
  2955. Z_SET_REFCOUNT_P(tmp, 0);
  2956. ZVAL_NULL(tmp);
  2957. return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
  2958. }
  2959. /* }}} */
  2960. ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC) /* {{{ */
  2961. {
  2962. zval *tmp;
  2963. ALLOC_ZVAL(tmp);
  2964. Z_UNSET_ISREF_P(tmp);
  2965. Z_SET_REFCOUNT_P(tmp, 0);
  2966. ZVAL_BOOL(tmp, value);
  2967. return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
  2968. }
  2969. /* }}} */
  2970. ZEND_API int zend_update_static_property_long(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC) /* {{{ */
  2971. {
  2972. zval *tmp;
  2973. ALLOC_ZVAL(tmp);
  2974. Z_UNSET_ISREF_P(tmp);
  2975. Z_SET_REFCOUNT_P(tmp, 0);
  2976. ZVAL_LONG(tmp, value);
  2977. return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
  2978. }
  2979. /* }}} */
  2980. ZEND_API int zend_update_static_property_double(zend_class_entry *scope, char *name, int name_length, double value TSRMLS_DC) /* {{{ */
  2981. {
  2982. zval *tmp;
  2983. ALLOC_ZVAL(tmp);
  2984. Z_UNSET_ISREF_P(tmp);
  2985. Z_SET_REFCOUNT_P(tmp, 0);
  2986. ZVAL_DOUBLE(tmp, value);
  2987. return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
  2988. }
  2989. /* }}} */
  2990. ZEND_API int zend_update_static_property_string(zend_class_entry *scope, char *name, int name_length, const char *value TSRMLS_DC) /* {{{ */
  2991. {
  2992. zval *tmp;
  2993. ALLOC_ZVAL(tmp);
  2994. Z_UNSET_ISREF_P(tmp);
  2995. Z_SET_REFCOUNT_P(tmp, 0);
  2996. ZVAL_STRING(tmp, value, 1);
  2997. return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
  2998. }
  2999. /* }}} */
  3000. ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, char *name, int name_length, const char *value, int value_len TSRMLS_DC) /* {{{ */
  3001. {
  3002. zval *tmp;
  3003. ALLOC_ZVAL(tmp);
  3004. Z_UNSET_ISREF_P(tmp);
  3005. Z_SET_REFCOUNT_P(tmp, 0);
  3006. ZVAL_STRINGL(tmp, value, value_len, 1);
  3007. return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
  3008. }
  3009. /* }}} */
  3010. ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *name, int name_length, zend_bool silent TSRMLS_DC) /* {{{ */
  3011. {
  3012. zval *property, *value;
  3013. zend_class_entry *old_scope = EG(scope);
  3014. EG(scope) = scope;
  3015. if (!Z_OBJ_HT_P(object)->read_property) {
  3016. char *class_name;
  3017. zend_uint class_name_len;
  3018. zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC);
  3019. zend_error(E_CORE_ERROR, "Property %s of class %s cannot be read", name, class_name);
  3020. }
  3021. MAKE_STD_ZVAL(property);
  3022. ZVAL_STRINGL(property, name, name_length, 1);
  3023. value = Z_OBJ_HT_P(object)->read_property(object, property, silent?BP_VAR_IS:BP_VAR_R TSRMLS_CC);
  3024. zval_ptr_dtor(&property);
  3025. EG(scope) = old_scope;
  3026. return value;
  3027. }
  3028. /* }}} */
  3029. ZEND_API zval *zend_read_static_property(zend_class_entry *scope, char *name, int name_length, zend_bool silent TSRMLS_DC) /* {{{ */
  3030. {
  3031. zval **property;
  3032. zend_class_entry *old_scope = EG(scope);
  3033. EG(scope) = scope;
  3034. property = zend_std_get_static_property(scope, name, name_length, silent TSRMLS_CC);
  3035. EG(scope) = old_scope;
  3036. return property?*property:NULL;
  3037. }
  3038. /* }}} */
  3039. ZEND_API void zend_save_error_handling(zend_error_handling *current TSRMLS_DC) /* {{{ */
  3040. {
  3041. current->handling = EG(error_handling);
  3042. current->exception = EG(exception_class);
  3043. current->user_handler = EG(user_error_handler);
  3044. if (current->user_handler) {
  3045. Z_ADDREF_P(current->user_handler);
  3046. }
  3047. }
  3048. /* }}} */
  3049. ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current TSRMLS_DC) /* {{{ */
  3050. {
  3051. if (current) {
  3052. zend_save_error_handling(current TSRMLS_CC);
  3053. if (error_handling != EH_NORMAL && EG(user_error_handler)) {
  3054. zval_ptr_dtor(&EG(user_error_handler));
  3055. EG(user_error_handler) = NULL;
  3056. }
  3057. }
  3058. EG(error_handling) = error_handling;
  3059. EG(exception_class) = error_handling == EH_THROW ? exception_class : NULL;
  3060. }
  3061. /* }}} */
  3062. ZEND_API void zend_restore_error_handling(zend_error_handling *saved TSRMLS_DC) /* {{{ */
  3063. {
  3064. EG(error_handling) = saved->handling;
  3065. EG(exception_class) = saved->handling == EH_THROW ? saved->exception : NULL;
  3066. if (saved->user_handler && saved->user_handler != EG(user_error_handler)) {
  3067. if (EG(user_error_handler)) {
  3068. zval_ptr_dtor(&EG(user_error_handler));
  3069. }
  3070. EG(user_error_handler) = saved->user_handler;
  3071. } else if (saved->user_handler) {
  3072. zval_ptr_dtor(&saved->user_handler);
  3073. }
  3074. saved->user_handler = NULL;
  3075. }
  3076. /* }}} */
  3077. /*
  3078. * Local variables:
  3079. * tab-width: 4
  3080. * c-basic-offset: 4
  3081. * indent-tabs-mode: t
  3082. * End:
  3083. */