Annotation of embedaddon/php/ext/xml/xml.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>