PageRenderTime 48ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/ext/xml/xml.c

http://github.com/infusion/PHP
C | 1829 lines | 1318 code | 304 blank | 207 comment | 265 complexity | 06c310f1d828c9d619f7cf31402af394 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2011 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Stig Sæther Bakken <ssb@php.net> |
  16. | Thies C. Arntzen <thies@thieso.net> |
  17. | Sterling Hughes <sterling@php.net> |
  18. +----------------------------------------------------------------------+
  19. */
  20. /* $Id: xml.c 306939 2011-01-01 02:19:59Z felipe $ */
  21. #define IS_EXT_MODULE
  22. #ifdef HAVE_CONFIG_H
  23. #include "config.h"
  24. #endif
  25. #include "php.h"
  26. #define PHP_XML_INTERNAL
  27. #include "zend_variables.h"
  28. #include "ext/standard/php_string.h"
  29. #include "ext/standard/info.h"
  30. #if HAVE_XML
  31. #include "php_xml.h"
  32. # include "ext/standard/head.h"
  33. #ifdef LIBXML_EXPAT_COMPAT
  34. #include "ext/libxml/php_libxml.h"
  35. #endif
  36. /* Short-term TODO list:
  37. * - Implement XML_ExternalEntityParserCreate()
  38. * - XML_SetCommentHandler
  39. * - XML_SetCdataSectionHandler
  40. * - XML_SetParamEntityParsing
  41. */
  42. /* Long-term TODO list:
  43. * - Fix the expat library so you can install your own memory manager
  44. * functions
  45. */
  46. /* Known bugs:
  47. * - Weird things happen with <![CDATA[]]> sections.
  48. */
  49. ZEND_DECLARE_MODULE_GLOBALS(xml)
  50. /* {{{ dynamically loadable module stuff */
  51. #ifdef COMPILE_DL_XML
  52. ZEND_GET_MODULE(xml)
  53. #endif /* COMPILE_DL_XML */
  54. /* }}} */
  55. /* {{{ function prototypes */
  56. PHP_MINIT_FUNCTION(xml);
  57. PHP_MINFO_FUNCTION(xml);
  58. static PHP_GINIT_FUNCTION(xml);
  59. static void xml_parser_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
  60. static void xml_set_handler(zval **, zval **);
  61. inline static unsigned short xml_encode_iso_8859_1(unsigned char);
  62. inline static char xml_decode_iso_8859_1(unsigned short);
  63. inline static unsigned short xml_encode_us_ascii(unsigned char);
  64. inline static char xml_decode_us_ascii(unsigned short);
  65. static zval *xml_call_handler(xml_parser *, zval *, zend_function *, int, zval **);
  66. static zval *_xml_xmlchar_zval(const XML_Char *, int, const XML_Char *);
  67. static int _xml_xmlcharlen(const XML_Char *);
  68. static void _xml_add_to_info(xml_parser *parser,char *name);
  69. inline static char *_xml_decode_tag(xml_parser *parser, const char *tag);
  70. void _xml_startElementHandler(void *, const XML_Char *, const XML_Char **);
  71. void _xml_endElementHandler(void *, const XML_Char *);
  72. void _xml_characterDataHandler(void *, const XML_Char *, int);
  73. void _xml_processingInstructionHandler(void *, const XML_Char *, const XML_Char *);
  74. void _xml_defaultHandler(void *, const XML_Char *, int);
  75. void _xml_unparsedEntityDeclHandler(void *, const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *);
  76. void _xml_notationDeclHandler(void *, const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *);
  77. int _xml_externalEntityRefHandler(XML_Parser, const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *);
  78. void _xml_startNamespaceDeclHandler(void *, const XML_Char *, const XML_Char *);
  79. void _xml_endNamespaceDeclHandler(void *, const XML_Char *);
  80. /* }}} */
  81. /* {{{ extension definition structures */
  82. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_parser_create, 0, 0, 0)
  83. ZEND_ARG_INFO(0, encoding)
  84. ZEND_END_ARG_INFO()
  85. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_parser_create_ns, 0, 0, 0)
  86. ZEND_ARG_INFO(0, encoding)
  87. ZEND_ARG_INFO(0, sep)
  88. ZEND_END_ARG_INFO()
  89. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_object, 0, 0, 2)
  90. ZEND_ARG_INFO(0, parser)
  91. ZEND_ARG_INFO(1, obj)
  92. ZEND_END_ARG_INFO()
  93. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_element_handler, 0, 0, 3)
  94. ZEND_ARG_INFO(0, parser)
  95. ZEND_ARG_INFO(0, shdl)
  96. ZEND_ARG_INFO(0, ehdl)
  97. ZEND_END_ARG_INFO()
  98. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_character_data_handler, 0, 0, 2)
  99. ZEND_ARG_INFO(0, parser)
  100. ZEND_ARG_INFO(0, hdl)
  101. ZEND_END_ARG_INFO()
  102. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_processing_instruction_handler, 0, 0, 2)
  103. ZEND_ARG_INFO(0, parser)
  104. ZEND_ARG_INFO(0, hdl)
  105. ZEND_END_ARG_INFO()
  106. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_default_handler, 0, 0, 2)
  107. ZEND_ARG_INFO(0, parser)
  108. ZEND_ARG_INFO(0, hdl)
  109. ZEND_END_ARG_INFO()
  110. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_unparsed_entity_decl_handler, 0, 0, 2)
  111. ZEND_ARG_INFO(0, parser)
  112. ZEND_ARG_INFO(0, hdl)
  113. ZEND_END_ARG_INFO()
  114. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_notation_decl_handler, 0, 0, 2)
  115. ZEND_ARG_INFO(0, parser)
  116. ZEND_ARG_INFO(0, hdl)
  117. ZEND_END_ARG_INFO()
  118. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_external_entity_ref_handler, 0, 0, 2)
  119. ZEND_ARG_INFO(0, parser)
  120. ZEND_ARG_INFO(0, hdl)
  121. ZEND_END_ARG_INFO()
  122. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_start_namespace_decl_handler, 0, 0, 2)
  123. ZEND_ARG_INFO(0, parser)
  124. ZEND_ARG_INFO(0, hdl)
  125. ZEND_END_ARG_INFO()
  126. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_end_namespace_decl_handler, 0, 0, 2)
  127. ZEND_ARG_INFO(0, parser)
  128. ZEND_ARG_INFO(0, hdl)
  129. ZEND_END_ARG_INFO()
  130. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_parse, 0, 0, 2)
  131. ZEND_ARG_INFO(0, parser)
  132. ZEND_ARG_INFO(0, data)
  133. ZEND_ARG_INFO(0, isfinal)
  134. ZEND_END_ARG_INFO()
  135. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_parse_into_struct, 0, 0, 3)
  136. ZEND_ARG_INFO(0, parser)
  137. ZEND_ARG_INFO(0, data)
  138. ZEND_ARG_INFO(1, values)
  139. ZEND_ARG_INFO(1, index)
  140. ZEND_END_ARG_INFO()
  141. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_get_error_code, 0, 0, 1)
  142. ZEND_ARG_INFO(0, parser)
  143. ZEND_END_ARG_INFO()
  144. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_error_string, 0, 0, 1)
  145. ZEND_ARG_INFO(0, code)
  146. ZEND_END_ARG_INFO()
  147. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_get_current_line_number, 0, 0, 1)
  148. ZEND_ARG_INFO(0, parser)
  149. ZEND_END_ARG_INFO()
  150. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_get_current_column_number, 0, 0, 1)
  151. ZEND_ARG_INFO(0, parser)
  152. ZEND_END_ARG_INFO()
  153. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_get_current_byte_index, 0, 0, 1)
  154. ZEND_ARG_INFO(0, parser)
  155. ZEND_END_ARG_INFO()
  156. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_parser_free, 0, 0, 1)
  157. ZEND_ARG_INFO(0, parser)
  158. ZEND_END_ARG_INFO()
  159. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_parser_set_option, 0, 0, 3)
  160. ZEND_ARG_INFO(0, parser)
  161. ZEND_ARG_INFO(0, option)
  162. ZEND_ARG_INFO(0, value)
  163. ZEND_END_ARG_INFO()
  164. ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_parser_get_option, 0, 0, 2)
  165. ZEND_ARG_INFO(0, parser)
  166. ZEND_ARG_INFO(0, option)
  167. ZEND_END_ARG_INFO()
  168. ZEND_BEGIN_ARG_INFO_EX(arginfo_utf8_encode, 0, 0, 1)
  169. ZEND_ARG_INFO(0, data)
  170. ZEND_END_ARG_INFO()
  171. ZEND_BEGIN_ARG_INFO_EX(arginfo_utf8_decode, 0, 0, 1)
  172. ZEND_ARG_INFO(0, data)
  173. ZEND_END_ARG_INFO()
  174. const zend_function_entry xml_functions[] = {
  175. PHP_FE(xml_parser_create, arginfo_xml_parser_create)
  176. PHP_FE(xml_parser_create_ns, arginfo_xml_parser_create_ns)
  177. PHP_FE(xml_set_object, arginfo_xml_set_object)
  178. PHP_FE(xml_set_element_handler, arginfo_xml_set_element_handler)
  179. PHP_FE(xml_set_character_data_handler, arginfo_xml_set_character_data_handler)
  180. PHP_FE(xml_set_processing_instruction_handler, arginfo_xml_set_processing_instruction_handler)
  181. PHP_FE(xml_set_default_handler, arginfo_xml_set_default_handler)
  182. PHP_FE(xml_set_unparsed_entity_decl_handler,arginfo_xml_set_unparsed_entity_decl_handler)
  183. PHP_FE(xml_set_notation_decl_handler, arginfo_xml_set_notation_decl_handler)
  184. PHP_FE(xml_set_external_entity_ref_handler, arginfo_xml_set_external_entity_ref_handler)
  185. PHP_FE(xml_set_start_namespace_decl_handler,arginfo_xml_set_start_namespace_decl_handler)
  186. PHP_FE(xml_set_end_namespace_decl_handler, arginfo_xml_set_end_namespace_decl_handler)
  187. PHP_FE(xml_parse, arginfo_xml_parse)
  188. PHP_FE(xml_parse_into_struct, arginfo_xml_parse_into_struct)
  189. PHP_FE(xml_get_error_code, arginfo_xml_get_error_code)
  190. PHP_FE(xml_error_string, arginfo_xml_error_string)
  191. PHP_FE(xml_get_current_line_number, arginfo_xml_get_current_line_number)
  192. PHP_FE(xml_get_current_column_number, arginfo_xml_get_current_column_number)
  193. PHP_FE(xml_get_current_byte_index, arginfo_xml_get_current_byte_index)
  194. PHP_FE(xml_parser_free, arginfo_xml_parser_free)
  195. PHP_FE(xml_parser_set_option, arginfo_xml_parser_set_option)
  196. PHP_FE(xml_parser_get_option, arginfo_xml_parser_get_option)
  197. PHP_FE(utf8_encode, arginfo_utf8_encode)
  198. PHP_FE(utf8_decode, arginfo_utf8_decode)
  199. {NULL, NULL, NULL}
  200. };
  201. #ifdef LIBXML_EXPAT_COMPAT
  202. static const zend_module_dep xml_deps[] = {
  203. ZEND_MOD_REQUIRED("libxml")
  204. {NULL, NULL, NULL}
  205. };
  206. #endif
  207. zend_module_entry xml_module_entry = {
  208. #ifdef LIBXML_EXPAT_COMPAT
  209. STANDARD_MODULE_HEADER_EX, NULL,
  210. xml_deps,
  211. #else
  212. STANDARD_MODULE_HEADER,
  213. #endif
  214. "xml", /* extension name */
  215. xml_functions, /* extension function list */
  216. PHP_MINIT(xml), /* extension-wide startup function */
  217. NULL, /* extension-wide shutdown function */
  218. NULL, /* per-request startup function */
  219. NULL, /* per-request shutdown function */
  220. PHP_MINFO(xml), /* information function */
  221. NO_VERSION_YET,
  222. PHP_MODULE_GLOBALS(xml), /* globals descriptor */
  223. PHP_GINIT(xml), /* globals ctor */
  224. NULL, /* globals dtor */
  225. NULL, /* post deactivate */
  226. STANDARD_MODULE_PROPERTIES_EX
  227. };
  228. /* All the encoding functions are set to NULL right now, since all
  229. * the encoding is currently done internally by expat/xmltok.
  230. */
  231. xml_encoding xml_encodings[] = {
  232. { "ISO-8859-1", xml_decode_iso_8859_1, xml_encode_iso_8859_1 },
  233. { "US-ASCII", xml_decode_us_ascii, xml_encode_us_ascii },
  234. { "UTF-8", NULL, NULL },
  235. { NULL, NULL, NULL }
  236. };
  237. static XML_Memory_Handling_Suite php_xml_mem_hdlrs;
  238. /* True globals, no need for thread safety */
  239. static int le_xml_parser;
  240. /* }}} */
  241. /* {{{ startup, shutdown and info functions */
  242. static PHP_GINIT_FUNCTION(xml)
  243. {
  244. xml_globals->default_encoding = "UTF-8";
  245. }
  246. static void *php_xml_malloc_wrapper(size_t sz)
  247. {
  248. return emalloc(sz);
  249. }
  250. static void *php_xml_realloc_wrapper(void *ptr, size_t sz)
  251. {
  252. return erealloc(ptr, sz);
  253. }
  254. static void php_xml_free_wrapper(void *ptr)
  255. {
  256. if (ptr != NULL) {
  257. efree(ptr);
  258. }
  259. }
  260. PHP_MINIT_FUNCTION(xml)
  261. {
  262. le_xml_parser = zend_register_list_destructors_ex(xml_parser_dtor, NULL, "xml", module_number);
  263. REGISTER_LONG_CONSTANT("XML_ERROR_NONE", XML_ERROR_NONE, CONST_CS|CONST_PERSISTENT);
  264. REGISTER_LONG_CONSTANT("XML_ERROR_NO_MEMORY", XML_ERROR_NO_MEMORY, CONST_CS|CONST_PERSISTENT);
  265. REGISTER_LONG_CONSTANT("XML_ERROR_SYNTAX", XML_ERROR_SYNTAX, CONST_CS|CONST_PERSISTENT);
  266. REGISTER_LONG_CONSTANT("XML_ERROR_NO_ELEMENTS", XML_ERROR_NO_ELEMENTS, CONST_CS|CONST_PERSISTENT);
  267. REGISTER_LONG_CONSTANT("XML_ERROR_INVALID_TOKEN", XML_ERROR_INVALID_TOKEN, CONST_CS|CONST_PERSISTENT);
  268. REGISTER_LONG_CONSTANT("XML_ERROR_UNCLOSED_TOKEN", XML_ERROR_UNCLOSED_TOKEN, CONST_CS|CONST_PERSISTENT);
  269. REGISTER_LONG_CONSTANT("XML_ERROR_PARTIAL_CHAR", XML_ERROR_PARTIAL_CHAR, CONST_CS|CONST_PERSISTENT);
  270. REGISTER_LONG_CONSTANT("XML_ERROR_TAG_MISMATCH", XML_ERROR_TAG_MISMATCH, CONST_CS|CONST_PERSISTENT);
  271. REGISTER_LONG_CONSTANT("XML_ERROR_DUPLICATE_ATTRIBUTE", XML_ERROR_DUPLICATE_ATTRIBUTE, CONST_CS|CONST_PERSISTENT);
  272. REGISTER_LONG_CONSTANT("XML_ERROR_JUNK_AFTER_DOC_ELEMENT", XML_ERROR_JUNK_AFTER_DOC_ELEMENT, CONST_CS|CONST_PERSISTENT);
  273. REGISTER_LONG_CONSTANT("XML_ERROR_PARAM_ENTITY_REF", XML_ERROR_PARAM_ENTITY_REF, CONST_CS|CONST_PERSISTENT);
  274. REGISTER_LONG_CONSTANT("XML_ERROR_UNDEFINED_ENTITY", XML_ERROR_UNDEFINED_ENTITY, CONST_CS|CONST_PERSISTENT);
  275. REGISTER_LONG_CONSTANT("XML_ERROR_RECURSIVE_ENTITY_REF", XML_ERROR_RECURSIVE_ENTITY_REF, CONST_CS|CONST_PERSISTENT);
  276. REGISTER_LONG_CONSTANT("XML_ERROR_ASYNC_ENTITY", XML_ERROR_ASYNC_ENTITY, CONST_CS|CONST_PERSISTENT);
  277. REGISTER_LONG_CONSTANT("XML_ERROR_BAD_CHAR_REF", XML_ERROR_BAD_CHAR_REF, CONST_CS|CONST_PERSISTENT);
  278. REGISTER_LONG_CONSTANT("XML_ERROR_BINARY_ENTITY_REF", XML_ERROR_BINARY_ENTITY_REF, CONST_CS|CONST_PERSISTENT);
  279. REGISTER_LONG_CONSTANT("XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF", XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF, CONST_CS|CONST_PERSISTENT);
  280. REGISTER_LONG_CONSTANT("XML_ERROR_MISPLACED_XML_PI", XML_ERROR_MISPLACED_XML_PI, CONST_CS|CONST_PERSISTENT);
  281. REGISTER_LONG_CONSTANT("XML_ERROR_UNKNOWN_ENCODING", XML_ERROR_UNKNOWN_ENCODING, CONST_CS|CONST_PERSISTENT);
  282. REGISTER_LONG_CONSTANT("XML_ERROR_INCORRECT_ENCODING", XML_ERROR_INCORRECT_ENCODING, CONST_CS|CONST_PERSISTENT);
  283. REGISTER_LONG_CONSTANT("XML_ERROR_UNCLOSED_CDATA_SECTION", XML_ERROR_UNCLOSED_CDATA_SECTION, CONST_CS|CONST_PERSISTENT);
  284. REGISTER_LONG_CONSTANT("XML_ERROR_EXTERNAL_ENTITY_HANDLING", XML_ERROR_EXTERNAL_ENTITY_HANDLING, CONST_CS|CONST_PERSISTENT);
  285. REGISTER_LONG_CONSTANT("XML_OPTION_CASE_FOLDING", PHP_XML_OPTION_CASE_FOLDING, CONST_CS|CONST_PERSISTENT);
  286. REGISTER_LONG_CONSTANT("XML_OPTION_TARGET_ENCODING", PHP_XML_OPTION_TARGET_ENCODING, CONST_CS|CONST_PERSISTENT);
  287. REGISTER_LONG_CONSTANT("XML_OPTION_SKIP_TAGSTART", PHP_XML_OPTION_SKIP_TAGSTART, CONST_CS|CONST_PERSISTENT);
  288. REGISTER_LONG_CONSTANT("XML_OPTION_SKIP_WHITE", PHP_XML_OPTION_SKIP_WHITE, CONST_CS|CONST_PERSISTENT);
  289. /* this object should not be pre-initialised at compile time,
  290. as the order of members may vary */
  291. php_xml_mem_hdlrs.malloc_fcn = php_xml_malloc_wrapper;
  292. php_xml_mem_hdlrs.realloc_fcn = php_xml_realloc_wrapper;
  293. php_xml_mem_hdlrs.free_fcn = php_xml_free_wrapper;
  294. #ifdef LIBXML_EXPAT_COMPAT
  295. REGISTER_STRING_CONSTANT("XML_SAX_IMPL", "libxml", CONST_CS|CONST_PERSISTENT);
  296. #else
  297. REGISTER_STRING_CONSTANT("XML_SAX_IMPL", "expat", CONST_CS|CONST_PERSISTENT);
  298. #endif
  299. return SUCCESS;
  300. }
  301. PHP_MINFO_FUNCTION(xml)
  302. {
  303. php_info_print_table_start();
  304. php_info_print_table_row(2, "XML Support", "active");
  305. php_info_print_table_row(2, "XML Namespace Support", "active");
  306. #if defined(LIBXML_DOTTED_VERSION) && defined(LIBXML_EXPAT_COMPAT)
  307. php_info_print_table_row(2, "libxml2 Version", LIBXML_DOTTED_VERSION);
  308. #else
  309. php_info_print_table_row(2, "EXPAT Version", XML_ExpatVersion());
  310. #endif
  311. php_info_print_table_end();
  312. }
  313. /* }}} */
  314. /* {{{ extension-internal functions */
  315. static zval *_xml_resource_zval(long value)
  316. {
  317. zval *ret;
  318. TSRMLS_FETCH();
  319. MAKE_STD_ZVAL(ret);
  320. Z_TYPE_P(ret) = IS_RESOURCE;
  321. Z_LVAL_P(ret) = value;
  322. zend_list_addref(value);
  323. return ret;
  324. }
  325. static zval *_xml_string_zval(const char *str)
  326. {
  327. zval *ret;
  328. int len = strlen(str);
  329. MAKE_STD_ZVAL(ret);
  330. Z_TYPE_P(ret) = IS_STRING;
  331. Z_STRLEN_P(ret) = len;
  332. Z_STRVAL_P(ret) = estrndup(str, len);
  333. return ret;
  334. }
  335. static zval *_xml_xmlchar_zval(const XML_Char *s, int len, const XML_Char *encoding)
  336. {
  337. zval *ret;
  338. MAKE_STD_ZVAL(ret);
  339. if (s == NULL) {
  340. ZVAL_FALSE(ret);
  341. return ret;
  342. }
  343. if (len == 0) {
  344. len = _xml_xmlcharlen(s);
  345. }
  346. Z_TYPE_P(ret) = IS_STRING;
  347. Z_STRVAL_P(ret) = xml_utf8_decode(s, len, &Z_STRLEN_P(ret), encoding);
  348. return ret;
  349. }
  350. /* }}} */
  351. /* {{{ xml_parser_dtor() */
  352. static void xml_parser_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
  353. {
  354. xml_parser *parser = (xml_parser *)rsrc->ptr;
  355. if (parser->parser) {
  356. XML_ParserFree(parser->parser);
  357. }
  358. if (parser->ltags) {
  359. int inx;
  360. for (inx = 0; inx < parser->level; inx++)
  361. efree(parser->ltags[ inx ]);
  362. efree(parser->ltags);
  363. }
  364. if (parser->startElementHandler) {
  365. zval_ptr_dtor(&parser->startElementHandler);
  366. }
  367. if (parser->endElementHandler) {
  368. zval_ptr_dtor(&parser->endElementHandler);
  369. }
  370. if (parser->characterDataHandler) {
  371. zval_ptr_dtor(&parser->characterDataHandler);
  372. }
  373. if (parser->processingInstructionHandler) {
  374. zval_ptr_dtor(&parser->processingInstructionHandler);
  375. }
  376. if (parser->defaultHandler) {
  377. zval_ptr_dtor(&parser->defaultHandler);
  378. }
  379. if (parser->unparsedEntityDeclHandler) {
  380. zval_ptr_dtor(&parser->unparsedEntityDeclHandler);
  381. }
  382. if (parser->notationDeclHandler) {
  383. zval_ptr_dtor(&parser->notationDeclHandler);
  384. }
  385. if (parser->externalEntityRefHandler) {
  386. zval_ptr_dtor(&parser->externalEntityRefHandler);
  387. }
  388. if (parser->unknownEncodingHandler) {
  389. zval_ptr_dtor(&parser->unknownEncodingHandler);
  390. }
  391. if (parser->startNamespaceDeclHandler) {
  392. zval_ptr_dtor(&parser->startNamespaceDeclHandler);
  393. }
  394. if (parser->endNamespaceDeclHandler) {
  395. zval_ptr_dtor(&parser->endNamespaceDeclHandler);
  396. }
  397. if (parser->baseURI) {
  398. efree(parser->baseURI);
  399. }
  400. if (parser->object) {
  401. zval_ptr_dtor(&parser->object);
  402. }
  403. efree(parser);
  404. }
  405. /* }}} */
  406. /* {{{ xml_set_handler() */
  407. static void xml_set_handler(zval **handler, zval **data)
  408. {
  409. /* If we have already a handler, release it */
  410. if (*handler) {
  411. zval_ptr_dtor(handler);
  412. }
  413. /* IS_ARRAY might indicate that we're using array($obj, 'method') syntax */
  414. if (Z_TYPE_PP(data) != IS_ARRAY && Z_TYPE_PP(data) != IS_OBJECT) {
  415. convert_to_string_ex(data);
  416. if (Z_STRLEN_PP(data) == 0) {
  417. *handler = NULL;
  418. return;
  419. }
  420. }
  421. zval_add_ref(data);
  422. *handler = *data;
  423. }
  424. /* }}} */
  425. /* {{{ xml_call_handler() */
  426. static zval *xml_call_handler(xml_parser *parser, zval *handler, zend_function *function_ptr, int argc, zval **argv)
  427. {
  428. int i;
  429. TSRMLS_FETCH();
  430. if (parser && handler && !EG(exception)) {
  431. zval ***args;
  432. zval *retval;
  433. int result;
  434. zend_fcall_info fci;
  435. args = safe_emalloc(sizeof(zval **), argc, 0);
  436. for (i = 0; i < argc; i++) {
  437. args[i] = &argv[i];
  438. }
  439. fci.size = sizeof(fci);
  440. fci.function_table = EG(function_table);
  441. fci.function_name = handler;
  442. fci.symbol_table = NULL;
  443. fci.object_ptr = parser->object;
  444. fci.retval_ptr_ptr = &retval;
  445. fci.param_count = argc;
  446. fci.params = args;
  447. fci.no_separation = 0;
  448. /*fci.function_handler_cache = &function_ptr;*/
  449. result = zend_call_function(&fci, NULL TSRMLS_CC);
  450. if (result == FAILURE) {
  451. zval **method;
  452. zval **obj;
  453. if (Z_TYPE_P(handler) == IS_STRING) {
  454. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler %s()", Z_STRVAL_P(handler));
  455. } else if (zend_hash_index_find(Z_ARRVAL_P(handler), 0, (void **) &obj) == SUCCESS &&
  456. zend_hash_index_find(Z_ARRVAL_P(handler), 1, (void **) &method) == SUCCESS &&
  457. Z_TYPE_PP(obj) == IS_OBJECT &&
  458. Z_TYPE_PP(method) == IS_STRING) {
  459. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler %s::%s()", Z_OBJCE_PP(obj)->name, Z_STRVAL_PP(method));
  460. } else
  461. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler");
  462. }
  463. for (i = 0; i < argc; i++) {
  464. zval_ptr_dtor(args[i]);
  465. }
  466. efree(args);
  467. if (result == FAILURE) {
  468. return NULL;
  469. } else {
  470. return EG(exception) ? NULL : retval;
  471. }
  472. } else {
  473. for (i = 0; i < argc; i++) {
  474. zval_ptr_dtor(&argv[i]);
  475. }
  476. return NULL;
  477. }
  478. }
  479. /* }}} */
  480. /* {{{ xml_encode_iso_8859_1() */
  481. inline static unsigned short xml_encode_iso_8859_1(unsigned char c)
  482. {
  483. return (unsigned short)c;
  484. }
  485. /* }}} */
  486. /* {{{ xml_decode_iso_8859_1() */
  487. inline static char xml_decode_iso_8859_1(unsigned short c)
  488. {
  489. return (char)(c > 0xff ? '?' : c);
  490. }
  491. /* }}} */
  492. /* {{{ xml_encode_us_ascii() */
  493. inline static unsigned short xml_encode_us_ascii(unsigned char c)
  494. {
  495. return (unsigned short)c;
  496. }
  497. /* }}} */
  498. /* {{{ xml_decode_us_ascii() */
  499. inline static char xml_decode_us_ascii(unsigned short c)
  500. {
  501. return (char)(c > 0x7f ? '?' : c);
  502. }
  503. /* }}} */
  504. /* {{{ xml_get_encoding() */
  505. static xml_encoding *xml_get_encoding(const XML_Char *name)
  506. {
  507. xml_encoding *enc = &xml_encodings[0];
  508. while (enc && enc->name) {
  509. if (strcasecmp(name, enc->name) == 0) {
  510. return enc;
  511. }
  512. enc++;
  513. }
  514. return NULL;
  515. }
  516. /* }}} */
  517. /* {{{ xml_utf8_encode */
  518. PHPAPI char *xml_utf8_encode(const char *s, int len, int *newlen, const XML_Char *encoding)
  519. {
  520. int pos = len;
  521. char *newbuf;
  522. unsigned int c;
  523. unsigned short (*encoder)(unsigned char) = NULL;
  524. xml_encoding *enc = xml_get_encoding(encoding);
  525. *newlen = 0;
  526. if (enc) {
  527. encoder = enc->encoding_function;
  528. } else {
  529. /* If the target encoding was unknown, fail */
  530. return NULL;
  531. }
  532. if (encoder == NULL) {
  533. /* If no encoder function was specified, return the data as-is.
  534. */
  535. newbuf = emalloc(len + 1);
  536. memcpy(newbuf, s, len);
  537. *newlen = len;
  538. newbuf[*newlen] = '\0';
  539. return newbuf;
  540. }
  541. /* This is the theoretical max (will never get beyond len * 2 as long
  542. * as we are converting from single-byte characters, though) */
  543. newbuf = safe_emalloc(len, 4, 1);
  544. while (pos > 0) {
  545. c = encoder ? encoder((unsigned char)(*s)) : (unsigned short)(*s);
  546. if (c < 0x80) {
  547. newbuf[(*newlen)++] = (char) c;
  548. } else if (c < 0x800) {
  549. newbuf[(*newlen)++] = (0xc0 | (c >> 6));
  550. newbuf[(*newlen)++] = (0x80 | (c & 0x3f));
  551. } else if (c < 0x10000) {
  552. newbuf[(*newlen)++] = (0xe0 | (c >> 12));
  553. newbuf[(*newlen)++] = (0xc0 | ((c >> 6) & 0x3f));
  554. newbuf[(*newlen)++] = (0x80 | (c & 0x3f));
  555. } else if (c < 0x200000) {
  556. newbuf[(*newlen)++] = (0xf0 | (c >> 18));
  557. newbuf[(*newlen)++] = (0xe0 | ((c >> 12) & 0x3f));
  558. newbuf[(*newlen)++] = (0xc0 | ((c >> 6) & 0x3f));
  559. newbuf[(*newlen)++] = (0x80 | (c & 0x3f));
  560. }
  561. pos--;
  562. s++;
  563. }
  564. newbuf[*newlen] = 0;
  565. newbuf = erealloc(newbuf, (*newlen)+1);
  566. return newbuf;
  567. }
  568. /* }}} */
  569. /* copied from trunk's implementation of get_next_char in ext/standard/html.c */
  570. #define MB_FAILURE(pos, advance) do { \
  571. *cursor = pos + (advance); \
  572. *status = FAILURE; \
  573. return 0; \
  574. } while (0)
  575. #define CHECK_LEN(pos, chars_need) ((str_len - (pos)) >= (chars_need))
  576. #define utf8_lead(c) ((c) < 0x80 || ((c) >= 0xC2 && (c) <= 0xF4))
  577. #define utf8_trail(c) ((c) >= 0x80 && (c) <= 0xBF)
  578. /* {{{ php_next_utf8_char
  579. */
  580. static inline unsigned int php_next_utf8_char(
  581. const unsigned char *str,
  582. size_t str_len,
  583. size_t *cursor,
  584. int *status)
  585. {
  586. size_t pos = *cursor;
  587. unsigned int this_char = 0;
  588. unsigned char c;
  589. *status = SUCCESS;
  590. if (!CHECK_LEN(pos, 1))
  591. MB_FAILURE(pos, 1);
  592. /* We'll follow strategy 2. from section 3.6.1 of UTR #36:
  593. * "In a reported illegal byte sequence, do not include any
  594. * non-initial byte that encodes a valid character or is a leading
  595. * byte for a valid sequence.» */
  596. c = str[pos];
  597. if (c < 0x80) {
  598. this_char = c;
  599. pos++;
  600. } else if (c < 0xc2) {
  601. MB_FAILURE(pos, 1);
  602. } else if (c < 0xe0) {
  603. if (!CHECK_LEN(pos, 2))
  604. MB_FAILURE(pos, 1);
  605. if (!utf8_trail(str[pos + 1])) {
  606. MB_FAILURE(pos, utf8_lead(str[pos + 1]) ? 1 : 2);
  607. }
  608. this_char = ((c & 0x1f) << 6) | (str[pos + 1] & 0x3f);
  609. if (this_char < 0x80) { /* non-shortest form */
  610. MB_FAILURE(pos, 2);
  611. }
  612. pos += 2;
  613. } else if (c < 0xf0) {
  614. size_t avail = str_len - pos;
  615. if (avail < 3 ||
  616. !utf8_trail(str[pos + 1]) || !utf8_trail(str[pos + 2])) {
  617. if (avail < 2 || utf8_lead(str[pos + 1]))
  618. MB_FAILURE(pos, 1);
  619. else if (avail < 3 || utf8_lead(str[pos + 2]))
  620. MB_FAILURE(pos, 2);
  621. else
  622. MB_FAILURE(pos, 3);
  623. }
  624. this_char = ((c & 0x0f) << 12) | ((str[pos + 1] & 0x3f) << 6) | (str[pos + 2] & 0x3f);
  625. if (this_char < 0x800) { /* non-shortest form */
  626. MB_FAILURE(pos, 3);
  627. } else if (this_char >= 0xd800 && this_char <= 0xdfff) { /* surrogate */
  628. MB_FAILURE(pos, 3);
  629. }
  630. pos += 3;
  631. } else if (c < 0xf5) {
  632. size_t avail = str_len - pos;
  633. if (avail < 4 ||
  634. !utf8_trail(str[pos + 1]) || !utf8_trail(str[pos + 2]) ||
  635. !utf8_trail(str[pos + 3])) {
  636. if (avail < 2 || utf8_lead(str[pos + 1]))
  637. MB_FAILURE(pos, 1);
  638. else if (avail < 3 || utf8_lead(str[pos + 2]))
  639. MB_FAILURE(pos, 2);
  640. else if (avail < 4 || utf8_lead(str[pos + 3]))
  641. MB_FAILURE(pos, 3);
  642. else
  643. MB_FAILURE(pos, 4);
  644. }
  645. this_char = ((c & 0x07) << 18) | ((str[pos + 1] & 0x3f) << 12) | ((str[pos + 2] & 0x3f) << 6) | (str[pos + 3] & 0x3f);
  646. if (this_char < 0x10000 || this_char > 0x10FFFF) { /* non-shortest form or outside range */
  647. MB_FAILURE(pos, 4);
  648. }
  649. pos += 4;
  650. } else {
  651. MB_FAILURE(pos, 1);
  652. }
  653. *cursor = pos;
  654. return this_char;
  655. }
  656. /* }}} */
  657. /* {{{ xml_utf8_decode */
  658. PHPAPI char *xml_utf8_decode(const XML_Char *s, int len, int *newlen, const XML_Char *encoding)
  659. {
  660. size_t pos = 0;
  661. char *newbuf = emalloc(len + 1);
  662. unsigned int c;
  663. char (*decoder)(unsigned short) = NULL;
  664. xml_encoding *enc = xml_get_encoding(encoding);
  665. *newlen = 0;
  666. if (enc) {
  667. decoder = enc->decoding_function;
  668. }
  669. if (decoder == NULL) {
  670. /* If the target encoding was unknown, or no decoder function
  671. * was specified, return the UTF-8-encoded data as-is.
  672. */
  673. memcpy(newbuf, s, len);
  674. *newlen = len;
  675. newbuf[*newlen] = '\0';
  676. return newbuf;
  677. }
  678. while (pos < (size_t)len) {
  679. int status = FAILURE;
  680. c = php_next_utf8_char((const unsigned char*)s, (size_t) len, &pos, &status);
  681. if (status == FAILURE || c > 0xFFU) {
  682. c = '?';
  683. }
  684. newbuf[*newlen] = decoder ? decoder(c) : c;
  685. ++*newlen;
  686. }
  687. if (*newlen < len) {
  688. newbuf = erealloc(newbuf, *newlen + 1);
  689. }
  690. newbuf[*newlen] = '\0';
  691. return newbuf;
  692. }
  693. /* }}} */
  694. /* {{{ _xml_xmlcharlen() */
  695. static int _xml_xmlcharlen(const XML_Char *s)
  696. {
  697. int len = 0;
  698. while (*s) {
  699. len++;
  700. s++;
  701. }
  702. return len;
  703. }
  704. /* }}} */
  705. /* {{{ _xml_zval_strdup() */
  706. PHPAPI char *_xml_zval_strdup(zval *val)
  707. {
  708. if (Z_TYPE_P(val) == IS_STRING) {
  709. char *buf = emalloc(Z_STRLEN_P(val) + 1);
  710. memcpy(buf, Z_STRVAL_P(val), Z_STRLEN_P(val));
  711. buf[Z_STRLEN_P(val)] = '\0';
  712. return buf;
  713. }
  714. return NULL;
  715. }
  716. /* }}} */
  717. /* {{{ _xml_add_to_info */
  718. static void _xml_add_to_info(xml_parser *parser,char *name)
  719. {
  720. zval **element, *values;
  721. if (! parser->info) {
  722. return;
  723. }
  724. if (zend_hash_find(Z_ARRVAL_P(parser->info),name,strlen(name) + 1,(void **) &element) == FAILURE) {
  725. MAKE_STD_ZVAL(values);
  726. array_init(values);
  727. zend_hash_update(Z_ARRVAL_P(parser->info), name, strlen(name)+1, (void *) &values, sizeof(zval*), (void **) &element);
  728. }
  729. add_next_index_long(*element,parser->curtag);
  730. parser->curtag++;
  731. }
  732. /* }}} */
  733. /* {{{ _xml_decode_tag() */
  734. static char *_xml_decode_tag(xml_parser *parser, const char *tag)
  735. {
  736. char *newstr;
  737. int out_len;
  738. newstr = xml_utf8_decode(tag, strlen(tag), &out_len, parser->target_encoding);
  739. if (parser->case_folding) {
  740. php_strtoupper(newstr, out_len);
  741. }
  742. return newstr;
  743. }
  744. /* }}} */
  745. /* {{{ _xml_startElementHandler() */
  746. void _xml_startElementHandler(void *userData, const XML_Char *name, const XML_Char **attributes)
  747. {
  748. xml_parser *parser = (xml_parser *)userData;
  749. const char **attrs = (const char **) attributes;
  750. char *tag_name;
  751. char *att, *val;
  752. int val_len;
  753. zval *retval, *args[3];
  754. if (parser) {
  755. parser->level++;
  756. tag_name = _xml_decode_tag(parser, name);
  757. if (parser->startElementHandler) {
  758. args[0] = _xml_resource_zval(parser->index);
  759. args[1] = _xml_string_zval(((char *) tag_name) + parser->toffset);
  760. MAKE_STD_ZVAL(args[2]);
  761. array_init(args[2]);
  762. while (attributes && *attributes) {
  763. att = _xml_decode_tag(parser, attributes[0]);
  764. val = xml_utf8_decode(attributes[1], strlen(attributes[1]), &val_len, parser->target_encoding);
  765. add_assoc_stringl(args[2], att, val, val_len, 0);
  766. attributes += 2;
  767. efree(att);
  768. }
  769. if ((retval = xml_call_handler(parser, parser->startElementHandler, parser->startElementPtr, 3, args))) {
  770. zval_ptr_dtor(&retval);
  771. }
  772. }
  773. if (parser->data) {
  774. zval *tag, *atr;
  775. int atcnt = 0;
  776. MAKE_STD_ZVAL(tag);
  777. MAKE_STD_ZVAL(atr);
  778. array_init(tag);
  779. array_init(atr);
  780. _xml_add_to_info(parser,((char *) tag_name) + parser->toffset);
  781. add_assoc_string(tag,"tag",((char *) tag_name) + parser->toffset,1); /* cast to avoid gcc-warning */
  782. add_assoc_string(tag,"type","open",1);
  783. add_assoc_long(tag,"level",parser->level);
  784. parser->ltags[parser->level-1] = estrdup(tag_name);
  785. parser->lastwasopen = 1;
  786. attributes = (const XML_Char **) attrs;
  787. while (attributes && *attributes) {
  788. att = _xml_decode_tag(parser, attributes[0]);
  789. val = xml_utf8_decode(attributes[1], strlen(attributes[1]), &val_len, parser->target_encoding);
  790. add_assoc_stringl(atr,att,val,val_len,0);
  791. atcnt++;
  792. attributes += 2;
  793. efree(att);
  794. }
  795. if (atcnt) {
  796. zend_hash_add(Z_ARRVAL_P(tag),"attributes",sizeof("attributes"),&atr,sizeof(zval*),NULL);
  797. } else {
  798. zval_ptr_dtor(&atr);
  799. }
  800. zend_hash_next_index_insert(Z_ARRVAL_P(parser->data),&tag,sizeof(zval*),(void *) &parser->ctag);
  801. }
  802. efree(tag_name);
  803. }
  804. }
  805. /* }}} */
  806. /* {{{ _xml_endElementHandler() */
  807. void _xml_endElementHandler(void *userData, const XML_Char *name)
  808. {
  809. xml_parser *parser = (xml_parser *)userData;
  810. char *tag_name;
  811. if (parser) {
  812. zval *retval, *args[2];
  813. tag_name = _xml_decode_tag(parser, name);
  814. if (parser->endElementHandler) {
  815. args[0] = _xml_resource_zval(parser->index);
  816. args[1] = _xml_string_zval(((char *) tag_name) + parser->toffset);
  817. if ((retval = xml_call_handler(parser, parser->endElementHandler, parser->endElementPtr, 2, args))) {
  818. zval_ptr_dtor(&retval);
  819. }
  820. }
  821. if (parser->data) {
  822. zval *tag;
  823. if (parser->lastwasopen) {
  824. add_assoc_string(*(parser->ctag),"type","complete",1);
  825. } else {
  826. MAKE_STD_ZVAL(tag);
  827. array_init(tag);
  828. _xml_add_to_info(parser,((char *) tag_name) + parser->toffset);
  829. add_assoc_string(tag,"tag",((char *) tag_name) + parser->toffset,1); /* cast to avoid gcc-warning */
  830. add_assoc_string(tag,"type","close",1);
  831. add_assoc_long(tag,"level",parser->level);
  832. zend_hash_next_index_insert(Z_ARRVAL_P(parser->data),&tag,sizeof(zval*),NULL);
  833. }
  834. parser->lastwasopen = 0;
  835. }
  836. efree(tag_name);
  837. if (parser->ltags) {
  838. efree(parser->ltags[parser->level-1]);
  839. }
  840. parser->level--;
  841. }
  842. }
  843. /* }}} */
  844. /* {{{ _xml_characterDataHandler() */
  845. void _xml_characterDataHandler(void *userData, const XML_Char *s, int len)
  846. {
  847. xml_parser *parser = (xml_parser *)userData;
  848. if (parser) {
  849. zval *retval, *args[2];
  850. if (parser->characterDataHandler) {
  851. args[0] = _xml_resource_zval(parser->index);
  852. args[1] = _xml_xmlchar_zval(s, len, parser->target_encoding);
  853. if ((retval = xml_call_handler(parser, parser->characterDataHandler, parser->characterDataPtr, 2, args))) {
  854. zval_ptr_dtor(&retval);
  855. }
  856. }
  857. if (parser->data) {
  858. int i;
  859. int doprint = 0;
  860. char *decoded_value;
  861. int decoded_len;
  862. decoded_value = xml_utf8_decode(s,len,&decoded_len,parser->target_encoding);
  863. for (i = 0; i < decoded_len; i++) {
  864. switch (decoded_value[i]) {
  865. case ' ':
  866. case '\t':
  867. case '\n':
  868. continue;
  869. default:
  870. doprint = 1;
  871. break;
  872. }
  873. if (doprint) {
  874. break;
  875. }
  876. }
  877. if (doprint || (! parser->skipwhite)) {
  878. if (parser->lastwasopen) {
  879. zval **myval;
  880. /* check if the current tag already has a value - if yes append to that! */
  881. if (zend_hash_find(Z_ARRVAL_PP(parser->ctag),"value",sizeof("value"),(void **) &myval) == SUCCESS) {
  882. int newlen = Z_STRLEN_PP(myval) + decoded_len;
  883. Z_STRVAL_PP(myval) = erealloc(Z_STRVAL_PP(myval),newlen+1);
  884. strcpy(Z_STRVAL_PP(myval) + Z_STRLEN_PP(myval),decoded_value);
  885. Z_STRLEN_PP(myval) += decoded_len;
  886. efree(decoded_value);
  887. } else {
  888. add_assoc_string(*(parser->ctag),"value",decoded_value,0);
  889. }
  890. } else {
  891. zval *tag;
  892. zval **curtag, **mytype, **myval;
  893. HashPosition hpos=NULL;
  894. zend_hash_internal_pointer_end_ex(Z_ARRVAL_P(parser->data), &hpos);
  895. if (hpos && (zend_hash_get_current_data_ex(Z_ARRVAL_P(parser->data), (void **) &curtag, &hpos) == SUCCESS)) {
  896. if (zend_hash_find(Z_ARRVAL_PP(curtag),"type",sizeof("type"),(void **) &mytype) == SUCCESS) {
  897. if (!strcmp(Z_STRVAL_PP(mytype), "cdata")) {
  898. if (zend_hash_find(Z_ARRVAL_PP(curtag),"value",sizeof("value"),(void **) &myval) == SUCCESS) {
  899. int newlen = Z_STRLEN_PP(myval) + decoded_len;
  900. Z_STRVAL_PP(myval) = erealloc(Z_STRVAL_PP(myval),newlen+1);
  901. strcpy(Z_STRVAL_PP(myval) + Z_STRLEN_PP(myval),decoded_value);
  902. Z_STRLEN_PP(myval) += decoded_len;
  903. efree(decoded_value);
  904. return;
  905. }
  906. }
  907. }
  908. }
  909. MAKE_STD_ZVAL(tag);
  910. array_init(tag);
  911. _xml_add_to_info(parser,parser->ltags[parser->level-1] + parser->toffset);
  912. add_assoc_string(tag,"tag",parser->ltags[parser->level-1] + parser->toffset,1);
  913. add_assoc_string(tag,"value",decoded_value,0);
  914. add_assoc_string(tag,"type","cdata",1);
  915. add_assoc_long(tag,"level",parser->level);
  916. zend_hash_next_index_insert(Z_ARRVAL_P(parser->data),&tag,sizeof(zval*),NULL);
  917. }
  918. } else {
  919. efree(decoded_value);
  920. }
  921. }
  922. }
  923. }
  924. /* }}} */
  925. /* {{{ _xml_processingInstructionHandler() */
  926. void _xml_processingInstructionHandler(void *userData, const XML_Char *target, const XML_Char *data)
  927. {
  928. xml_parser *parser = (xml_parser *)userData;
  929. if (parser && parser->processingInstructionHandler) {
  930. zval *retval, *args[3];
  931. args[0] = _xml_resource_zval(parser->index);
  932. args[1] = _xml_xmlchar_zval(target, 0, parser->target_encoding);
  933. args[2] = _xml_xmlchar_zval(data, 0, parser->target_encoding);
  934. if ((retval = xml_call_handler(parser, parser->processingInstructionHandler, parser->processingInstructionPtr, 3, args))) {
  935. zval_ptr_dtor(&retval);
  936. }
  937. }
  938. }
  939. /* }}} */
  940. /* {{{ _xml_defaultHandler() */
  941. void _xml_defaultHandler(void *userData, const XML_Char *s, int len)
  942. {
  943. xml_parser *parser = (xml_parser *)userData;
  944. if (parser && parser->defaultHandler) {
  945. zval *retval, *args[2];
  946. args[0] = _xml_resource_zval(parser->index);
  947. args[1] = _xml_xmlchar_zval(s, len, parser->target_encoding);
  948. if ((retval = xml_call_handler(parser, parser->defaultHandler, parser->defaultPtr, 2, args))) {
  949. zval_ptr_dtor(&retval);
  950. }
  951. }
  952. }
  953. /* }}} */
  954. /* {{{ _xml_unparsedEntityDeclHandler() */
  955. void _xml_unparsedEntityDeclHandler(void *userData,
  956. const XML_Char *entityName,
  957. const XML_Char *base,
  958. const XML_Char *systemId,
  959. const XML_Char *publicId,
  960. const XML_Char *notationName)
  961. {
  962. xml_parser *parser = (xml_parser *)userData;
  963. if (parser && parser->unparsedEntityDeclHandler) {
  964. zval *retval, *args[6];
  965. args[0] = _xml_resource_zval(parser->index);
  966. args[1] = _xml_xmlchar_zval(entityName, 0, parser->target_encoding);
  967. args[2] = _xml_xmlchar_zval(base, 0, parser->target_encoding);
  968. args[3] = _xml_xmlchar_zval(systemId, 0, parser->target_encoding);
  969. args[4] = _xml_xmlchar_zval(publicId, 0, parser->target_encoding);
  970. args[5] = _xml_xmlchar_zval(notationName, 0, parser->target_encoding);
  971. if ((retval = xml_call_handler(parser, parser->unparsedEntityDeclHandler, parser->unparsedEntityDeclPtr, 6, args))) {
  972. zval_ptr_dtor(&retval);
  973. }
  974. }
  975. }
  976. /* }}} */
  977. /* {{{ _xml_notationDeclHandler() */
  978. void _xml_notationDeclHandler(void *userData,
  979. const XML_Char *notationName,
  980. const XML_Char *base,
  981. const XML_Char *systemId,
  982. const XML_Char *publicId)
  983. {
  984. xml_parser *parser = (xml_parser *)userData;
  985. if (parser && parser->notationDeclHandler) {
  986. zval *retval, *args[5];
  987. args[0] = _xml_resource_zval(parser->index);
  988. args[1] = _xml_xmlchar_zval(notationName, 0, parser->target_encoding);
  989. args[2] = _xml_xmlchar_zval(base, 0, parser->target_encoding);
  990. args[3] = _xml_xmlchar_zval(systemId, 0, parser->target_encoding);
  991. args[4] = _xml_xmlchar_zval(publicId, 0, parser->target_encoding);
  992. if ((retval = xml_call_handler(parser, parser->notationDeclHandler, parser->notationDeclPtr, 5, args))) {
  993. zval_ptr_dtor(&retval);
  994. }
  995. }
  996. }
  997. /* }}} */
  998. /* {{{ _xml_externalEntityRefHandler() */
  999. int _xml_externalEntityRefHandler(XML_Parser parserPtr,
  1000. const XML_Char *openEntityNames,
  1001. const XML_Char *base,
  1002. const XML_Char *systemId,
  1003. const XML_Char *publicId)
  1004. {
  1005. xml_parser *parser = XML_GetUserData(parserPtr);
  1006. int ret = 0; /* abort if no handler is set (should be configurable?) */
  1007. if (parser && parser->externalEntityRefHandler) {
  1008. zval *retval, *args[5];
  1009. args[0] = _xml_resource_zval(parser->index);
  1010. args[1] = _xml_xmlchar_zval(openEntityNames, 0, parser->target_encoding);
  1011. args[2] = _xml_xmlchar_zval(base, 0, parser->target_encoding);
  1012. args[3] = _xml_xmlchar_zval(systemId, 0, parser->target_encoding);
  1013. args[4] = _xml_xmlchar_zval(publicId, 0, parser->target_encoding);
  1014. if ((retval = xml_call_handler(parser, parser->externalEntityRefHandler, parser->externalEntityRefPtr, 5, args))) {
  1015. convert_to_long(retval);
  1016. ret = Z_LVAL_P(retval);
  1017. efree(retval);
  1018. } else {
  1019. ret = 0;
  1020. }
  1021. }
  1022. return ret;
  1023. }
  1024. /* }}} */
  1025. /* {{{ _xml_startNamespaceDeclHandler() */
  1026. void _xml_startNamespaceDeclHandler(void *userData,const XML_Char *prefix, const XML_Char *uri)
  1027. {
  1028. xml_parser *parser = (xml_parser *)userData;
  1029. if (parser && parser->startNamespaceDeclHandler) {
  1030. zval *retval, *args[3];
  1031. args[0] = _xml_resource_zval(parser->index);
  1032. args[1] = _xml_xmlchar_zval(prefix, 0, parser->target_encoding);
  1033. args[2] = _xml_xmlchar_zval(uri, 0, parser->target_encoding);
  1034. if ((retval = xml_call_handler(parser, parser->startNamespaceDeclHandler, parser->startNamespaceDeclPtr, 3, args))) {
  1035. zval_ptr_dtor(&retval);
  1036. }
  1037. }
  1038. }
  1039. /* }}} */
  1040. /* {{{ _xml_endNamespaceDeclHandler() */
  1041. void _xml_endNamespaceDeclHandler(void *userData, const XML_Char *prefix)
  1042. {
  1043. xml_parser *parser = (xml_parser *)userData;
  1044. if (parser && parser->endNamespaceDeclHandler) {
  1045. zval *retval, *args[2];
  1046. args[0] = _xml_resource_zval(parser->index);
  1047. args[1] = _xml_xmlchar_zval(prefix, 0, parser->target_encoding);
  1048. if ((retval = xml_call_handler(parser, parser->endNamespaceDeclHandler, parser->endNamespaceDeclPtr, 2, args))) {
  1049. zval_ptr_dtor(&retval);
  1050. }
  1051. }
  1052. }
  1053. /* }}} */
  1054. /************************* EXTENSION FUNCTIONS *************************/
  1055. static void php_xml_parser_create_impl(INTERNAL_FUNCTION_PARAMETERS, int ns_support) /* {{{ */
  1056. {
  1057. xml_parser *parser;
  1058. int auto_detect = 0;
  1059. char *encoding_param = NULL;
  1060. int encoding_param_len = 0;
  1061. char *ns_param = NULL;
  1062. int ns_param_len = 0;
  1063. XML_Char *encoding;
  1064. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, (ns_support ? "|ss": "|s"), &encoding_param, &encoding_param_len, &ns_param, &ns_param_len) == FAILURE) {
  1065. RETURN_FALSE;
  1066. }
  1067. if (encoding_param != NULL) {
  1068. /* The supported encoding types are hardcoded here because
  1069. * we are limited to the encodings supported by expat/xmltok.
  1070. */
  1071. if (encoding_param_len == 0) {
  1072. encoding = XML(default_encoding);
  1073. auto_detect = 1;
  1074. } else if (strcasecmp(encoding_param, "ISO-8859-1") == 0) {
  1075. encoding = "ISO-8859-1";
  1076. } else if (strcasecmp(encoding_param, "UTF-8") == 0) {
  1077. encoding = "UTF-8";
  1078. } else if (strcasecmp(encoding_param, "US-ASCII") == 0) {
  1079. encoding = "US-ASCII";
  1080. } else {
  1081. php_error_docref(NULL TSRMLS_CC, E_WARNING, "unsupported source encoding \"%s\"", encoding_param);
  1082. RETURN_FALSE;
  1083. }
  1084. } else {
  1085. encoding = XML(default_encoding);
  1086. }
  1087. if (ns_support && ns_param == NULL){
  1088. ns_param = ":";
  1089. }
  1090. parser = ecalloc(1, sizeof(xml_parser));
  1091. parser->parser = XML_ParserCreate_MM((auto_detect ? NULL : encoding),
  1092. &php_xml_mem_hdlrs, ns_param);
  1093. parser->target_encoding = encoding;
  1094. parser->case_folding = 1;
  1095. parser->object = NULL;
  1096. parser->isparsing = 0;
  1097. XML_SetUserData(parser->parser, parser);
  1098. ZEND_REGISTER_RESOURCE(return_value, parser,le_xml_parser);
  1099. parser->index = Z_LVAL_P(return_value);
  1100. }
  1101. /* }}} */
  1102. /* {{{ proto resource xml_parser_create([string encoding])
  1103. Create an XML parser */
  1104. PHP_FUNCTION(xml_parser_create)
  1105. {
  1106. php_xml_parser_create_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  1107. }
  1108. /* }}} */
  1109. /* {{{ proto resource xml_parser_create_ns([string encoding [, string sep]])
  1110. Create an XML parser */
  1111. PHP_FUNCTION(xml_parser_create_ns)
  1112. {
  1113. php_xml_parser_create_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  1114. }
  1115. /* }}} */
  1116. /* {{{ proto int xml_set_object(resource parser, object &obj)
  1117. Set up object which should be used for callbacks */
  1118. PHP_FUNCTION(xml_set_object)
  1119. {
  1120. xml_parser *parser;
  1121. zval *pind, *mythis;
  1122. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ro", &pind, &mythis) == FAILURE) {
  1123. return;
  1124. }
  1125. ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
  1126. /* please leave this commented - or ask thies@thieso.net before doing it (again) */
  1127. if (parser->object) {
  1128. zval_ptr_dtor(&parser->object);
  1129. }
  1130. /* please leave this commented - or ask thies@thieso.net before doing it (again) */
  1131. /* #ifdef ZEND_ENGINE_2
  1132. zval_add_ref(&parser->object);
  1133. #endif */
  1134. ALLOC_ZVAL(parser->object);
  1135. MAKE_COPY_ZVAL(&mythis, parser->object);
  1136. RETVAL_TRUE;
  1137. }
  1138. /* }}} */
  1139. /* {{{ proto int xml_set_element_handler(resource parser, string shdl, string ehdl)
  1140. Set up start and end element handlers */
  1141. PHP_FUNCTION(xml_set_element_handler)
  1142. {
  1143. xml_parser *parser;
  1144. zval *pind, **shdl, **ehdl;
  1145. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZZ", &pind, &shdl, &ehdl) == FAILURE) {
  1146. return;
  1147. }
  1148. ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
  1149. xml_set_handler(&parser->startElementHandler, shdl);
  1150. xml_set_handler(&parser->endElementHandler, ehdl);
  1151. XML_SetElementHandler(parser->parser, _xml_startElementHandler, _xml_endElementHandler);
  1152. RETVAL_TRUE;
  1153. }
  1154. /* }}} */
  1155. /* {{{ proto int xml_set_character_data_handler(resource parser, string hdl)
  1156. Set up character data handler */
  1157. PHP_FUNCTION(xml_set_character_data_handler)
  1158. {
  1159. xml_parser *parser;
  1160. zval *pind, **hdl;
  1161. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pind, &hdl) == FAILURE) {
  1162. return;
  1163. }
  1164. ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
  1165. xml_set_handler(&parser->characterDataHandler, hdl);
  1166. XML_SetCharacterDataHandler(parser->parser, _xml_characterDataHandler);
  1167. RETVAL_TRUE;
  1168. }
  1169. /* }}} */
  1170. /* {{{ proto int xml_set_processing_instruction_handler(resource parser, string hdl)
  1171. Set up processing instruction (PI) handler */
  1172. PHP_FUNCTION(xml_set_processing_instruction_handler)
  1173. {
  1174. xml_parser *parser;
  1175. zval *pind, **hdl;
  1176. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pind, &hdl) == FAILURE) {
  1177. return;
  1178. }
  1179. ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
  1180. xml_set_handler(&parser->processingInstructionHandler, hdl);
  1181. XML_SetProcessingInstructionHandler(parser->parser, _xml_processingInstructionHandler);
  1182. RETVAL_TRUE;
  1183. }
  1184. /* }}} */
  1185. /* {{{ proto int xml_set_default_handler(resource parser, string hdl)
  1186. Set up default handler */
  1187. PHP_FUNCTION(xml_set_default_handler)
  1188. {
  1189. xml_parser *parser;
  1190. zval *pind, **hdl;
  1191. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pind, &hdl) == FAILURE) {
  1192. return;
  1193. }
  1194. ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
  1195. xml_set_handler(&parser->defaultHandler, hdl);
  1196. XML_SetDefaultHandler(parser->parser, _xml_defaultHandler);
  1197. RETVAL_TRUE;
  1198. }
  1199. /* }}} */
  1200. /* {{{ proto int xml_set_unparsed_entity_decl_handler(resource parser, string hdl)
  1201. Set up unparsed entity declaration handler */
  1202. PHP_FUNCTION(xml_set_unparsed_entity_decl_handler)
  1203. {
  1204. xml_parser *parser;
  1205. zval *pind, **hdl;
  1206. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pind, &hdl) == FAILURE) {
  1207. return;
  1208. }
  1209. ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
  1210. xml_set_handler(&parser->unparsedEntityDeclHandler, hdl);
  1211. XML_SetUnparsedEntityDeclHandler(parser->parser, _xml_unparsedEntityDeclHandler);
  1212. RETVAL_TRUE;
  1213. }
  1214. /* }}} */
  1215. /* {{{ proto int xml_set_notation_decl_handler(resource parser, string hdl)
  1216. Set up notation declaration handler */
  1217. PHP_FUNCTION(xml_set_notation_decl_handler)
  1218. {
  1219. xml_parser *parser;
  1220. zval *pind, **hdl;
  1221. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pind, &hdl) == FAILURE) {
  1222. return;
  1223. }
  1224. ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
  1225. xml_set_handler(&parser->notationDeclHandler, hdl);
  1226. XML_SetNotationDeclHandler(parser->parser, _xml_notationDeclHandler);
  1227. RETVAL_TRUE;
  1228. }
  1229. /* }}} */
  1230. /* {{{ proto int xml_set_external_entity_ref_handler(resource parser, string hdl)
  1231. Set up external entity reference handler */
  1232. PHP_FUNCTION(xml_set_external_entity_ref_handler)
  1233. {
  1234. xml_parser *parser;
  1235. zval *pind, **hdl;
  1236. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pind, &hdl) == FAILURE) {
  1237. return;
  1238. }
  1239. ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
  1240. xml_set_handler(&parser->externalEntityRefHandler, hdl);
  1241. XML_SetExternalEntityRefHandler(parser->parser, (void *) _xml_externalEntityRefHandler);
  1242. RETVAL_TRUE;
  1243. }
  1244. /* }}} */
  1245. /* {{{ proto int xml_set_start_namespace_decl_handler(resource parser, string hdl)
  1246. Set up character data handler */
  1247. PHP_FUNCTION(xml_set_start_namespace_decl_handler)
  1248. {
  1249. xml_parser *parser;
  1250. zval *pind, **hdl;
  1251. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pind, &hdl) == FAILURE) {
  1252. return;
  1253. }
  1254. ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
  1255. xml_set_handler(&parser->startNamespaceDeclHandler, hdl);
  1256. XML_SetStartNamespaceDeclHandler(parser->parser, _xml_startNamespaceDeclHandler);
  1257. RETVAL_TRUE;
  1258. }
  1259. /* }}} */
  1260. /* {{{ proto int xml_set_end_namespace_decl_handler(resource parser, string hdl)
  1261. Set up character data handler */
  1262. PHP_FUNCTION(xml_set_end_namespace_decl_handler)
  1263. {
  1264. xml_parser *parser;
  1265. zval *pind, **hdl;
  1266. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pind, &hdl) == FAILURE) {
  1267. return;
  1268. }
  1269. ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
  1270. xml_set_handler(&parser->endNamespaceDeclHandler, hdl);
  1271. XML_SetEndNamespaceDeclHandler(parser->parser, _xml_endNamespaceDeclHandler);
  1272. RETVAL_TRUE;
  1273. }
  1274. /* }}} */
  1275. /* {{{ proto int xml_parse(resource parser, string data [, int isFinal])
  1276. Start parsing an XML document */
  1277. PHP_FUNCTION(xml_parse)
  1278. {
  1279. xml_parser *parser;
  1280. zval *pind;
  1281. char *data;
  1282. int data_len, ret;
  1283. long isFinal = 0;
  1284. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &pind, &data, &data_len, &isFinal) == FAILURE) {
  1285. return;
  1286. }
  1287. ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
  1288. parser->isparsing = 1;
  1289. ret = XML_Parse(parser->parser, data, data_len, isFinal);
  1290. parser->isparsing = 0;
  1291. RETVAL_LONG(ret);
  1292. }
  1293. /* }}} */
  1294. /* {{{ proto int xml_parse_into_struct(resource parser, string data, array &values [, array &index ])
  1295. Parsing a XML document */
  1296. PHP_FUNCTION(xml_parse_into_struct)
  1297. {
  1298. xml_parser *parser;
  1299. zval *pind, **xdata, **info = NULL;
  1300. char *data;
  1301. int data_len, ret;
  1302. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsZ|Z", &pind, &data, &data_len, &xdata, &info) == FAILURE) {
  1303. return;
  1304. }
  1305. if (info) {
  1306. zval_dtor(*info);
  1307. array_init(*info);
  1308. }
  1309. ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
  1310. zval_dtor(*xdata);
  1311. array_init(*xdata);
  1312. parser->data = *xdata;
  1313. if (info) {
  1314. parser->info = *info;
  1315. }
  1316. parser->level = 0;
  1317. parser->ltags = safe_emalloc(XML_MAXLEVEL, sizeof(char *), 0);
  1318. XML_SetDefaultHandler(parser->parser, _xml_defaultHandler);
  1319. XML_SetElementHandler(parser->parser, _xml_startElementHandler, _xml_endElementHandler);
  1320. XML_SetCharacterDataHandler(parser->parser, _xml_characterDataHandler);
  1321. parser->isparsing = 1;
  1322. ret = XML_Parse(parser->parser, data, data_len, 1);
  1323. parser->isparsing = 0;
  1324. RETVAL_LONG(ret);
  1325. }
  1326. /* }}} */
  1327. /* {{{ proto int xml_get_error_code(resource parser)
  1328. Get XML parser error code */
  1329. PHP_FUNCTION(xml_get_error_code)
  1330. {
  1331. xml_parser *parser;
  1332. zval *pind;
  1333. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) {
  1334. return;
  1335. }
  1336. ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
  1337. RETVAL_LONG((long)XML_GetErrorCode(parser->parser));
  1338. }
  1339. /* }}} */
  1340. /* {{{ proto string xml_error_string(int code)
  1341. Get XML parser error string */
  1342. PHP_FUNCTION(xml_error_string)
  1343. {
  1344. long code;
  1345. char *str;
  1346. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code) == FAILURE) {
  1347. return;
  1348. }
  1349. str = (char *)XML_ErrorString((int)code);
  1350. if (str) {
  1351. RETVAL_STRING(str, 1);
  1352. }
  1353. }
  1354. /* }}} */
  1355. /* {{{ proto int xml_get_current_line_number(resource parser)
  1356. Get current line number for an XML parser */
  1357. PHP_FUNCTION(xml_get_current_line_number)
  1358. {
  1359. xml_parser *parser;
  1360. zval *pind;
  1361. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) {
  1362. return;
  1363. }
  1364. ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
  1365. RETVAL_LONG(XML_GetCurrentLineNumber(parser->parser));
  1366. }
  1367. /* }}} */
  1368. /* {{{ proto int xml_get_current_column_number(resource parser)
  1369. Get current column number for an XML parser */
  1370. PHP_FUNCTION(xml_get_current_column_number)
  1371. {
  1372. xml_parser *parser;
  1373. zval *pind;
  1374. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) {
  1375. return;
  1376. }
  1377. ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
  1378. RETVAL_LONG(XML_GetCurrentColumnNumber(parser->parser));
  1379. }
  1380. /* }}} */
  1381. /* {{{ proto int xml_get_current_byte_index(resource parser)
  1382. Get current byte index for an XML parser */
  1383. PHP_FUNCTION(xml_get_current_byte_index)
  1384. {
  1385. xml_parser *parser;
  1386. zval *pind;
  1387. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) {
  1388. return;
  1389. }
  1390. ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
  1391. RETVAL_LONG(XML_GetCurrentByteIndex(parser->parser));
  1392. }
  1393. /* }}} */
  1394. /* {{{ proto int xml_parser_free(resource parser)
  1395. Free an XML parser */
  1396. PHP_FUNCTION(xml_parser_free)
  1397. {
  1398. zval *pind;
  1399. xml_parser *parser;
  1400. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) {
  1401. return;
  1402. }
  1403. ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
  1404. if (parser->isparsing == 1) {
  1405. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parser cannot be freed while it is parsing.");
  1406. …

Large files files are truncated, but you can click here to view the full file