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