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