Return to xml.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / xml |
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: */