Annotation of embedaddon/php/ext/xml/xml.c, revision 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>