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

Generated by: LCOV version 1.10

Generated at Sun, 18 Sep 2016 08:20:19 +0000 (8 days ago)

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