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