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: 620 730 84.9 %
Date: 2014-04-18 Functions: 51 59 86.4 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Fri, 18 Apr 2014 07:01:38 +0000 (5 days ago)

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