1/* 2 +----------------------------------------------------------------------+ 3 | PHP Version 5 | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 1997-2013 The PHP Group | 6 +----------------------------------------------------------------------+ 7 | This source file is subject to version 3.01 of the PHP license, | 8 | that is bundled with this package in the file LICENSE, and is | 9 | available through the world-wide-web at the following url: | 10 | http://www.php.net/license/3_01.txt | 11 | If you did not receive a copy of the PHP license and are unable to | 12 | obtain it through the world-wide-web, please send a note to | 13 | license@php.net so we can mail you a copy immediately. | 14 +----------------------------------------------------------------------+ 15 | Authors: Stig S�ther Bakken <ssb@php.net> | 16 | Thies C. Arntzen <thies@thieso.net> | 17 | Sterling Hughes <sterling@php.net> | 18 +----------------------------------------------------------------------+ 19 */ 20 21/* $Id$ */ 22 23#define IS_EXT_MODULE 24 25#ifdef HAVE_CONFIG_H 26#include "config.h" 27#endif 28 29#include "php.h" 30 31#define PHP_XML_INTERNAL 32#include "zend_variables.h" 33#include "ext/standard/php_string.h" 34#include "ext/standard/info.h" 35 36#if HAVE_XML 37 38#include "php_xml.h" 39# include "ext/standard/head.h" 40#ifdef LIBXML_EXPAT_COMPAT 41#include "ext/libxml/php_libxml.h" 42#endif 43 44/* Short-term TODO list: 45 * - Implement XML_ExternalEntityParserCreate() 46 * - XML_SetCommentHandler 47 * - XML_SetCdataSectionHandler 48 * - XML_SetParamEntityParsing 49 */ 50 51/* Long-term TODO list: 52 * - Fix the expat library so you can install your own memory manager 53 * functions 54 */ 55 56/* Known bugs: 57 * - Weird things happen with <![CDATA[]]> sections. 58 */ 59 60ZEND_DECLARE_MODULE_GLOBALS(xml) 61 62/* {{{ dynamically loadable module stuff */ 63#ifdef COMPILE_DL_XML 64ZEND_GET_MODULE(xml) 65#endif /* COMPILE_DL_XML */ 66/* }}} */ 67 68/* {{{ function prototypes */ 69PHP_MINIT_FUNCTION(xml); 70PHP_MINFO_FUNCTION(xml); 71static PHP_GINIT_FUNCTION(xml); 72 73static void xml_parser_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC); 74static void xml_set_handler(zval **, zval **); 75inline static unsigned short xml_encode_iso_8859_1(unsigned char); 76inline static char xml_decode_iso_8859_1(unsigned short); 77inline static unsigned short xml_encode_us_ascii(unsigned char); 78inline static char xml_decode_us_ascii(unsigned short); 79static zval *xml_call_handler(xml_parser *, zval *, zend_function *, int, zval **); 80static zval *_xml_xmlchar_zval(const XML_Char *, int, const XML_Char *); 81static int _xml_xmlcharlen(const XML_Char *); 82static void _xml_add_to_info(xml_parser *parser,char *name); 83inline static char *_xml_decode_tag(xml_parser *parser, const char *tag); 84 85void _xml_startElementHandler(void *, const XML_Char *, const XML_Char **); 86void _xml_endElementHandler(void *, const XML_Char *); 87void _xml_characterDataHandler(void *, const XML_Char *, int); 88void _xml_processingInstructionHandler(void *, const XML_Char *, const XML_Char *); 89void _xml_defaultHandler(void *, const XML_Char *, int); 90void _xml_unparsedEntityDeclHandler(void *, const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *); 91void _xml_notationDeclHandler(void *, const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *); 92int _xml_externalEntityRefHandler(XML_Parser, const XML_Char *, const XML_Char *, const XML_Char *, const XML_Char *); 93 94void _xml_startNamespaceDeclHandler(void *, const XML_Char *, const XML_Char *); 95void _xml_endNamespaceDeclHandler(void *, const XML_Char *); 96/* }}} */ 97 98/* {{{ extension definition structures */ 99ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_parser_create, 0, 0, 0) 100 ZEND_ARG_INFO(0, encoding) 101ZEND_END_ARG_INFO() 102 103ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_parser_create_ns, 0, 0, 0) 104 ZEND_ARG_INFO(0, encoding) 105 ZEND_ARG_INFO(0, sep) 106ZEND_END_ARG_INFO() 107 108ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_object, 0, 0, 2) 109 ZEND_ARG_INFO(0, parser) 110 ZEND_ARG_INFO(1, obj) 111ZEND_END_ARG_INFO() 112 113ZEND_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) 117ZEND_END_ARG_INFO() 118 119ZEND_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) 122ZEND_END_ARG_INFO() 123 124ZEND_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) 127ZEND_END_ARG_INFO() 128 129ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_set_default_handler, 0, 0, 2) 130 ZEND_ARG_INFO(0, parser) 131 ZEND_ARG_INFO(0, hdl) 132ZEND_END_ARG_INFO() 133 134ZEND_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) 137ZEND_END_ARG_INFO() 138 139ZEND_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) 142ZEND_END_ARG_INFO() 143 144ZEND_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) 147ZEND_END_ARG_INFO() 148 149ZEND_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) 152ZEND_END_ARG_INFO() 153 154ZEND_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) 157ZEND_END_ARG_INFO() 158 159ZEND_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) 163ZEND_END_ARG_INFO() 164 165ZEND_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) 170ZEND_END_ARG_INFO() 171 172ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_get_error_code, 0, 0, 1) 173 ZEND_ARG_INFO(0, parser) 174ZEND_END_ARG_INFO() 175 176ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_error_string, 0, 0, 1) 177 ZEND_ARG_INFO(0, code) 178ZEND_END_ARG_INFO() 179 180ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_get_current_line_number, 0, 0, 1) 181 ZEND_ARG_INFO(0, parser) 182ZEND_END_ARG_INFO() 183 184ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_get_current_column_number, 0, 0, 1) 185 ZEND_ARG_INFO(0, parser) 186ZEND_END_ARG_INFO() 187 188ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_get_current_byte_index, 0, 0, 1) 189 ZEND_ARG_INFO(0, parser) 190ZEND_END_ARG_INFO() 191 192ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_parser_free, 0, 0, 1) 193 ZEND_ARG_INFO(0, parser) 194ZEND_END_ARG_INFO() 195 196ZEND_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) 200ZEND_END_ARG_INFO() 201 202ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_parser_get_option, 0, 0, 2) 203 ZEND_ARG_INFO(0, parser) 204 ZEND_ARG_INFO(0, option) 205ZEND_END_ARG_INFO() 206 207ZEND_BEGIN_ARG_INFO_EX(arginfo_utf8_encode, 0, 0, 1) 208 ZEND_ARG_INFO(0, data) 209ZEND_END_ARG_INFO() 210 211ZEND_BEGIN_ARG_INFO_EX(arginfo_utf8_decode, 0, 0, 1) 212 ZEND_ARG_INFO(0, data) 213ZEND_END_ARG_INFO() 214 215const 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 244static const zend_module_dep xml_deps[] = { 245 ZEND_MOD_REQUIRED("libxml") 246 ZEND_MOD_END 247}; 248#endif 249 250zend_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 */ 275xml_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 282static XML_Memory_Handling_Suite php_xml_mem_hdlrs; 283 284/* True globals, no need for thread safety */ 285static int le_xml_parser; 286 287/* }}} */ 288 289/* {{{ startup, shutdown and info functions */ 290static PHP_GINIT_FUNCTION(xml) 291{ 292 xml_globals->default_encoding = "UTF-8"; 293} 294 295static void *php_xml_malloc_wrapper(size_t sz) 296{ 297 return emalloc(sz); 298} 299 300static void *php_xml_realloc_wrapper(void *ptr, size_t sz) 301{ 302 return erealloc(ptr, sz); 303} 304 305static void php_xml_free_wrapper(void *ptr) 306{ 307 if (ptr != NULL) { 308 efree(ptr); 309 } 310} 311 312PHP_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 360PHP_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 */ 375static 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 390static 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 402static 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() */ 421static 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() */ 479static 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() */ 503static 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() */ 566inline 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() */ 573inline 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() */ 580inline static unsigned short xml_encode_us_ascii(unsigned char c) 581{ 582 return (unsigned short)c; 583} 584/* }}} */ 585 586/* {{{ xml_decode_us_ascii() */ 587inline static char xml_decode_us_ascii(unsigned short c) 588{ 589 return (char)(c > 0x7f ? '?' : c); 590} 591/* }}} */ 592 593/* {{{ xml_get_encoding() */ 594static 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 */ 609PHPAPI 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 */ 675static 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 */ 764PHPAPI 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() */ 806static 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() */ 819PHPAPI 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 */ 832static 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() */ 855static 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() */ 871void _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() */ 955void _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() */ 1008void _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() */ 1104void _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() */ 1122void _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() */ 1139void _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() */ 1165void _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() */ 1189int _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() */ 1219void _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() */ 1237void _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 1255static 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 */ 1315PHP_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 */ 1323PHP_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 */ 1331PHP_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 */ 1361PHP_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 */ 1381PHP_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 */ 1400PHP_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 */ 1419PHP_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 */ 1437PHP_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 */ 1456PHP_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 */ 1474PHP_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 */ 1492PHP_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 */ 1511PHP_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 */ 1530PHP_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 1554PHP_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 */ 1598PHP_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 */ 1614PHP_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 */ 1632PHP_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 */ 1648PHP_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 */ 1664PHP_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 */ 1680PHP_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 */ 1706PHP_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 */ 1752PHP_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 */ 1782PHP_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 */ 1802PHP_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 */ 1830