xml.c 50 KB

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