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>