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