PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/xml - xml.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 550 629 87.4 %
Date: 2014-12-13 Functions: 48 56 85.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sat, 13 Dec 2014 06:16:24 +0000 (5 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.