Back to index

php5  5.3.10
xml.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Authors: Stig Sæther Bakken <ssb@php.net>                            |
00016    |          Thies C. Arntzen <thies@thieso.net>                         |
00017    |          Sterling Hughes <sterling@php.net>                          |
00018    +----------------------------------------------------------------------+
00019  */
00020 
00021 /* $Id: xml.c 321634 2012-01-01 13:15:04Z felipe $ */
00022 
00023 #define IS_EXT_MODULE
00024 
00025 #ifdef HAVE_CONFIG_H
00026 #include "config.h"
00027 #endif
00028 
00029 #include "php.h"
00030 
00031 #define PHP_XML_INTERNAL
00032 #include "zend_variables.h"
00033 #include "ext/standard/php_string.h"
00034 #include "ext/standard/info.h"
00035 
00036 #if HAVE_XML
00037 
00038 #include "php_xml.h"
00039 # include "ext/standard/head.h"
00040 #ifdef LIBXML_EXPAT_COMPAT
00041 #include "ext/libxml/php_libxml.h"
00042 #endif
00043 
00044 /* Short-term TODO list:
00045  * - Implement XML_ExternalEntityParserCreate()
00046  * - XML_SetCommentHandler
00047  * - XML_SetCdataSectionHandler
00048  * - XML_SetParamEntityParsing
00049  */
00050 
00051 /* Long-term TODO list:
00052  * - Fix the expat library so you can install your own memory manager
00053  *   functions
00054  */
00055 
00056 /* Known bugs:
00057  * - Weird things happen with <![CDATA[]]> sections.
00058  */
00059 
00060 ZEND_DECLARE_MODULE_GLOBALS(xml)
00061 
00062 /* {{{ dynamically loadable module stuff */
00063 #ifdef COMPILE_DL_XML
00064 ZEND_GET_MODULE(xml)
00065 #endif /* COMPILE_DL_XML */
00066 /* }}} */
00067 
00068 /* {{{ function prototypes */
00069 PHP_MINIT_FUNCTION(xml);
00070 PHP_MINFO_FUNCTION(xml);
00071 static PHP_GINIT_FUNCTION(xml);
00072 
00073 static void xml_parser_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
00074 static void xml_set_handler(zval **, zval **);
00075 inline static unsigned short xml_encode_iso_8859_1(unsigned char);
00076 inline static char xml_decode_iso_8859_1(unsigned short);
00077 inline static unsigned short xml_encode_us_ascii(unsigned char);
00078 inline static char xml_decode_us_ascii(unsigned short);
00079 static zval *xml_call_handler(xml_parser *, zval *, zend_function *, int, zval **);
00080 static zval *_xml_xmlchar_zval(const XML_Char *, int, const XML_Char *);
00081 static int _xml_xmlcharlen(const XML_Char *);
00082 static void _xml_add_to_info(xml_parser *parser,char *name);
00083 inline static char *_xml_decode_tag(xml_parser *parser, const char *tag);
00084 
00085 void _xml_startElementHandler(void *, const XML_Char *, const XML_Char **);
00086 void _xml_endElementHandler(void *, const XML_Char *);
00087 void _xml_characterDataHandler(void *, const XML_Char *, int);
00088 void _xml_processingInstructionHandler(void *, const XML_Char *, const XML_Char *);
00089 void _xml_defaultHandler(void *, const XML_Char *, int);
00090 void _xml_unparsedEntityDeclHandler(void *, const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *);
00091 void _xml_notationDeclHandler(void *, const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *);
00092 int  _xml_externalEntityRefHandler(XML_Parser, const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *);
00093 
00094 void _xml_startNamespaceDeclHandler(void *, const XML_Char *, const XML_Char *);
00095 void _xml_endNamespaceDeclHandler(void *, const XML_Char *);
00096 /* }}} */
00097 
00098 /* {{{ extension definition structures */
00099 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_parser_create, 0, 0, 0)
00100        ZEND_ARG_INFO(0, encoding)
00101 ZEND_END_ARG_INFO()
00102 
00103 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_parser_create_ns, 0, 0, 0)
00104        ZEND_ARG_INFO(0, encoding)
00105        ZEND_ARG_INFO(0, sep)
00106 ZEND_END_ARG_INFO()
00107 
00108 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_object, 0, 0, 2)
00109        ZEND_ARG_INFO(0, parser)
00110        ZEND_ARG_INFO(1, obj)
00111 ZEND_END_ARG_INFO()
00112 
00113 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_element_handler, 0, 0, 3)
00114        ZEND_ARG_INFO(0, parser)
00115        ZEND_ARG_INFO(0, shdl)
00116        ZEND_ARG_INFO(0, ehdl)
00117 ZEND_END_ARG_INFO()
00118 
00119 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_character_data_handler, 0, 0, 2)
00120        ZEND_ARG_INFO(0, parser)
00121        ZEND_ARG_INFO(0, hdl)
00122 ZEND_END_ARG_INFO()
00123 
00124 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_processing_instruction_handler, 0, 0, 2)
00125        ZEND_ARG_INFO(0, parser)
00126        ZEND_ARG_INFO(0, hdl)
00127 ZEND_END_ARG_INFO()
00128 
00129 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_default_handler, 0, 0, 2)
00130        ZEND_ARG_INFO(0, parser)
00131        ZEND_ARG_INFO(0, hdl)
00132 ZEND_END_ARG_INFO()
00133 
00134 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_unparsed_entity_decl_handler, 0, 0, 2)
00135        ZEND_ARG_INFO(0, parser)
00136        ZEND_ARG_INFO(0, hdl)
00137 ZEND_END_ARG_INFO()
00138 
00139 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_notation_decl_handler, 0, 0, 2)
00140        ZEND_ARG_INFO(0, parser)
00141        ZEND_ARG_INFO(0, hdl)
00142 ZEND_END_ARG_INFO()
00143 
00144 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_external_entity_ref_handler, 0, 0, 2)
00145        ZEND_ARG_INFO(0, parser)
00146        ZEND_ARG_INFO(0, hdl)
00147 ZEND_END_ARG_INFO()
00148 
00149 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_start_namespace_decl_handler, 0, 0, 2)
00150        ZEND_ARG_INFO(0, parser)
00151        ZEND_ARG_INFO(0, hdl)
00152 ZEND_END_ARG_INFO()
00153 
00154 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_end_namespace_decl_handler, 0, 0, 2)
00155        ZEND_ARG_INFO(0, parser)
00156        ZEND_ARG_INFO(0, hdl)
00157 ZEND_END_ARG_INFO()
00158 
00159 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_parse, 0, 0, 2)
00160        ZEND_ARG_INFO(0, parser)
00161        ZEND_ARG_INFO(0, data)
00162        ZEND_ARG_INFO(0, isfinal)
00163 ZEND_END_ARG_INFO()
00164 
00165 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_parse_into_struct, 0, 0, 3)
00166        ZEND_ARG_INFO(0, parser)
00167        ZEND_ARG_INFO(0, data)
00168        ZEND_ARG_INFO(1, values)
00169        ZEND_ARG_INFO(1, index)
00170 ZEND_END_ARG_INFO()
00171 
00172 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_get_error_code, 0, 0, 1)
00173        ZEND_ARG_INFO(0, parser)
00174 ZEND_END_ARG_INFO()
00175 
00176 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_error_string, 0, 0, 1)
00177        ZEND_ARG_INFO(0, code)
00178 ZEND_END_ARG_INFO()
00179 
00180 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_get_current_line_number, 0, 0, 1)
00181        ZEND_ARG_INFO(0, parser)
00182 ZEND_END_ARG_INFO()
00183 
00184 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_get_current_column_number, 0, 0, 1)
00185        ZEND_ARG_INFO(0, parser)
00186 ZEND_END_ARG_INFO()
00187 
00188 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_get_current_byte_index, 0, 0, 1)
00189        ZEND_ARG_INFO(0, parser)
00190 ZEND_END_ARG_INFO()
00191 
00192 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_parser_free, 0, 0, 1)
00193        ZEND_ARG_INFO(0, parser)
00194 ZEND_END_ARG_INFO()
00195 
00196 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_parser_set_option, 0, 0, 3)
00197        ZEND_ARG_INFO(0, parser)
00198        ZEND_ARG_INFO(0, option)
00199        ZEND_ARG_INFO(0, value)
00200 ZEND_END_ARG_INFO()
00201 
00202 ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_parser_get_option, 0, 0, 2)
00203        ZEND_ARG_INFO(0, parser)
00204        ZEND_ARG_INFO(0, option)
00205 ZEND_END_ARG_INFO()
00206 
00207 ZEND_BEGIN_ARG_INFO_EX(arginfo_utf8_encode, 0, 0, 1)
00208        ZEND_ARG_INFO(0, data)
00209 ZEND_END_ARG_INFO()
00210 
00211 ZEND_BEGIN_ARG_INFO_EX(arginfo_utf8_decode, 0, 0, 1)
00212        ZEND_ARG_INFO(0, data)
00213 ZEND_END_ARG_INFO()
00214 
00215 const zend_function_entry xml_functions[] = {
00216        PHP_FE(xml_parser_create,                               arginfo_xml_parser_create)
00217        PHP_FE(xml_parser_create_ns,                            arginfo_xml_parser_create_ns)
00218        PHP_FE(xml_set_object,                                         arginfo_xml_set_object)
00219        PHP_FE(xml_set_element_handler,                         arginfo_xml_set_element_handler)
00220        PHP_FE(xml_set_character_data_handler,           arginfo_xml_set_character_data_handler)
00221        PHP_FE(xml_set_processing_instruction_handler,   arginfo_xml_set_processing_instruction_handler)
00222        PHP_FE(xml_set_default_handler,                         arginfo_xml_set_default_handler)
00223        PHP_FE(xml_set_unparsed_entity_decl_handler,arginfo_xml_set_unparsed_entity_decl_handler)
00224        PHP_FE(xml_set_notation_decl_handler,            arginfo_xml_set_notation_decl_handler)
00225        PHP_FE(xml_set_external_entity_ref_handler,      arginfo_xml_set_external_entity_ref_handler)
00226        PHP_FE(xml_set_start_namespace_decl_handler,arginfo_xml_set_start_namespace_decl_handler)
00227        PHP_FE(xml_set_end_namespace_decl_handler,       arginfo_xml_set_end_namespace_decl_handler)
00228        PHP_FE(xml_parse,                                              arginfo_xml_parse)
00229        PHP_FE(xml_parse_into_struct,                           arginfo_xml_parse_into_struct)
00230        PHP_FE(xml_get_error_code,                              arginfo_xml_get_error_code)
00231        PHP_FE(xml_error_string,                                arginfo_xml_error_string)
00232        PHP_FE(xml_get_current_line_number,                     arginfo_xml_get_current_line_number)
00233        PHP_FE(xml_get_current_column_number,            arginfo_xml_get_current_column_number)
00234        PHP_FE(xml_get_current_byte_index,               arginfo_xml_get_current_byte_index)
00235        PHP_FE(xml_parser_free,                                 arginfo_xml_parser_free)
00236        PHP_FE(xml_parser_set_option,                           arginfo_xml_parser_set_option)
00237        PHP_FE(xml_parser_get_option,                           arginfo_xml_parser_get_option)
00238        PHP_FE(utf8_encode,                                     arginfo_utf8_encode)
00239        PHP_FE(utf8_decode,                                     arginfo_utf8_decode)
00240        PHP_FE_END
00241 };
00242 
00243 #ifdef LIBXML_EXPAT_COMPAT
00244 static const zend_module_dep xml_deps[] = {
00245        ZEND_MOD_REQUIRED("libxml")
00246        ZEND_MOD_END
00247 };
00248 #endif
00249 
00250 zend_module_entry xml_module_entry = {
00251 #ifdef LIBXML_EXPAT_COMPAT
00252     STANDARD_MODULE_HEADER_EX, NULL,
00253        xml_deps,
00254 #else
00255     STANDARD_MODULE_HEADER,
00256 #endif
00257        "xml",                /* extension name */
00258        xml_functions,        /* extension function list */
00259        PHP_MINIT(xml),       /* extension-wide startup function */
00260        NULL,                 /* extension-wide shutdown function */
00261        NULL,                 /* per-request startup function */
00262        NULL,                 /* per-request shutdown function */
00263        PHP_MINFO(xml),       /* information function */
00264     NO_VERSION_YET,
00265     PHP_MODULE_GLOBALS(xml), /* globals descriptor */
00266     PHP_GINIT(xml),          /* globals ctor */
00267     NULL,                    /* globals dtor */
00268     NULL,                    /* post deactivate */
00269        STANDARD_MODULE_PROPERTIES_EX
00270 };
00271 
00272 /* All the encoding functions are set to NULL right now, since all
00273  * the encoding is currently done internally by expat/xmltok.
00274  */
00275 xml_encoding xml_encodings[] = {
00276        { "ISO-8859-1", xml_decode_iso_8859_1, xml_encode_iso_8859_1 },
00277        { "US-ASCII",   xml_decode_us_ascii,   xml_encode_us_ascii   },
00278        { "UTF-8",      NULL,                  NULL                  },
00279        { NULL,         NULL,                  NULL                  }
00280 };
00281 
00282 static XML_Memory_Handling_Suite php_xml_mem_hdlrs;
00283 
00284 /* True globals, no need for thread safety */
00285 static int le_xml_parser; 
00286 
00287 /* }}} */
00288 
00289 /* {{{ startup, shutdown and info functions */
00290 static PHP_GINIT_FUNCTION(xml)
00291 {
00292        xml_globals->default_encoding = "UTF-8";
00293 }
00294 
00295 static void *php_xml_malloc_wrapper(size_t sz)
00296 {
00297        return emalloc(sz);
00298 }
00299 
00300 static void *php_xml_realloc_wrapper(void *ptr, size_t sz)
00301 {
00302        return erealloc(ptr, sz);
00303 }
00304 
00305 static void php_xml_free_wrapper(void *ptr)
00306 {
00307        if (ptr != NULL) {
00308               efree(ptr);
00309        }
00310 }
00311 
00312 PHP_MINIT_FUNCTION(xml)
00313 {
00314        le_xml_parser =      zend_register_list_destructors_ex(xml_parser_dtor, NULL, "xml", module_number);
00315 
00316        REGISTER_LONG_CONSTANT("XML_ERROR_NONE", XML_ERROR_NONE, CONST_CS|CONST_PERSISTENT);
00317        REGISTER_LONG_CONSTANT("XML_ERROR_NO_MEMORY", XML_ERROR_NO_MEMORY, CONST_CS|CONST_PERSISTENT);
00318        REGISTER_LONG_CONSTANT("XML_ERROR_SYNTAX", XML_ERROR_SYNTAX, CONST_CS|CONST_PERSISTENT);
00319        REGISTER_LONG_CONSTANT("XML_ERROR_NO_ELEMENTS", XML_ERROR_NO_ELEMENTS, CONST_CS|CONST_PERSISTENT);
00320        REGISTER_LONG_CONSTANT("XML_ERROR_INVALID_TOKEN", XML_ERROR_INVALID_TOKEN, CONST_CS|CONST_PERSISTENT);
00321        REGISTER_LONG_CONSTANT("XML_ERROR_UNCLOSED_TOKEN", XML_ERROR_UNCLOSED_TOKEN, CONST_CS|CONST_PERSISTENT);
00322        REGISTER_LONG_CONSTANT("XML_ERROR_PARTIAL_CHAR", XML_ERROR_PARTIAL_CHAR, CONST_CS|CONST_PERSISTENT);
00323        REGISTER_LONG_CONSTANT("XML_ERROR_TAG_MISMATCH", XML_ERROR_TAG_MISMATCH, CONST_CS|CONST_PERSISTENT);
00324        REGISTER_LONG_CONSTANT("XML_ERROR_DUPLICATE_ATTRIBUTE", XML_ERROR_DUPLICATE_ATTRIBUTE, CONST_CS|CONST_PERSISTENT);
00325        REGISTER_LONG_CONSTANT("XML_ERROR_JUNK_AFTER_DOC_ELEMENT", XML_ERROR_JUNK_AFTER_DOC_ELEMENT, CONST_CS|CONST_PERSISTENT);
00326        REGISTER_LONG_CONSTANT("XML_ERROR_PARAM_ENTITY_REF", XML_ERROR_PARAM_ENTITY_REF, CONST_CS|CONST_PERSISTENT);
00327        REGISTER_LONG_CONSTANT("XML_ERROR_UNDEFINED_ENTITY", XML_ERROR_UNDEFINED_ENTITY, CONST_CS|CONST_PERSISTENT);
00328        REGISTER_LONG_CONSTANT("XML_ERROR_RECURSIVE_ENTITY_REF", XML_ERROR_RECURSIVE_ENTITY_REF, CONST_CS|CONST_PERSISTENT);
00329        REGISTER_LONG_CONSTANT("XML_ERROR_ASYNC_ENTITY", XML_ERROR_ASYNC_ENTITY, CONST_CS|CONST_PERSISTENT);
00330        REGISTER_LONG_CONSTANT("XML_ERROR_BAD_CHAR_REF", XML_ERROR_BAD_CHAR_REF, CONST_CS|CONST_PERSISTENT);
00331        REGISTER_LONG_CONSTANT("XML_ERROR_BINARY_ENTITY_REF", XML_ERROR_BINARY_ENTITY_REF, CONST_CS|CONST_PERSISTENT);
00332        REGISTER_LONG_CONSTANT("XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF", XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF, CONST_CS|CONST_PERSISTENT);
00333        REGISTER_LONG_CONSTANT("XML_ERROR_MISPLACED_XML_PI", XML_ERROR_MISPLACED_XML_PI, CONST_CS|CONST_PERSISTENT);
00334        REGISTER_LONG_CONSTANT("XML_ERROR_UNKNOWN_ENCODING", XML_ERROR_UNKNOWN_ENCODING, CONST_CS|CONST_PERSISTENT);
00335        REGISTER_LONG_CONSTANT("XML_ERROR_INCORRECT_ENCODING", XML_ERROR_INCORRECT_ENCODING, CONST_CS|CONST_PERSISTENT);
00336        REGISTER_LONG_CONSTANT("XML_ERROR_UNCLOSED_CDATA_SECTION", XML_ERROR_UNCLOSED_CDATA_SECTION, CONST_CS|CONST_PERSISTENT);
00337        REGISTER_LONG_CONSTANT("XML_ERROR_EXTERNAL_ENTITY_HANDLING", XML_ERROR_EXTERNAL_ENTITY_HANDLING, CONST_CS|CONST_PERSISTENT);
00338 
00339        REGISTER_LONG_CONSTANT("XML_OPTION_CASE_FOLDING", PHP_XML_OPTION_CASE_FOLDING, CONST_CS|CONST_PERSISTENT);
00340        REGISTER_LONG_CONSTANT("XML_OPTION_TARGET_ENCODING", PHP_XML_OPTION_TARGET_ENCODING, CONST_CS|CONST_PERSISTENT);
00341        REGISTER_LONG_CONSTANT("XML_OPTION_SKIP_TAGSTART", PHP_XML_OPTION_SKIP_TAGSTART, CONST_CS|CONST_PERSISTENT);
00342        REGISTER_LONG_CONSTANT("XML_OPTION_SKIP_WHITE", PHP_XML_OPTION_SKIP_WHITE, CONST_CS|CONST_PERSISTENT);
00343 
00344        /* this object should not be pre-initialised at compile time,
00345           as the order of members may vary */  
00346 
00347        php_xml_mem_hdlrs.malloc_fcn = php_xml_malloc_wrapper;
00348        php_xml_mem_hdlrs.realloc_fcn = php_xml_realloc_wrapper;
00349        php_xml_mem_hdlrs.free_fcn = php_xml_free_wrapper;
00350 
00351 #ifdef LIBXML_EXPAT_COMPAT
00352        REGISTER_STRING_CONSTANT("XML_SAX_IMPL", "libxml", CONST_CS|CONST_PERSISTENT);
00353 #else
00354        REGISTER_STRING_CONSTANT("XML_SAX_IMPL", "expat", CONST_CS|CONST_PERSISTENT);
00355 #endif
00356 
00357        return SUCCESS;
00358 }
00359 
00360 PHP_MINFO_FUNCTION(xml)
00361 {
00362        php_info_print_table_start();
00363        php_info_print_table_row(2, "XML Support", "active");
00364        php_info_print_table_row(2, "XML Namespace Support", "active");
00365 #if defined(LIBXML_DOTTED_VERSION) && defined(LIBXML_EXPAT_COMPAT)
00366        php_info_print_table_row(2, "libxml2 Version", LIBXML_DOTTED_VERSION);
00367 #else
00368        php_info_print_table_row(2, "EXPAT Version", XML_ExpatVersion());
00369 #endif
00370        php_info_print_table_end();
00371 }
00372 /* }}} */
00373 
00374 /* {{{ extension-internal functions */
00375 static zval *_xml_resource_zval(long value)
00376 {
00377        zval *ret;
00378        TSRMLS_FETCH();
00379 
00380        MAKE_STD_ZVAL(ret);
00381 
00382        Z_TYPE_P(ret) = IS_RESOURCE;
00383        Z_LVAL_P(ret) = value;
00384 
00385        zend_list_addref(value);
00386 
00387        return ret;
00388 }
00389 
00390 static zval *_xml_string_zval(const char *str)
00391 {
00392        zval *ret;
00393        int len = strlen(str);
00394        MAKE_STD_ZVAL(ret);
00395 
00396        Z_TYPE_P(ret) = IS_STRING;
00397        Z_STRLEN_P(ret) = len;
00398        Z_STRVAL_P(ret) = estrndup(str, len);
00399        return ret;
00400 }
00401 
00402 static zval *_xml_xmlchar_zval(const XML_Char *s, int len, const XML_Char *encoding)
00403 {
00404        zval *ret;
00405        MAKE_STD_ZVAL(ret);
00406        
00407        if (s == NULL) {
00408               ZVAL_FALSE(ret);
00409               return ret;
00410        }
00411        if (len == 0) {
00412               len = _xml_xmlcharlen(s);
00413        }
00414        Z_TYPE_P(ret) = IS_STRING;
00415        Z_STRVAL_P(ret) = xml_utf8_decode(s, len, &Z_STRLEN_P(ret), encoding);
00416        return ret;
00417 }
00418 /* }}} */
00419 
00420 /* {{{ xml_parser_dtor() */
00421 static void xml_parser_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
00422 {
00423        xml_parser *parser = (xml_parser *)rsrc->ptr;
00424        
00425        if (parser->parser) {
00426               XML_ParserFree(parser->parser);
00427        }
00428        if (parser->ltags) {
00429               int inx;
00430               for (inx = 0; inx < parser->level; inx++)
00431                      efree(parser->ltags[ inx ]);
00432               efree(parser->ltags);
00433        }
00434        if (parser->startElementHandler) {
00435               zval_ptr_dtor(&parser->startElementHandler);
00436        }
00437        if (parser->endElementHandler) {
00438               zval_ptr_dtor(&parser->endElementHandler);
00439        }
00440        if (parser->characterDataHandler) {
00441               zval_ptr_dtor(&parser->characterDataHandler);
00442        }
00443        if (parser->processingInstructionHandler) {
00444               zval_ptr_dtor(&parser->processingInstructionHandler);
00445        }
00446        if (parser->defaultHandler) {
00447               zval_ptr_dtor(&parser->defaultHandler);
00448        }
00449        if (parser->unparsedEntityDeclHandler) {
00450               zval_ptr_dtor(&parser->unparsedEntityDeclHandler);
00451        }
00452        if (parser->notationDeclHandler) {
00453               zval_ptr_dtor(&parser->notationDeclHandler);
00454        }
00455        if (parser->externalEntityRefHandler) {
00456               zval_ptr_dtor(&parser->externalEntityRefHandler);
00457        }
00458        if (parser->unknownEncodingHandler) {
00459               zval_ptr_dtor(&parser->unknownEncodingHandler);
00460        }
00461        if (parser->startNamespaceDeclHandler) {
00462               zval_ptr_dtor(&parser->startNamespaceDeclHandler);
00463        }
00464        if (parser->endNamespaceDeclHandler) {
00465               zval_ptr_dtor(&parser->endNamespaceDeclHandler);
00466        }
00467        if (parser->baseURI) {
00468               efree(parser->baseURI);
00469        }
00470        if (parser->object) {
00471               zval_ptr_dtor(&parser->object);
00472        }
00473 
00474        efree(parser);
00475 }
00476 /* }}} */
00477 
00478 /* {{{ xml_set_handler() */
00479 static void xml_set_handler(zval **handler, zval **data)
00480 {
00481        /* If we have already a handler, release it */
00482        if (*handler) {
00483               zval_ptr_dtor(handler);
00484        }
00485 
00486        /* IS_ARRAY might indicate that we're using array($obj, 'method') syntax */
00487        if (Z_TYPE_PP(data) != IS_ARRAY && Z_TYPE_PP(data) != IS_OBJECT) {
00488 
00489               convert_to_string_ex(data);
00490               if (Z_STRLEN_PP(data) == 0) {
00491                      *handler = NULL;
00492                      return;
00493               }
00494        }
00495 
00496        zval_add_ref(data);
00497 
00498        *handler = *data;
00499 }
00500 /* }}} */
00501 
00502 /* {{{ xml_call_handler() */
00503 static zval *xml_call_handler(xml_parser *parser, zval *handler, zend_function *function_ptr, int argc, zval **argv)
00504 {
00505        int i; 
00506        TSRMLS_FETCH();
00507 
00508        if (parser && handler && !EG(exception)) {
00509               zval ***args;
00510               zval *retval;
00511               int result;
00512               zend_fcall_info fci;
00513 
00514               args = safe_emalloc(sizeof(zval **), argc, 0);
00515               for (i = 0; i < argc; i++) {
00516                      args[i] = &argv[i];
00517               }
00518               
00519               fci.size = sizeof(fci);
00520               fci.function_table = EG(function_table);
00521               fci.function_name = handler;
00522               fci.symbol_table = NULL;
00523               fci.object_ptr = parser->object;
00524               fci.retval_ptr_ptr = &retval;
00525               fci.param_count = argc;
00526               fci.params = args;
00527               fci.no_separation = 0;
00528               /*fci.function_handler_cache = &function_ptr;*/
00529 
00530               result = zend_call_function(&fci, NULL TSRMLS_CC);
00531               if (result == FAILURE) {
00532                      zval **method;
00533                      zval **obj;
00534 
00535                      if (Z_TYPE_P(handler) == IS_STRING) {
00536                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler %s()", Z_STRVAL_P(handler));
00537                      } else if (zend_hash_index_find(Z_ARRVAL_P(handler), 0, (void **) &obj) == SUCCESS &&
00538                                       zend_hash_index_find(Z_ARRVAL_P(handler), 1, (void **) &method) == SUCCESS &&
00539                                       Z_TYPE_PP(obj) == IS_OBJECT &&
00540                                       Z_TYPE_PP(method) == IS_STRING) {
00541                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler %s::%s()", Z_OBJCE_PP(obj)->name, Z_STRVAL_PP(method));
00542                      } else 
00543                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler");
00544               }
00545 
00546               for (i = 0; i < argc; i++) {
00547                      zval_ptr_dtor(args[i]);
00548               }
00549               efree(args);
00550 
00551               if (result == FAILURE) {
00552                      return NULL;
00553               } else {
00554                      return EG(exception) ? NULL : retval;
00555               }
00556        } else {
00557               for (i = 0; i < argc; i++) {
00558                      zval_ptr_dtor(&argv[i]);
00559               }
00560               return NULL;
00561        }
00562 }
00563 /* }}} */
00564 
00565 /* {{{ xml_encode_iso_8859_1() */
00566 inline static unsigned short xml_encode_iso_8859_1(unsigned char c)
00567 {
00568        return (unsigned short)c;
00569 }
00570 /* }}} */
00571 
00572 /* {{{ xml_decode_iso_8859_1() */
00573 inline static char xml_decode_iso_8859_1(unsigned short c)
00574 {
00575        return (char)(c > 0xff ? '?' : c);
00576 }
00577 /* }}} */
00578 
00579 /* {{{ xml_encode_us_ascii() */
00580 inline static unsigned short xml_encode_us_ascii(unsigned char c)
00581 {
00582        return (unsigned short)c;
00583 }
00584 /* }}} */
00585 
00586 /* {{{ xml_decode_us_ascii() */
00587 inline static char xml_decode_us_ascii(unsigned short c)
00588 {
00589        return (char)(c > 0x7f ? '?' : c);
00590 }
00591 /* }}} */
00592 
00593 /* {{{ xml_get_encoding() */
00594 static xml_encoding *xml_get_encoding(const XML_Char *name)
00595 {
00596        xml_encoding *enc = &xml_encodings[0];
00597 
00598        while (enc && enc->name) {
00599               if (strcasecmp(name, enc->name) == 0) {
00600                      return enc;
00601               }
00602               enc++;
00603        }
00604        return NULL;
00605 }
00606 /* }}} */
00607 
00608 /* {{{ xml_utf8_encode */
00609 PHPAPI char *xml_utf8_encode(const char *s, int len, int *newlen, const XML_Char *encoding)
00610 {
00611        int pos = len;
00612        char *newbuf;
00613        unsigned int c;
00614        unsigned short (*encoder)(unsigned char) = NULL;
00615        xml_encoding *enc = xml_get_encoding(encoding);
00616 
00617        *newlen = 0;
00618        if (enc) {
00619               encoder = enc->encoding_function;
00620        } else {
00621               /* If the target encoding was unknown, fail */
00622               return NULL;
00623        }
00624        if (encoder == NULL) {
00625               /* If no encoder function was specified, return the data as-is.
00626                */
00627               newbuf = emalloc(len + 1);
00628               memcpy(newbuf, s, len);
00629               *newlen = len;
00630               newbuf[*newlen] = '\0';
00631               return newbuf;
00632        }
00633        /* This is the theoretical max (will never get beyond len * 2 as long
00634         * as we are converting from single-byte characters, though) */
00635        newbuf = safe_emalloc(len, 4, 1);
00636        while (pos > 0) {
00637               c = encoder ? encoder((unsigned char)(*s)) : (unsigned short)(*s);
00638               if (c < 0x80) {
00639                      newbuf[(*newlen)++] = (char) c;
00640               } else if (c < 0x800) {
00641                      newbuf[(*newlen)++] = (0xc0 | (c >> 6));
00642                      newbuf[(*newlen)++] = (0x80 | (c & 0x3f));
00643               } else if (c < 0x10000) {
00644                      newbuf[(*newlen)++] = (0xe0 | (c >> 12));
00645                      newbuf[(*newlen)++] = (0xc0 | ((c >> 6) & 0x3f));
00646                      newbuf[(*newlen)++] = (0x80 | (c & 0x3f));
00647               } else if (c < 0x200000) {
00648                      newbuf[(*newlen)++] = (0xf0 | (c >> 18));
00649                      newbuf[(*newlen)++] = (0xe0 | ((c >> 12) & 0x3f));
00650                      newbuf[(*newlen)++] = (0xc0 | ((c >> 6) & 0x3f));
00651                      newbuf[(*newlen)++] = (0x80 | (c & 0x3f));
00652               }
00653               pos--;
00654               s++;
00655        }
00656        newbuf[*newlen] = 0;
00657        newbuf = erealloc(newbuf, (*newlen)+1);
00658        return newbuf;
00659 }
00660 /* }}} */
00661 
00662 /* copied from trunk's implementation of get_next_char in ext/standard/html.c */
00663 #define MB_FAILURE(pos, advance) do { \
00664        *cursor = pos + (advance); \
00665        *status = FAILURE; \
00666        return 0; \
00667 } while (0)
00668 
00669 #define CHECK_LEN(pos, chars_need) ((str_len - (pos)) >= (chars_need))
00670 #define utf8_lead(c)  ((c) < 0x80 || ((c) >= 0xC2 && (c) <= 0xF4))
00671 #define utf8_trail(c) ((c) >= 0x80 && (c) <= 0xBF)
00672 
00673 /* {{{ php_next_utf8_char
00674  */
00675 static inline unsigned int php_next_utf8_char(
00676               const unsigned char *str,
00677               size_t str_len,
00678               size_t *cursor,
00679               int *status)
00680 {
00681        size_t pos = *cursor;
00682        unsigned int this_char = 0;
00683        unsigned char c;
00684 
00685        *status = SUCCESS;
00686 
00687        if (!CHECK_LEN(pos, 1))
00688               MB_FAILURE(pos, 1);
00689 
00690        /* We'll follow strategy 2. from section 3.6.1 of UTR #36:
00691               * "In a reported illegal byte sequence, do not include any
00692               *  non-initial byte that encodes a valid character or is a leading
00693               *  byte for a valid sequence.» */
00694        c = str[pos];
00695        if (c < 0x80) {
00696               this_char = c;
00697               pos++;
00698        } else if (c < 0xc2) {
00699               MB_FAILURE(pos, 1);
00700        } else if (c < 0xe0) {
00701               if (!CHECK_LEN(pos, 2))
00702                      MB_FAILURE(pos, 1);
00703 
00704               if (!utf8_trail(str[pos + 1])) {
00705                      MB_FAILURE(pos, utf8_lead(str[pos + 1]) ? 1 : 2);
00706               }
00707               this_char = ((c & 0x1f) << 6) | (str[pos + 1] & 0x3f);
00708               if (this_char < 0x80) { /* non-shortest form */
00709                      MB_FAILURE(pos, 2);
00710               }
00711               pos += 2;
00712        } else if (c < 0xf0) {
00713               size_t avail = str_len - pos;
00714 
00715               if (avail < 3 ||
00716                             !utf8_trail(str[pos + 1]) || !utf8_trail(str[pos + 2])) {
00717                      if (avail < 2 || utf8_lead(str[pos + 1]))
00718                             MB_FAILURE(pos, 1);
00719                      else if (avail < 3 || utf8_lead(str[pos + 2]))
00720                             MB_FAILURE(pos, 2);
00721                      else
00722                             MB_FAILURE(pos, 3);
00723               }
00724 
00725               this_char = ((c & 0x0f) << 12) | ((str[pos + 1] & 0x3f) << 6) | (str[pos + 2] & 0x3f);
00726               if (this_char < 0x800) { /* non-shortest form */
00727                      MB_FAILURE(pos, 3);
00728               } else if (this_char >= 0xd800 && this_char <= 0xdfff) { /* surrogate */
00729                      MB_FAILURE(pos, 3);
00730               }
00731               pos += 3;
00732        } else if (c < 0xf5) {
00733               size_t avail = str_len - pos;
00734 
00735               if (avail < 4 ||
00736                             !utf8_trail(str[pos + 1]) || !utf8_trail(str[pos + 2]) ||
00737                             !utf8_trail(str[pos + 3])) {
00738                      if (avail < 2 || utf8_lead(str[pos + 1]))
00739                             MB_FAILURE(pos, 1);
00740                      else if (avail < 3 || utf8_lead(str[pos + 2]))
00741                             MB_FAILURE(pos, 2);
00742                      else if (avail < 4 || utf8_lead(str[pos + 3]))
00743                             MB_FAILURE(pos, 3);
00744                      else
00745                             MB_FAILURE(pos, 4);
00746               }
00747                             
00748               this_char = ((c & 0x07) << 18) | ((str[pos + 1] & 0x3f) << 12) | ((str[pos + 2] & 0x3f) << 6) | (str[pos + 3] & 0x3f);
00749               if (this_char < 0x10000 || this_char > 0x10FFFF) { /* non-shortest form or outside range */
00750                      MB_FAILURE(pos, 4);
00751               }
00752               pos += 4;
00753        } else {
00754               MB_FAILURE(pos, 1);
00755        }
00756        
00757        *cursor = pos;
00758        return this_char;
00759 }
00760 /* }}} */
00761 
00762 
00763 /* {{{ xml_utf8_decode */
00764 PHPAPI char *xml_utf8_decode(const XML_Char *s, int len, int *newlen, const XML_Char *encoding)
00765 {
00766        size_t pos = 0;
00767        char *newbuf = emalloc(len + 1);
00768        unsigned int c;
00769        char (*decoder)(unsigned short) = NULL;
00770        xml_encoding *enc = xml_get_encoding(encoding);
00771 
00772        *newlen = 0;
00773        if (enc) {
00774               decoder = enc->decoding_function;
00775        }
00776        if (decoder == NULL) {
00777               /* If the target encoding was unknown, or no decoder function
00778                * was specified, return the UTF-8-encoded data as-is.
00779                */
00780               memcpy(newbuf, s, len);
00781               *newlen = len;
00782               newbuf[*newlen] = '\0';
00783               return newbuf;
00784        }
00785 
00786        while (pos < (size_t)len) {
00787               int status = FAILURE;
00788               c = php_next_utf8_char((const unsigned char*)s, (size_t) len, &pos, &status);
00789 
00790               if (status == FAILURE || c > 0xFFU) {
00791                      c = '?';
00792               }
00793 
00794               newbuf[*newlen] = decoder ? decoder(c) : c;
00795               ++*newlen;
00796        }
00797        if (*newlen < len) {
00798               newbuf = erealloc(newbuf, *newlen + 1);
00799        }
00800        newbuf[*newlen] = '\0';
00801        return newbuf;
00802 }
00803 /* }}} */
00804 
00805 /* {{{ _xml_xmlcharlen() */
00806 static int _xml_xmlcharlen(const XML_Char *s)
00807 {
00808        int len = 0;
00809 
00810        while (*s) {
00811               len++;
00812               s++;
00813        }
00814        return len;
00815 }
00816 /* }}} */
00817 
00818 /* {{{ _xml_zval_strdup() */
00819 PHPAPI char *_xml_zval_strdup(zval *val)
00820 {
00821        if (Z_TYPE_P(val) == IS_STRING) {
00822               char *buf = emalloc(Z_STRLEN_P(val) + 1);
00823               memcpy(buf, Z_STRVAL_P(val), Z_STRLEN_P(val));
00824               buf[Z_STRLEN_P(val)] = '\0';
00825               return buf;
00826        }
00827        return NULL;
00828 }
00829 /* }}} */
00830 
00831 /* {{{ _xml_add_to_info */
00832 static void _xml_add_to_info(xml_parser *parser,char *name)
00833 {
00834        zval **element, *values;
00835 
00836        if (! parser->info) {
00837               return;
00838        }
00839 
00840        if (zend_hash_find(Z_ARRVAL_P(parser->info),name,strlen(name) + 1,(void **) &element) == FAILURE) {
00841               MAKE_STD_ZVAL(values);
00842               
00843               array_init(values);
00844               
00845               zend_hash_update(Z_ARRVAL_P(parser->info), name, strlen(name)+1, (void *) &values, sizeof(zval*), (void **) &element);
00846        } 
00847                      
00848        add_next_index_long(*element,parser->curtag);
00849        
00850        parser->curtag++;
00851 }
00852 /* }}} */
00853 
00854 /* {{{ _xml_decode_tag() */
00855 static char *_xml_decode_tag(xml_parser *parser, const char *tag)
00856 {
00857        char *newstr;
00858        int out_len;
00859 
00860        newstr = xml_utf8_decode(tag, strlen(tag), &out_len, parser->target_encoding);
00861 
00862        if (parser->case_folding) {
00863               php_strtoupper(newstr, out_len);
00864        }
00865 
00866        return newstr;
00867 }
00868 /* }}} */
00869 
00870 /* {{{ _xml_startElementHandler() */
00871 void _xml_startElementHandler(void *userData, const XML_Char *name, const XML_Char **attributes)
00872 {
00873        xml_parser *parser = (xml_parser *)userData;
00874        const char **attrs = (const char **) attributes;
00875        char *tag_name;
00876        char *att, *val;
00877        int val_len;
00878        zval *retval, *args[3];
00879 
00880        if (parser) {
00881               parser->level++;
00882 
00883               tag_name = _xml_decode_tag(parser, name);
00884 
00885               if (parser->startElementHandler) {
00886                      args[0] = _xml_resource_zval(parser->index);
00887                      args[1] = _xml_string_zval(((char *) tag_name) + parser->toffset);
00888                      MAKE_STD_ZVAL(args[2]);
00889                      array_init(args[2]);
00890 
00891                      while (attributes && *attributes) {
00892                             att = _xml_decode_tag(parser, attributes[0]);
00893                             val = xml_utf8_decode(attributes[1], strlen(attributes[1]), &val_len, parser->target_encoding);
00894 
00895                             add_assoc_stringl(args[2], att, val, val_len, 0);
00896 
00897                             attributes += 2;
00898 
00899                             efree(att);
00900                      }
00901                      
00902                      if ((retval = xml_call_handler(parser, parser->startElementHandler, parser->startElementPtr, 3, args))) {
00903                             zval_ptr_dtor(&retval);
00904                      }
00905               } 
00906 
00907               if (parser->data) {
00908                      zval *tag, *atr;
00909                      int atcnt = 0;
00910 
00911                      MAKE_STD_ZVAL(tag);
00912                      MAKE_STD_ZVAL(atr);
00913 
00914                      array_init(tag);
00915                      array_init(atr);
00916 
00917                      _xml_add_to_info(parser,((char *) tag_name) + parser->toffset);
00918 
00919                      add_assoc_string(tag,"tag",((char *) tag_name) + parser->toffset,1); /* cast to avoid gcc-warning */
00920                      add_assoc_string(tag,"type","open",1);
00921                      add_assoc_long(tag,"level",parser->level);
00922 
00923                      parser->ltags[parser->level-1] = estrdup(tag_name);
00924                      parser->lastwasopen = 1;
00925 
00926                      attributes = (const XML_Char **) attrs;
00927 
00928                      while (attributes && *attributes) {
00929                             att = _xml_decode_tag(parser, attributes[0]);
00930                             val = xml_utf8_decode(attributes[1], strlen(attributes[1]), &val_len, parser->target_encoding);
00931                             
00932                             add_assoc_stringl(atr,att,val,val_len,0);
00933 
00934                             atcnt++;
00935                             attributes += 2;
00936 
00937                             efree(att);
00938                      }
00939 
00940                      if (atcnt) {
00941                             zend_hash_add(Z_ARRVAL_P(tag),"attributes",sizeof("attributes"),&atr,sizeof(zval*),NULL);
00942                      } else {
00943                             zval_ptr_dtor(&atr);
00944                      }
00945 
00946                      zend_hash_next_index_insert(Z_ARRVAL_P(parser->data),&tag,sizeof(zval*),(void *) &parser->ctag);
00947               }
00948 
00949               efree(tag_name);
00950        }
00951 }
00952 /* }}} */
00953 
00954 /* {{{ _xml_endElementHandler() */
00955 void _xml_endElementHandler(void *userData, const XML_Char *name)
00956 {
00957        xml_parser *parser = (xml_parser *)userData;
00958        char *tag_name;
00959 
00960        if (parser) {
00961               zval *retval, *args[2];
00962 
00963               tag_name = _xml_decode_tag(parser, name);
00964 
00965               if (parser->endElementHandler) {
00966                      args[0] = _xml_resource_zval(parser->index);
00967                      args[1] = _xml_string_zval(((char *) tag_name) + parser->toffset);
00968 
00969                      if ((retval = xml_call_handler(parser, parser->endElementHandler, parser->endElementPtr, 2, args))) {
00970                             zval_ptr_dtor(&retval);
00971                      }
00972               } 
00973 
00974               if (parser->data) {
00975                      zval *tag;
00976 
00977                      if (parser->lastwasopen) {
00978                             add_assoc_string(*(parser->ctag),"type","complete",1);
00979                      } else {
00980                             MAKE_STD_ZVAL(tag);
00981 
00982                             array_init(tag);
00983                               
00984                             _xml_add_to_info(parser,((char *) tag_name) + parser->toffset);
00985 
00986                             add_assoc_string(tag,"tag",((char *) tag_name) + parser->toffset,1); /* cast to avoid gcc-warning */
00987                             add_assoc_string(tag,"type","close",1);
00988                             add_assoc_long(tag,"level",parser->level);
00989                               
00990                             zend_hash_next_index_insert(Z_ARRVAL_P(parser->data),&tag,sizeof(zval*),NULL);
00991                      }
00992 
00993                      parser->lastwasopen = 0;
00994               }
00995 
00996               efree(tag_name);
00997 
00998               if (parser->ltags) {
00999                      efree(parser->ltags[parser->level-1]);
01000               }
01001 
01002               parser->level--;
01003        }
01004 }
01005 /* }}} */
01006 
01007 /* {{{ _xml_characterDataHandler() */
01008 void _xml_characterDataHandler(void *userData, const XML_Char *s, int len)
01009 {
01010        xml_parser *parser = (xml_parser *)userData;
01011 
01012        if (parser) {
01013               zval *retval, *args[2];
01014 
01015               if (parser->characterDataHandler) {
01016                      args[0] = _xml_resource_zval(parser->index);
01017                      args[1] = _xml_xmlchar_zval(s, len, parser->target_encoding);
01018                      if ((retval = xml_call_handler(parser, parser->characterDataHandler, parser->characterDataPtr, 2, args))) {
01019                             zval_ptr_dtor(&retval);
01020                      }
01021               } 
01022 
01023               if (parser->data) {
01024                      int i;
01025                      int doprint = 0;
01026 
01027                      char *decoded_value;
01028                      int decoded_len;
01029                      
01030                      decoded_value = xml_utf8_decode(s,len,&decoded_len,parser->target_encoding);
01031                      for (i = 0; i < decoded_len; i++) {
01032                             switch (decoded_value[i]) {
01033                             case ' ':
01034                             case '\t':
01035                             case '\n':
01036                                    continue;
01037                             default:
01038                                    doprint = 1;
01039                                    break;
01040                             }
01041                             if (doprint) {
01042                                    break;
01043                             }
01044                      }
01045                      if (doprint || (! parser->skipwhite)) {
01046                             if (parser->lastwasopen) {
01047                                    zval **myval;
01048                                    
01049                                    /* check if the current tag already has a value - if yes append to that! */
01050                                    if (zend_hash_find(Z_ARRVAL_PP(parser->ctag),"value",sizeof("value"),(void **) &myval) == SUCCESS) {
01051                                           int newlen = Z_STRLEN_PP(myval) + decoded_len;
01052                                           Z_STRVAL_PP(myval) = erealloc(Z_STRVAL_PP(myval),newlen+1);
01053                                           strncpy(Z_STRVAL_PP(myval) + Z_STRLEN_PP(myval), decoded_value, decoded_len + 1);
01054                                           Z_STRLEN_PP(myval) += decoded_len;
01055                                           efree(decoded_value);
01056                                    } else {
01057                                           add_assoc_string(*(parser->ctag),"value",decoded_value,0);
01058                                    }
01059                                    
01060                             } else {
01061                                    zval *tag;
01062                                    zval **curtag, **mytype, **myval;
01063                                    HashPosition hpos=NULL;
01064 
01065                                    zend_hash_internal_pointer_end_ex(Z_ARRVAL_P(parser->data), &hpos);
01066 
01067                                    if (hpos && (zend_hash_get_current_data_ex(Z_ARRVAL_P(parser->data), (void **) &curtag, &hpos) == SUCCESS)) {
01068                                           if (zend_hash_find(Z_ARRVAL_PP(curtag),"type",sizeof("type"),(void **) &mytype) == SUCCESS) {
01069                                                  if (!strcmp(Z_STRVAL_PP(mytype), "cdata")) {
01070                                                         if (zend_hash_find(Z_ARRVAL_PP(curtag),"value",sizeof("value"),(void **) &myval) == SUCCESS) {
01071                                                                int newlen = Z_STRLEN_PP(myval) + decoded_len;
01072                                                                Z_STRVAL_PP(myval) = erealloc(Z_STRVAL_PP(myval),newlen+1);
01073                                                                strncpy(Z_STRVAL_PP(myval) + Z_STRLEN_PP(myval), decoded_value, decoded_len + 1);
01074                                                                Z_STRLEN_PP(myval) += decoded_len;
01075                                                                efree(decoded_value);
01076                                                                return;
01077                                                         }
01078                                                  }
01079                                           }
01080                                    }
01081 
01082                                    MAKE_STD_ZVAL(tag);
01083                                    
01084                                    array_init(tag);
01085                                    
01086                                    _xml_add_to_info(parser,parser->ltags[parser->level-1] + parser->toffset);
01087 
01088                                    add_assoc_string(tag,"tag",parser->ltags[parser->level-1] + parser->toffset,1);
01089                                    add_assoc_string(tag,"value",decoded_value,0);
01090                                    add_assoc_string(tag,"type","cdata",1);
01091                                    add_assoc_long(tag,"level",parser->level);
01092 
01093                                    zend_hash_next_index_insert(Z_ARRVAL_P(parser->data),&tag,sizeof(zval*),NULL);
01094                             }
01095                      } else {
01096                             efree(decoded_value);
01097                      }
01098               }
01099        }
01100 }
01101 /* }}} */
01102 
01103 /* {{{ _xml_processingInstructionHandler() */
01104 void _xml_processingInstructionHandler(void *userData, const XML_Char *target, const XML_Char *data)
01105 {
01106        xml_parser *parser = (xml_parser *)userData;
01107 
01108        if (parser && parser->processingInstructionHandler) {
01109               zval *retval, *args[3];
01110 
01111               args[0] = _xml_resource_zval(parser->index);
01112               args[1] = _xml_xmlchar_zval(target, 0, parser->target_encoding);
01113               args[2] = _xml_xmlchar_zval(data, 0, parser->target_encoding);
01114               if ((retval = xml_call_handler(parser, parser->processingInstructionHandler, parser->processingInstructionPtr, 3, args))) {
01115                      zval_ptr_dtor(&retval);
01116               }
01117        }
01118 }
01119 /* }}} */
01120 
01121 /* {{{ _xml_defaultHandler() */
01122 void _xml_defaultHandler(void *userData, const XML_Char *s, int len)
01123 {
01124        xml_parser *parser = (xml_parser *)userData;
01125 
01126        if (parser && parser->defaultHandler) {
01127               zval *retval, *args[2];
01128 
01129               args[0] = _xml_resource_zval(parser->index);
01130               args[1] = _xml_xmlchar_zval(s, len, parser->target_encoding);
01131               if ((retval = xml_call_handler(parser, parser->defaultHandler, parser->defaultPtr, 2, args))) {
01132                      zval_ptr_dtor(&retval);
01133               }
01134        }
01135 }
01136 /* }}} */
01137 
01138 /* {{{ _xml_unparsedEntityDeclHandler() */
01139 void _xml_unparsedEntityDeclHandler(void *userData, 
01140                                                                        const XML_Char *entityName, 
01141                                                                        const XML_Char *base,
01142                                                                        const XML_Char *systemId,
01143                                                                        const XML_Char *publicId,
01144                                                                        const XML_Char *notationName)
01145 {
01146        xml_parser *parser = (xml_parser *)userData;
01147 
01148        if (parser && parser->unparsedEntityDeclHandler) {
01149               zval *retval, *args[6];
01150 
01151               args[0] = _xml_resource_zval(parser->index);
01152               args[1] = _xml_xmlchar_zval(entityName, 0, parser->target_encoding);
01153               args[2] = _xml_xmlchar_zval(base, 0, parser->target_encoding);
01154               args[3] = _xml_xmlchar_zval(systemId, 0, parser->target_encoding);
01155               args[4] = _xml_xmlchar_zval(publicId, 0, parser->target_encoding);
01156               args[5] = _xml_xmlchar_zval(notationName, 0, parser->target_encoding);
01157               if ((retval = xml_call_handler(parser, parser->unparsedEntityDeclHandler, parser->unparsedEntityDeclPtr, 6, args))) {
01158                      zval_ptr_dtor(&retval);
01159               }
01160        }
01161 }
01162 /* }}} */
01163 
01164 /* {{{ _xml_notationDeclHandler() */
01165 void _xml_notationDeclHandler(void *userData,
01166                                                    const XML_Char *notationName,
01167                                                    const XML_Char *base,
01168                                                    const XML_Char *systemId,
01169                                                    const XML_Char *publicId)
01170 {
01171        xml_parser *parser = (xml_parser *)userData;
01172 
01173        if (parser && parser->notationDeclHandler) {
01174               zval *retval, *args[5];
01175 
01176               args[0] = _xml_resource_zval(parser->index);
01177               args[1] = _xml_xmlchar_zval(notationName, 0, parser->target_encoding);
01178               args[2] = _xml_xmlchar_zval(base, 0, parser->target_encoding);
01179               args[3] = _xml_xmlchar_zval(systemId, 0, parser->target_encoding);
01180               args[4] = _xml_xmlchar_zval(publicId, 0, parser->target_encoding);
01181               if ((retval = xml_call_handler(parser, parser->notationDeclHandler, parser->notationDeclPtr, 5, args))) {
01182                      zval_ptr_dtor(&retval);
01183               }
01184        }
01185 }
01186 /* }}} */
01187 
01188 /* {{{ _xml_externalEntityRefHandler() */
01189 int _xml_externalEntityRefHandler(XML_Parser parserPtr,
01190                                                            const XML_Char *openEntityNames,
01191                                                            const XML_Char *base,
01192                                                            const XML_Char *systemId,
01193                                                            const XML_Char *publicId)
01194 {
01195        xml_parser *parser = XML_GetUserData(parserPtr);
01196        int ret = 0; /* abort if no handler is set (should be configurable?) */
01197 
01198        if (parser && parser->externalEntityRefHandler) {
01199               zval *retval, *args[5];
01200 
01201               args[0] = _xml_resource_zval(parser->index);
01202               args[1] = _xml_xmlchar_zval(openEntityNames, 0, parser->target_encoding);
01203               args[2] = _xml_xmlchar_zval(base, 0, parser->target_encoding);
01204               args[3] = _xml_xmlchar_zval(systemId, 0, parser->target_encoding);
01205               args[4] = _xml_xmlchar_zval(publicId, 0, parser->target_encoding);
01206               if ((retval = xml_call_handler(parser, parser->externalEntityRefHandler, parser->externalEntityRefPtr, 5, args))) {
01207                      convert_to_long(retval);
01208                      ret = Z_LVAL_P(retval);
01209                      efree(retval);
01210               } else {
01211                      ret = 0;
01212               }
01213        }
01214        return ret;
01215 }
01216 /* }}} */
01217 
01218 /* {{{ _xml_startNamespaceDeclHandler() */
01219 void _xml_startNamespaceDeclHandler(void *userData,const XML_Char *prefix, const XML_Char *uri)
01220 {
01221        xml_parser *parser = (xml_parser *)userData;
01222 
01223        if (parser && parser->startNamespaceDeclHandler) {
01224               zval *retval, *args[3];
01225 
01226               args[0] = _xml_resource_zval(parser->index);
01227               args[1] = _xml_xmlchar_zval(prefix, 0, parser->target_encoding);
01228               args[2] = _xml_xmlchar_zval(uri, 0, parser->target_encoding);
01229               if ((retval = xml_call_handler(parser, parser->startNamespaceDeclHandler, parser->startNamespaceDeclPtr, 3, args))) {
01230                      zval_ptr_dtor(&retval);
01231               }
01232        }
01233 }
01234 /* }}} */
01235 
01236 /* {{{ _xml_endNamespaceDeclHandler() */
01237 void _xml_endNamespaceDeclHandler(void *userData, const XML_Char *prefix)
01238 {
01239        xml_parser *parser = (xml_parser *)userData;
01240 
01241        if (parser && parser->endNamespaceDeclHandler) {
01242               zval *retval, *args[2];
01243 
01244               args[0] = _xml_resource_zval(parser->index);
01245               args[1] = _xml_xmlchar_zval(prefix, 0, parser->target_encoding);
01246               if ((retval = xml_call_handler(parser, parser->endNamespaceDeclHandler, parser->endNamespaceDeclPtr, 2, args))) {
01247                      zval_ptr_dtor(&retval);
01248               }
01249        }
01250 }
01251 /* }}} */
01252 
01253 /************************* EXTENSION FUNCTIONS *************************/
01254 
01255 static void php_xml_parser_create_impl(INTERNAL_FUNCTION_PARAMETERS, int ns_support) /* {{{ */
01256 {
01257        xml_parser *parser;
01258        int auto_detect = 0;
01259 
01260        char *encoding_param = NULL;
01261        int encoding_param_len = 0;
01262 
01263        char *ns_param = NULL;
01264        int ns_param_len = 0;
01265        
01266        XML_Char *encoding;
01267        
01268        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, (ns_support ? "|ss": "|s"), &encoding_param, &encoding_param_len, &ns_param, &ns_param_len) == FAILURE) {
01269               RETURN_FALSE;
01270        }
01271 
01272        if (encoding_param != NULL) {
01273               /* The supported encoding types are hardcoded here because
01274                * we are limited to the encodings supported by expat/xmltok.
01275                */
01276               if (encoding_param_len == 0) {
01277                      encoding = XML(default_encoding);
01278                      auto_detect = 1;
01279               } else if (strcasecmp(encoding_param, "ISO-8859-1") == 0) {
01280                      encoding = "ISO-8859-1";
01281               } else if (strcasecmp(encoding_param, "UTF-8") == 0) {
01282                      encoding = "UTF-8";
01283               } else if (strcasecmp(encoding_param, "US-ASCII") == 0) {
01284                      encoding = "US-ASCII";
01285               } else {
01286                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "unsupported source encoding \"%s\"", encoding_param);
01287                      RETURN_FALSE;
01288               }
01289        } else {
01290               encoding = XML(default_encoding);
01291        }
01292 
01293        if (ns_support && ns_param == NULL){
01294               ns_param = ":";
01295        }
01296 
01297        parser = ecalloc(1, sizeof(xml_parser));
01298        parser->parser = XML_ParserCreate_MM((auto_detect ? NULL : encoding),
01299                                          &php_xml_mem_hdlrs, ns_param);
01300 
01301        parser->target_encoding = encoding;
01302        parser->case_folding = 1;
01303        parser->object = NULL;
01304        parser->isparsing = 0;
01305 
01306        XML_SetUserData(parser->parser, parser);
01307 
01308        ZEND_REGISTER_RESOURCE(return_value, parser,le_xml_parser);
01309        parser->index = Z_LVAL_P(return_value);
01310 }
01311 /* }}} */
01312 
01313 /* {{{ proto resource xml_parser_create([string encoding]) 
01314    Create an XML parser */
01315 PHP_FUNCTION(xml_parser_create)
01316 {
01317        php_xml_parser_create_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);      
01318 }
01319 /* }}} */
01320 
01321 /* {{{ proto resource xml_parser_create_ns([string encoding [, string sep]]) 
01322    Create an XML parser */
01323 PHP_FUNCTION(xml_parser_create_ns)
01324 {
01325        php_xml_parser_create_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
01326 }
01327 /* }}} */
01328 
01329 /* {{{ proto int xml_set_object(resource parser, object &obj) 
01330    Set up object which should be used for callbacks */
01331 PHP_FUNCTION(xml_set_object)
01332 {
01333        xml_parser *parser;
01334        zval *pind, *mythis;
01335 
01336        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ro", &pind, &mythis) == FAILURE) {
01337               return;
01338        }
01339 
01340        ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
01341 
01342        /* please leave this commented - or ask thies@thieso.net before doing it (again) */
01343        if (parser->object) {
01344               zval_ptr_dtor(&parser->object);
01345        }
01346 
01347        /* please leave this commented - or ask thies@thieso.net before doing it (again) */
01348 /* #ifdef ZEND_ENGINE_2
01349        zval_add_ref(&parser->object); 
01350 #endif */
01351 
01352        ALLOC_ZVAL(parser->object);
01353        MAKE_COPY_ZVAL(&mythis, parser->object);
01354 
01355        RETVAL_TRUE;
01356 }
01357 /* }}} */
01358 
01359 /* {{{ proto int xml_set_element_handler(resource parser, string shdl, string ehdl) 
01360    Set up start and end element handlers */
01361 PHP_FUNCTION(xml_set_element_handler)
01362 {
01363        xml_parser *parser;
01364        zval *pind, **shdl, **ehdl;
01365 
01366        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZZ", &pind, &shdl, &ehdl) == FAILURE) {
01367               return;
01368        }
01369 
01370        ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
01371 
01372        xml_set_handler(&parser->startElementHandler, shdl);
01373        xml_set_handler(&parser->endElementHandler, ehdl);
01374        XML_SetElementHandler(parser->parser, _xml_startElementHandler, _xml_endElementHandler);
01375        RETVAL_TRUE;
01376 }
01377 /* }}} */
01378 
01379 /* {{{ proto int xml_set_character_data_handler(resource parser, string hdl) 
01380    Set up character data handler */
01381 PHP_FUNCTION(xml_set_character_data_handler)
01382 {
01383        xml_parser *parser;
01384        zval *pind, **hdl;
01385 
01386        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pind, &hdl) == FAILURE) {
01387               return;
01388        }
01389 
01390        ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
01391 
01392        xml_set_handler(&parser->characterDataHandler, hdl);
01393        XML_SetCharacterDataHandler(parser->parser, _xml_characterDataHandler);
01394        RETVAL_TRUE;
01395 }
01396 /* }}} */
01397 
01398 /* {{{ proto int xml_set_processing_instruction_handler(resource parser, string hdl) 
01399    Set up processing instruction (PI) handler */
01400 PHP_FUNCTION(xml_set_processing_instruction_handler)
01401 {
01402        xml_parser *parser;
01403        zval *pind, **hdl;
01404 
01405        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pind, &hdl) == FAILURE) {
01406               return;
01407        }
01408 
01409        ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
01410 
01411        xml_set_handler(&parser->processingInstructionHandler, hdl);
01412        XML_SetProcessingInstructionHandler(parser->parser, _xml_processingInstructionHandler);
01413        RETVAL_TRUE;
01414 }
01415 /* }}} */
01416 
01417 /* {{{ proto int xml_set_default_handler(resource parser, string hdl) 
01418    Set up default handler */
01419 PHP_FUNCTION(xml_set_default_handler)
01420 {
01421        xml_parser *parser;
01422        zval *pind, **hdl;
01423 
01424        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pind, &hdl) == FAILURE) {
01425               return;
01426        }
01427        ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
01428 
01429        xml_set_handler(&parser->defaultHandler, hdl);
01430        XML_SetDefaultHandler(parser->parser, _xml_defaultHandler);
01431        RETVAL_TRUE;
01432 }
01433 /* }}} */
01434 
01435 /* {{{ proto int xml_set_unparsed_entity_decl_handler(resource parser, string hdl) 
01436    Set up unparsed entity declaration handler */
01437 PHP_FUNCTION(xml_set_unparsed_entity_decl_handler)
01438 {
01439        xml_parser *parser;
01440        zval *pind, **hdl;
01441 
01442        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pind, &hdl) == FAILURE) {
01443               return;
01444        }
01445 
01446        ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
01447 
01448        xml_set_handler(&parser->unparsedEntityDeclHandler, hdl);
01449        XML_SetUnparsedEntityDeclHandler(parser->parser, _xml_unparsedEntityDeclHandler);
01450        RETVAL_TRUE;
01451 }
01452 /* }}} */
01453 
01454 /* {{{ proto int xml_set_notation_decl_handler(resource parser, string hdl) 
01455    Set up notation declaration handler */
01456 PHP_FUNCTION(xml_set_notation_decl_handler)
01457 {
01458        xml_parser *parser;
01459        zval *pind, **hdl;
01460 
01461        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pind, &hdl) == FAILURE) {
01462               return;
01463        }
01464        ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
01465 
01466        xml_set_handler(&parser->notationDeclHandler, hdl);
01467        XML_SetNotationDeclHandler(parser->parser, _xml_notationDeclHandler);
01468        RETVAL_TRUE;
01469 }
01470 /* }}} */
01471 
01472 /* {{{ proto int xml_set_external_entity_ref_handler(resource parser, string hdl) 
01473    Set up external entity reference handler */
01474 PHP_FUNCTION(xml_set_external_entity_ref_handler)
01475 {
01476        xml_parser *parser;
01477        zval *pind, **hdl;
01478 
01479        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pind, &hdl) == FAILURE) {
01480               return;
01481        }
01482        ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
01483 
01484        xml_set_handler(&parser->externalEntityRefHandler, hdl);
01485        XML_SetExternalEntityRefHandler(parser->parser, (void *) _xml_externalEntityRefHandler);
01486        RETVAL_TRUE;
01487 }
01488 /* }}} */
01489 
01490 /* {{{ proto int xml_set_start_namespace_decl_handler(resource parser, string hdl) 
01491    Set up character data handler */
01492 PHP_FUNCTION(xml_set_start_namespace_decl_handler)
01493 {
01494        xml_parser *parser;
01495        zval *pind, **hdl;
01496 
01497        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pind, &hdl) == FAILURE) {
01498               return;
01499        }
01500 
01501        ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
01502 
01503        xml_set_handler(&parser->startNamespaceDeclHandler, hdl);
01504        XML_SetStartNamespaceDeclHandler(parser->parser, _xml_startNamespaceDeclHandler);
01505        RETVAL_TRUE;
01506 }
01507 /* }}} */
01508 
01509 /* {{{ proto int xml_set_end_namespace_decl_handler(resource parser, string hdl) 
01510    Set up character data handler */
01511 PHP_FUNCTION(xml_set_end_namespace_decl_handler)
01512 {
01513        xml_parser *parser;
01514        zval *pind, **hdl;
01515 
01516        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pind, &hdl) == FAILURE) {
01517               return;
01518        }
01519 
01520        ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
01521 
01522        xml_set_handler(&parser->endNamespaceDeclHandler, hdl);
01523        XML_SetEndNamespaceDeclHandler(parser->parser, _xml_endNamespaceDeclHandler);
01524        RETVAL_TRUE;
01525 }
01526 /* }}} */
01527 
01528 /* {{{ proto int xml_parse(resource parser, string data [, int isFinal]) 
01529    Start parsing an XML document */
01530 PHP_FUNCTION(xml_parse)
01531 {
01532        xml_parser *parser;
01533        zval *pind;
01534        char *data;
01535        int data_len, ret;
01536        long isFinal = 0;
01537 
01538        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &pind, &data, &data_len, &isFinal) == FAILURE) {
01539               return;
01540        }
01541        ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
01542 
01543        parser->isparsing = 1;
01544        ret = XML_Parse(parser->parser, data, data_len, isFinal);
01545        parser->isparsing = 0;
01546        RETVAL_LONG(ret);
01547 }
01548 
01549 /* }}} */
01550 
01551 /* {{{ proto int xml_parse_into_struct(resource parser, string data, array &values [, array &index ])
01552    Parsing a XML document */
01553 
01554 PHP_FUNCTION(xml_parse_into_struct)
01555 {
01556        xml_parser *parser;
01557        zval *pind, **xdata, **info = NULL;
01558        char *data;
01559        int data_len, ret;
01560 
01561        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsZ|Z", &pind, &data, &data_len, &xdata, &info) == FAILURE) {
01562               return;
01563        }
01564        
01565        if (info) {   
01566               zval_dtor(*info);
01567               array_init(*info);
01568        }
01569 
01570        ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
01571 
01572        zval_dtor(*xdata);
01573        array_init(*xdata);
01574 
01575        parser->data = *xdata;
01576        
01577        if (info) {
01578               parser->info = *info;
01579        }
01580        
01581        parser->level = 0;
01582        parser->ltags = safe_emalloc(XML_MAXLEVEL, sizeof(char *), 0);
01583 
01584        XML_SetDefaultHandler(parser->parser, _xml_defaultHandler);
01585        XML_SetElementHandler(parser->parser, _xml_startElementHandler, _xml_endElementHandler);
01586        XML_SetCharacterDataHandler(parser->parser, _xml_characterDataHandler);
01587 
01588        parser->isparsing = 1;
01589        ret = XML_Parse(parser->parser, data, data_len, 1);
01590        parser->isparsing = 0;
01591 
01592        RETVAL_LONG(ret);
01593 }
01594 /* }}} */
01595 
01596 /* {{{ proto int xml_get_error_code(resource parser) 
01597    Get XML parser error code */
01598 PHP_FUNCTION(xml_get_error_code)
01599 {
01600        xml_parser *parser;
01601        zval *pind;
01602 
01603        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) {
01604               return;
01605        }
01606        ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
01607 
01608        RETVAL_LONG((long)XML_GetErrorCode(parser->parser));
01609 }
01610 /* }}} */
01611 
01612 /* {{{ proto string xml_error_string(int code)
01613    Get XML parser error string */
01614 PHP_FUNCTION(xml_error_string)
01615 {
01616        long code;
01617        char *str;
01618 
01619        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code) == FAILURE) {
01620               return;
01621        }
01622 
01623        str = (char *)XML_ErrorString((int)code);
01624        if (str) {
01625               RETVAL_STRING(str, 1);
01626        }
01627 }
01628 /* }}} */
01629 
01630 /* {{{ proto int xml_get_current_line_number(resource parser) 
01631    Get current line number for an XML parser */
01632 PHP_FUNCTION(xml_get_current_line_number)
01633 {
01634        xml_parser *parser;
01635        zval *pind;
01636 
01637        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) {
01638               return;
01639        }
01640        ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
01641 
01642        RETVAL_LONG(XML_GetCurrentLineNumber(parser->parser));
01643 }
01644 /* }}} */
01645 
01646 /* {{{ proto int xml_get_current_column_number(resource parser)
01647    Get current column number for an XML parser */
01648 PHP_FUNCTION(xml_get_current_column_number)
01649 {
01650        xml_parser *parser;
01651        zval *pind;
01652 
01653        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) {
01654               return;
01655        }
01656        ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
01657 
01658        RETVAL_LONG(XML_GetCurrentColumnNumber(parser->parser));
01659 }
01660 /* }}} */
01661 
01662 /* {{{ proto int xml_get_current_byte_index(resource parser) 
01663    Get current byte index for an XML parser */
01664 PHP_FUNCTION(xml_get_current_byte_index)
01665 {
01666        xml_parser *parser;
01667        zval *pind;
01668 
01669        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) {
01670               return;
01671        }
01672        ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
01673 
01674        RETVAL_LONG(XML_GetCurrentByteIndex(parser->parser));
01675 }
01676 /* }}} */
01677 
01678 /* {{{ proto int xml_parser_free(resource parser) 
01679    Free an XML parser */
01680 PHP_FUNCTION(xml_parser_free)
01681 {
01682        zval *pind;
01683        xml_parser *parser;
01684 
01685        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pind) == FAILURE) {
01686               return;
01687        }
01688 
01689        ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
01690 
01691        if (parser->isparsing == 1) {
01692               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parser cannot be freed while it is parsing.");
01693               RETURN_FALSE;
01694        }
01695 
01696        if (zend_list_delete(parser->index) == FAILURE) {
01697               RETURN_FALSE;
01698        }
01699 
01700        RETVAL_TRUE;
01701 }
01702 /* }}} */
01703 
01704 /* {{{ proto int xml_parser_set_option(resource parser, int option, mixed value) 
01705    Set options in an XML parser */
01706 PHP_FUNCTION(xml_parser_set_option)
01707 {
01708        xml_parser *parser;
01709        zval *pind, **val;
01710        long opt;
01711 
01712        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlZ", &pind, &opt, &val) == FAILURE) {
01713               return;
01714        }
01715        ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
01716 
01717        switch (opt) {
01718               case PHP_XML_OPTION_CASE_FOLDING:
01719                      convert_to_long_ex(val);
01720                      parser->case_folding = Z_LVAL_PP(val);
01721                      break;
01722               case PHP_XML_OPTION_SKIP_TAGSTART:
01723                      convert_to_long_ex(val);
01724                      parser->toffset = Z_LVAL_PP(val);
01725                      break;
01726               case PHP_XML_OPTION_SKIP_WHITE:
01727                      convert_to_long_ex(val);
01728                      parser->skipwhite = Z_LVAL_PP(val);
01729                      break;
01730               case PHP_XML_OPTION_TARGET_ENCODING: {
01731                      xml_encoding *enc;
01732                      convert_to_string_ex(val);
01733                      enc = xml_get_encoding(Z_STRVAL_PP(val));
01734                      if (enc == NULL) {
01735                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported target encoding \"%s\"", Z_STRVAL_PP(val));
01736                             RETURN_FALSE;
01737                      }
01738                      parser->target_encoding = enc->name;
01739                      break;
01740               }
01741               default:
01742                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown option");
01743                      RETURN_FALSE;
01744                      break;
01745        }
01746        RETVAL_TRUE;
01747 }
01748 /* }}} */
01749 
01750 /* {{{ proto int xml_parser_get_option(resource parser, int option) 
01751    Get options from an XML parser */
01752 PHP_FUNCTION(xml_parser_get_option)
01753 {
01754        xml_parser *parser;
01755        zval *pind;
01756        long opt;
01757 
01758        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &pind, &opt) == FAILURE) {
01759               return;
01760        }
01761        ZEND_FETCH_RESOURCE(parser,xml_parser *, &pind, -1, "XML Parser", le_xml_parser);
01762 
01763        switch (opt) {
01764               case PHP_XML_OPTION_CASE_FOLDING:
01765                      RETURN_LONG(parser->case_folding);
01766                      break;
01767               case PHP_XML_OPTION_TARGET_ENCODING:
01768                      RETURN_STRING(parser->target_encoding, 1);
01769                      break;
01770               default:
01771                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown option");
01772                      RETURN_FALSE;
01773                      break;
01774        }
01775 
01776        RETVAL_FALSE; /* never reached */
01777 }
01778 /* }}} */
01779 
01780 /* {{{ proto string utf8_encode(string data) 
01781    Encodes an ISO-8859-1 string to UTF-8 */
01782 PHP_FUNCTION(utf8_encode)
01783 {
01784        char *arg;
01785        XML_Char *encoded;
01786        int arg_len, len;
01787 
01788        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
01789               return;
01790        }
01791 
01792        encoded = xml_utf8_encode(arg, arg_len, &len, "ISO-8859-1");
01793        if (encoded == NULL) {
01794               RETURN_FALSE;
01795        }
01796        RETVAL_STRINGL(encoded, len, 0);
01797 }
01798 /* }}} */
01799 
01800 /* {{{ proto string utf8_decode(string data) 
01801    Converts a UTF-8 encoded string to ISO-8859-1 */
01802 PHP_FUNCTION(utf8_decode)
01803 {
01804        char *arg;
01805        XML_Char *decoded;
01806        int arg_len, len;
01807 
01808        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
01809               return;
01810        }
01811 
01812        decoded = xml_utf8_decode(arg, arg_len, &len, "ISO-8859-1");
01813        if (decoded == NULL) {
01814               RETURN_FALSE;
01815        }
01816        RETVAL_STRINGL(decoded, len, 0);
01817 }
01818 /* }}} */
01819 
01820 #endif
01821 
01822 /*
01823  * Local variables:
01824  * tab-width: 4
01825  * c-basic-offset: 4
01826  * End:
01827  * vim600: sw=4 ts=4 fdm=marker
01828  * vim<600: sw=4 ts=4
01829  */