1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 7                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 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   | Author: Rob Richards <rrichards@php.net>                             |
16   +----------------------------------------------------------------------+
17 */
18 
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22 
23 
24 #include "php.h"
25 #include "php_ini.h"
26 #include "ext/standard/info.h"
27 #include "php_xmlreader.h"
28 #ifdef HAVE_DOM
29 #include "ext/dom/xml_common.h"
30 #include "ext/dom/dom_ce.h"
31 #endif
32 #include <libxml/xmlreader.h>
33 #include <libxml/uri.h>
34 
35 zend_class_entry *xmlreader_class_entry;
36 
37 static zend_object_handlers xmlreader_object_handlers;
38 
39 static HashTable xmlreader_prop_handlers;
40 
41 typedef int (*xmlreader_read_int_t)(xmlTextReaderPtr reader);
42 typedef unsigned char *(*xmlreader_read_char_t)(xmlTextReaderPtr reader);
43 typedef const unsigned char *(*xmlreader_read_const_char_t)(xmlTextReaderPtr reader);
44 typedef int (*xmlreader_write_t)(xmlreader_object *obj, zval *newval);
45 
46 typedef unsigned char *(*xmlreader_read_one_char_t)(xmlTextReaderPtr reader, const unsigned char *);
47 
48 typedef struct _xmlreader_prop_handler {
49 	xmlreader_read_int_t read_int_func;
50 	xmlreader_read_const_char_t read_char_func;
51 	xmlreader_write_t write_func;
52 	int type;
53 } xmlreader_prop_handler;
54 
55 #define XMLREADER_LOAD_STRING 0
56 #define XMLREADER_LOAD_FILE 1
57 
58 /* {{{ xmlreader_register_prop_handler */
xmlreader_register_prop_handler(HashTable *prop_handler, char *name, xmlreader_read_int_t read_int_func, xmlreader_read_const_char_t read_char_func, int rettype)59 static void xmlreader_register_prop_handler(HashTable *prop_handler, char *name, xmlreader_read_int_t read_int_func, xmlreader_read_const_char_t read_char_func, int rettype)
60 {
61 	xmlreader_prop_handler hnd;
62 	zend_string *str;
63 
64 	hnd.read_char_func = read_char_func;
65 	hnd.read_int_func = read_int_func;
66 	hnd.type = rettype;
67 	str = zend_string_init_interned(name, strlen(name), 1);
68 	zend_hash_add_mem(prop_handler, str, &hnd, sizeof(xmlreader_prop_handler));
69 	zend_string_release_ex(str, 1);
70 }
71 /* }}} */
72 
73 /* {{{ xmlreader_property_reader */
xmlreader_property_reader(xmlreader_object *obj, xmlreader_prop_handler *hnd, zval *rv)74 static int xmlreader_property_reader(xmlreader_object *obj, xmlreader_prop_handler *hnd, zval *rv)
75 {
76 	const xmlChar *retchar = NULL;
77 	int retint = 0;
78 
79 	if (obj->ptr != NULL) {
80 		if (hnd->read_char_func) {
81 			retchar = hnd->read_char_func(obj->ptr);
82 		} else {
83 			if (hnd->read_int_func) {
84 				retint = hnd->read_int_func(obj->ptr);
85 				if (retint == -1) {
86 					php_error_docref(NULL, E_WARNING, "Internal libxml error returned");
87 					return FAILURE;
88 				}
89 			}
90 		}
91 	}
92 
93 	switch (hnd->type) {
94 		case IS_STRING:
95 			if (retchar) {
96 				ZVAL_STRING(rv, (char *) retchar);
97 			} else {
98 				ZVAL_EMPTY_STRING(rv);
99 			}
100 			break;
101 		/* this IS_FALSE actually means it's a BOOL type */
102 		case IS_FALSE:
103 			ZVAL_BOOL(rv, retint);
104 			break;
105 		case IS_LONG:
106 			ZVAL_LONG(rv, retint);
107 			break;
108 		default:
109 			ZVAL_NULL(rv);
110 	}
111 
112 	return SUCCESS;
113 }
114 /* }}} */
115 
116 /* {{{ xmlreader_get_property_ptr_ptr */
xmlreader_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot)117 zval *xmlreader_get_property_ptr_ptr(zval *object, zval *member, int type, void **cache_slot)
118 {
119 	xmlreader_object *obj;
120 	zval tmp_member;
121 	zval *retval = NULL;
122 	xmlreader_prop_handler *hnd = NULL;
123 
124  	if (Z_TYPE_P(member) != IS_STRING) {
125 		zend_string *str = zval_try_get_string_func(member);
126 		if (UNEXPECTED(!str)) {
127 			return NULL;
128 		}
129 		ZVAL_STR(&tmp_member, str);
130 		member = &tmp_member;
131 	}
132 
133 	obj = Z_XMLREADER_P(object);
134 
135 	if (obj->prop_handler != NULL) {
136 		hnd = zend_hash_find_ptr(obj->prop_handler, Z_STR_P(member));
137 	}
138 
139 	if (hnd == NULL) {
140 		retval = zend_std_get_property_ptr_ptr(object, member, type, cache_slot);
141 	}
142 
143 	if (member == &tmp_member) {
144 		zval_ptr_dtor_str(&tmp_member);
145 	}
146 
147 	return retval;
148 }
149 /* }}} */
150 
151 /* {{{ xmlreader_read_property */
xmlreader_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv)152 zval *xmlreader_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv)
153 {
154 	xmlreader_object *obj;
155 	zval tmp_member;
156 	zval *retval = NULL;
157 	xmlreader_prop_handler *hnd = NULL;
158 
159  	if (Z_TYPE_P(member) != IS_STRING) {
160 		zend_string *str = zval_try_get_string_func(member);
161 		if (UNEXPECTED(!str)) {
162 			return &EG(uninitialized_zval);
163 		}
164 		ZVAL_STR(&tmp_member, str);
165 		member = &tmp_member;
166 	}
167 
168 	obj = Z_XMLREADER_P(object);
169 
170 	if (obj->prop_handler != NULL) {
171 		hnd = zend_hash_find_ptr(obj->prop_handler, Z_STR_P(member));
172 	}
173 
174 	if (hnd != NULL) {
175 		if (xmlreader_property_reader(obj, hnd, rv) == FAILURE) {
176 			retval = &EG(uninitialized_zval);
177 		} else {
178 			retval = rv;
179 		}
180 	} else {
181 		retval = zend_std_read_property(object, member, type, cache_slot, rv);
182 	}
183 
184 	if (member == &tmp_member) {
185 		zval_ptr_dtor_str(&tmp_member);
186 	}
187 	return retval;
188 }
189 /* }}} */
190 
191 /* {{{ xmlreader_write_property */
xmlreader_write_property(zval *object, zval *member, zval *value, void **cache_slot)192 zval *xmlreader_write_property(zval *object, zval *member, zval *value, void **cache_slot)
193 {
194 	xmlreader_object *obj;
195 	zval tmp_member;
196 	xmlreader_prop_handler *hnd = NULL;
197 
198  	if (Z_TYPE_P(member) != IS_STRING) {
199 		zend_string *str = zval_try_get_string_func(member);
200 		if (UNEXPECTED(!str)) {
201 			return value;
202 		}
203 		ZVAL_STR(&tmp_member, str);
204 		member = &tmp_member;
205 	}
206 
207 	obj = Z_XMLREADER_P(object);
208 
209 	if (obj->prop_handler != NULL) {
210 		hnd = zend_hash_find_ptr(obj->prop_handler, Z_STR_P(member));
211 	}
212 	if (hnd != NULL) {
213 		php_error_docref(NULL, E_WARNING, "Cannot write to read-only property");
214 	} else {
215 		value = zend_std_write_property(object, member, value, cache_slot);
216 	}
217 
218 	if (member == &tmp_member) {
219 		zval_ptr_dtor_str(&tmp_member);
220 	}
221 
222 	return value;
223 }
224 /* }}} */
225 
226 /* {{{ _xmlreader_get_valid_file_path */
227 /* _xmlreader_get_valid_file_path and _xmlreader_get_relaxNG should be made a
228 	common function in libxml extension as code is common to a few xml extensions */
_xmlreader_get_valid_file_path(char *source, char *resolved_path, int resolved_path_len )229 char *_xmlreader_get_valid_file_path(char *source, char *resolved_path, int resolved_path_len ) {
230 	xmlURI *uri;
231 	xmlChar *escsource;
232 	char *file_dest;
233 	int isFileUri = 0;
234 
235 	uri = xmlCreateURI();
236 	escsource = xmlURIEscapeStr((xmlChar *)source, (xmlChar *)":");
237 	xmlParseURIReference(uri, (const char *)escsource);
238 	xmlFree(escsource);
239 
240 	if (uri->scheme != NULL) {
241 		/* absolute file uris - libxml only supports localhost or empty host */
242 		if (strncasecmp(source, "file:///",8) == 0) {
243 			isFileUri = 1;
244 #ifdef PHP_WIN32
245 			source += 8;
246 #else
247 			source += 7;
248 #endif
249 		} else if (strncasecmp(source, "file://localhost/",17) == 0) {
250 			isFileUri = 1;
251 #ifdef PHP_WIN32
252 			source += 17;
253 #else
254 			source += 16;
255 #endif
256 		}
257 	}
258 
259 	file_dest = source;
260 
261 	if ((uri->scheme == NULL || isFileUri)) {
262 		if (!VCWD_REALPATH(source, resolved_path) && !expand_filepath(source, resolved_path)) {
263 			xmlFreeURI(uri);
264 			return NULL;
265 		}
266 		file_dest = resolved_path;
267 	}
268 
269 	xmlFreeURI(uri);
270 
271 	return file_dest;
272 }
273 /* }}} */
274 
275 #ifdef LIBXML_SCHEMAS_ENABLED
276 /* {{{ _xmlreader_get_relaxNG */
_xmlreader_get_relaxNG(char *source, size_t source_len, size_t type, xmlRelaxNGValidityErrorFunc error_func, xmlRelaxNGValidityWarningFunc warn_func)277 static xmlRelaxNGPtr _xmlreader_get_relaxNG(char *source, size_t source_len, size_t type,
278 											xmlRelaxNGValidityErrorFunc error_func,
279 											xmlRelaxNGValidityWarningFunc warn_func)
280 {
281 	char *valid_file = NULL;
282 	xmlRelaxNGParserCtxtPtr parser = NULL;
283 	xmlRelaxNGPtr           sptr;
284 	char resolved_path[MAXPATHLEN + 1];
285 
286 	switch (type) {
287 	case XMLREADER_LOAD_FILE:
288 		valid_file = _xmlreader_get_valid_file_path(source, resolved_path, MAXPATHLEN );
289 		if (!valid_file) {
290 			return NULL;
291 		}
292 		parser = xmlRelaxNGNewParserCtxt(valid_file);
293 		break;
294 	case XMLREADER_LOAD_STRING:
295 		parser = xmlRelaxNGNewMemParserCtxt(source, source_len);
296 		/* If loading from memory, we need to set the base directory for the document
297 		   but it is not apparent how to do that for schema's */
298 		break;
299 	default:
300 		return NULL;
301 	}
302 
303 	if (parser == NULL) {
304 		return NULL;
305 	}
306 
307 	if (error_func || warn_func) {
308 		xmlRelaxNGSetParserErrors(parser,
309 			(xmlRelaxNGValidityErrorFunc) error_func,
310 			(xmlRelaxNGValidityWarningFunc) warn_func,
311 			parser);
312 	}
313 	sptr = xmlRelaxNGParse(parser);
314 	xmlRelaxNGFreeParserCtxt(parser);
315 
316 	return sptr;
317 }
318 /* }}} */
319 #endif
320 
321 static const zend_module_dep xmlreader_deps[] = {
322 	ZEND_MOD_REQUIRED("libxml")
323 	ZEND_MOD_END
324 };
325 
326 /* {{{ xmlreader_module_entry
327  */
328 zend_module_entry xmlreader_module_entry = {
329 	STANDARD_MODULE_HEADER_EX, NULL,
330 	xmlreader_deps,
331 	"xmlreader",
332 	NULL,
333 	PHP_MINIT(xmlreader),
334 	PHP_MSHUTDOWN(xmlreader),
335 	NULL,
336 	NULL,
337 	PHP_MINFO(xmlreader),
338 	PHP_XMLREADER_VERSION,
339 	STANDARD_MODULE_PROPERTIES
340 };
341 /* }}} */
342 
343 #ifdef COMPILE_DL_XMLREADER
ZEND_GET_MODULEnull344 ZEND_GET_MODULE(xmlreader)
345 #endif
346 
347 /* {{{ xmlreader_objects_clone */
348 void xmlreader_objects_clone(void *object, void **object_clone)
349 {
350 	/* TODO */
351 }
352 /* }}} */
353 
354 /* {{{ xmlreader_free_resources */
xmlreader_free_resources(xmlreader_object *intern)355 static void xmlreader_free_resources(xmlreader_object *intern) {
356 	if (intern) {
357 		if (intern->input) {
358 			xmlFreeParserInputBuffer(intern->input);
359 			intern->input = NULL;
360 		}
361 
362 		if (intern->ptr) {
363 			xmlFreeTextReader(intern->ptr);
364 			intern->ptr = NULL;
365 		}
366 #ifdef LIBXML_SCHEMAS_ENABLED
367 		if (intern->schema) {
368 			xmlRelaxNGFree((xmlRelaxNGPtr) intern->schema);
369 			intern->schema = NULL;
370 		}
371 #endif
372 	}
373 }
374 /* }}} */
375 
376 /* {{{ xmlreader_objects_free_storage */
xmlreader_objects_free_storage(zend_object *object)377 void xmlreader_objects_free_storage(zend_object *object)
378 {
379 	xmlreader_object *intern = php_xmlreader_fetch_object(object);
380 
381 	zend_object_std_dtor(&intern->std);
382 
383 	xmlreader_free_resources(intern);
384 }
385 /* }}} */
386 
387 /* {{{ xmlreader_objects_new */
xmlreader_objects_new(zend_class_entry *class_type)388 zend_object *xmlreader_objects_new(zend_class_entry *class_type)
389 {
390 	xmlreader_object *intern;
391 
392 	intern = zend_object_alloc(sizeof(xmlreader_object), class_type);
393 	zend_object_std_init(&intern->std, class_type);
394 	object_properties_init(&intern->std, class_type);
395 	intern->prop_handler = &xmlreader_prop_handlers;
396 	intern->std.handlers = &xmlreader_object_handlers;
397 
398 	return &intern->std;
399 }
400 /* }}} */
401 
402 /* {{{ php_xmlreader_string_arg */
php_xmlreader_string_arg(INTERNAL_FUNCTION_PARAMETERS, xmlreader_read_one_char_t internal_function)403 static void php_xmlreader_string_arg(INTERNAL_FUNCTION_PARAMETERS, xmlreader_read_one_char_t internal_function) {
404 	zval *id;
405 	size_t name_len = 0;
406 	char *retchar = NULL;
407 	xmlreader_object *intern;
408 	char *name;
409 
410 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
411 		return;
412 	}
413 
414 	if (!name_len) {
415 		php_error_docref(NULL, E_WARNING, "Argument cannot be an empty string");
416 		RETURN_FALSE;
417 	}
418 
419 	id = ZEND_THIS;
420 
421 	intern = Z_XMLREADER_P(id);
422 	if (intern && intern->ptr) {
423 		retchar = (char *)internal_function(intern->ptr, (const unsigned char *)name);
424 	}
425 	if (retchar) {
426 		RETVAL_STRING(retchar);
427 		xmlFree(retchar);
428 		return;
429 	} else {
430 		RETVAL_NULL();
431 	}
432 }
433 /* }}} */
434 
435 /* {{{ php_xmlreader_no_arg */
php_xmlreader_no_arg(INTERNAL_FUNCTION_PARAMETERS, xmlreader_read_int_t internal_function)436 static void php_xmlreader_no_arg(INTERNAL_FUNCTION_PARAMETERS, xmlreader_read_int_t internal_function) {
437 	zval *id;
438 	int retval;
439 	xmlreader_object *intern;
440 
441 	id = ZEND_THIS;
442 
443 	intern = Z_XMLREADER_P(id);
444 	if (intern && intern->ptr) {
445 		retval = internal_function(intern->ptr);
446 		if (retval == 1) {
447 			RETURN_TRUE;
448 		}
449 	}
450 
451 	RETURN_FALSE;
452 }
453 /* }}} */
454 
php_xmlreader_free_prop_handler(zval *el)455 static void php_xmlreader_free_prop_handler(zval *el) /* {{{ */ {
456 	pefree(Z_PTR_P(el), 1);
457 } /* }}} */
458 
459 /* {{{ php_xmlreader_no_arg_string */
php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAMETERS, xmlreader_read_char_t internal_function)460 static void php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAMETERS, xmlreader_read_char_t internal_function) {
461 	zval *id;
462 	char *retchar = NULL;
463 	xmlreader_object *intern;
464 
465 	id = ZEND_THIS;
466 
467 	intern = Z_XMLREADER_P(id);
468 	if (intern && intern->ptr) {
469 		retchar = (char *)internal_function(intern->ptr);
470 	}
471 	if (retchar) {
472 		RETVAL_STRING(retchar);
473 		xmlFree(retchar);
474 		return;
475 	} else {
476 		RETVAL_EMPTY_STRING();
477 	}
478 }
479 /* }}} */
480 
481 /* {{{ php_xmlreader_set_relaxng_schema */
php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAMETERS, int type)482 static void php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAMETERS, int type) {
483 #ifdef LIBXML_SCHEMAS_ENABLED
484 	zval *id;
485 	size_t source_len = 0;
486 	int retval = -1;
487 	xmlreader_object *intern;
488 	xmlRelaxNGPtr schema = NULL;
489 	char *source;
490 
491 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "p!", &source, &source_len) == FAILURE) {
492 		return;
493 	}
494 
495 	if (source != NULL && !source_len) {
496 		php_error_docref(NULL, E_WARNING, "Schema data source is required");
497 		RETURN_FALSE;
498 	}
499 
500 	id = ZEND_THIS;
501 
502 	intern = Z_XMLREADER_P(id);
503 	if (intern && intern->ptr) {
504 		if (source) {
505 			schema =  _xmlreader_get_relaxNG(source, source_len, type, NULL, NULL);
506 			if (schema) {
507 				retval = xmlTextReaderRelaxNGSetSchema(intern->ptr, schema);
508 			}
509 		} else {
510 			/* unset the associated relaxNG context and schema if one exists */
511 			retval = xmlTextReaderRelaxNGSetSchema(intern->ptr, NULL);
512 		}
513 
514 		if (retval == 0) {
515 			if (intern->schema) {
516 				xmlRelaxNGFree((xmlRelaxNGPtr) intern->schema);
517 			}
518 
519 			intern->schema = schema;
520 
521 			RETURN_TRUE;
522 		}
523 	}
524 
525 	php_error_docref(NULL, E_WARNING, "Unable to set schema. This must be set prior to reading or schema contains errors.");
526 
527 	RETURN_FALSE;
528 #else
529 	php_error_docref(NULL, E_WARNING, "No Schema support built into libxml.");
530 
531 	RETURN_FALSE;
532 #endif
533 }
534 /* }}} */
535 
536 /* {{{ proto bool XMLReader::close()
537 Closes xmlreader - current frees resources until xmlTextReaderClose is fixed in libxml */
PHP_METHODnull538 PHP_METHOD(xmlreader, close)
539 {
540 	zval *id;
541 	xmlreader_object *intern;
542 
543 	id = ZEND_THIS;
544 	intern = Z_XMLREADER_P(id);
545 	/* libxml is segfaulting in versions up to 2.6.8 using xmlTextReaderClose so for
546 	now we will free the whole reader when close is called as it would get rebuilt on
547 	a new load anyways */
548 	xmlreader_free_resources(intern);
549 
550 	RETURN_TRUE;
551 }
552 /* }}} */
553 
554 /* {{{ proto string XMLReader::getAttribute(string name)
555 Get value of an attribute from current element */
PHP_METHODnull556 PHP_METHOD(xmlreader, getAttribute)
557 {
558 	php_xmlreader_string_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderGetAttribute);
559 }
560 /* }}} */
561 
562 /* {{{ proto string XMLReader::getAttributeNo(int index)
563 Get value of an attribute at index from current element */
PHP_METHODnull564 PHP_METHOD(xmlreader, getAttributeNo)
565 {
566 	zval *id;
567 	zend_long attr_pos;
568 	char *retchar = NULL;
569 	xmlreader_object *intern;
570 
571 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &attr_pos) == FAILURE) {
572 		return;
573 	}
574 
575 	id = ZEND_THIS;
576 
577 	intern = Z_XMLREADER_P(id);
578 	if (intern && intern->ptr) {
579 		retchar = (char *)xmlTextReaderGetAttributeNo(intern->ptr, attr_pos);
580 	}
581 	if (retchar) {
582 		RETVAL_STRING(retchar);
583 		xmlFree(retchar);
584 	}
585 }
586 /* }}} */
587 
588 /* {{{ proto string XMLReader::getAttributeNs(string name, string namespaceURI)
589 Get value of a attribute via name and namespace from current element */
PHP_METHODnull590 PHP_METHOD(xmlreader, getAttributeNs)
591 {
592 	zval *id;
593 	size_t name_len = 0, ns_uri_len = 0;
594 	xmlreader_object *intern;
595 	char *name, *ns_uri, *retchar = NULL;
596 
597 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &name, &name_len, &ns_uri, &ns_uri_len) == FAILURE) {
598 		return;
599 	}
600 
601 	if (name_len == 0 || ns_uri_len == 0) {
602 		php_error_docref(NULL, E_WARNING, "Attribute Name and Namespace URI cannot be empty");
603 		RETURN_FALSE;
604 	}
605 
606 	id = ZEND_THIS;
607 
608 	intern = Z_XMLREADER_P(id);
609 	if (intern && intern->ptr) {
610 		retchar = (char *)xmlTextReaderGetAttributeNs(intern->ptr, (xmlChar *)name, (xmlChar *)ns_uri);
611 	}
612 	if (retchar) {
613 		RETVAL_STRING(retchar);
614 		xmlFree(retchar);
615 	}
616 }
617 /* }}} */
618 
619 /* {{{ proto bool XMLReader::getParserProperty(int property)
620 Indicates whether given property (one of the parser option constants) is set or not on parser */
PHP_METHODnull621 PHP_METHOD(xmlreader, getParserProperty)
622 {
623 	zval *id;
624 	zend_long property;
625 	int retval = -1;
626 	xmlreader_object *intern;
627 
628 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &property) == FAILURE) {
629 		return;
630 	}
631 
632 	id = ZEND_THIS;
633 
634 	intern = Z_XMLREADER_P(id);
635 	if (intern && intern->ptr) {
636 		retval = xmlTextReaderGetParserProp(intern->ptr,property);
637 	}
638 	if (retval == -1) {
639 		php_error_docref(NULL, E_WARNING, "Invalid parser property");
640 		RETURN_FALSE;
641 	}
642 
643 	RETURN_BOOL(retval);
644 }
645 /* }}} */
646 
647 /* {{{ proto bool XMLReader::isValid()
648 Returns boolean indicating if parsed document is valid or not.
649 Must set XMLREADER_LOADDTD or XMLREADER_VALIDATE parser option prior to the first call to read
650 or this method will always return FALSE */
PHP_METHODnull651 PHP_METHOD(xmlreader, isValid)
652 {
653 	php_xmlreader_no_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderIsValid);
654 }
655 /* }}} */
656 
657 /* {{{ proto string XMLReader::lookupNamespace(string prefix)
658 Return namespaceURI for associated prefix on current node */
PHP_METHODnull659 PHP_METHOD(xmlreader, lookupNamespace)
660 {
661 	php_xmlreader_string_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderLookupNamespace);
662 }
663 /* }}} */
664 
665 /* {{{ proto bool XMLReader::moveToAttribute(string name)
666 Positions reader at specified attribute - Returns TRUE on success and FALSE on failure */
PHP_METHODnull667 PHP_METHOD(xmlreader, moveToAttribute)
668 {
669 	zval *id;
670 	size_t name_len = 0;
671 	int retval;
672 	xmlreader_object *intern;
673 	char *name;
674 
675 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
676 		return;
677 	}
678 
679 	if (name_len == 0) {
680 		php_error_docref(NULL, E_WARNING, "Attribute Name is required");
681 		RETURN_FALSE;
682 	}
683 
684 	id = ZEND_THIS;
685 
686 	intern = Z_XMLREADER_P(id);
687 	if (intern && intern->ptr) {
688 		retval = xmlTextReaderMoveToAttribute(intern->ptr, (xmlChar *)name);
689 		if (retval == 1) {
690 			RETURN_TRUE;
691 		}
692 	}
693 
694 	RETURN_FALSE;
695 }
696 /* }}} */
697 
698 /* {{{ proto bool XMLReader::moveToAttributeNo(int index)
699 Positions reader at attribute at specified index.
700 Returns TRUE on success and FALSE on failure */
PHP_METHODnull701 PHP_METHOD(xmlreader, moveToAttributeNo)
702 {
703 	zval *id;
704 	zend_long attr_pos;
705 	int retval;
706 	xmlreader_object *intern;
707 
708 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &attr_pos) == FAILURE) {
709 		return;
710 	}
711 
712 	id = ZEND_THIS;
713 
714 	intern = Z_XMLREADER_P(id);
715 	if (intern && intern->ptr) {
716 		retval = xmlTextReaderMoveToAttributeNo(intern->ptr, attr_pos);
717 		if (retval == 1) {
718 			RETURN_TRUE;
719 		}
720 	}
721 
722 	RETURN_FALSE;
723 }
724 /* }}} */
725 
726 /* {{{ proto bool XMLReader::moveToAttributeNs(string name, string namespaceURI)
727 Positions reader at attribute spcified by name and namespaceURI.
728 Returns TRUE on success and FALSE on failure */
PHP_METHODnull729 PHP_METHOD(xmlreader, moveToAttributeNs)
730 {
731 	zval *id;
732 	size_t name_len=0, ns_uri_len=0;
733 	int retval;
734 	xmlreader_object *intern;
735 	char *name, *ns_uri;
736 
737 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &name, &name_len, &ns_uri, &ns_uri_len) == FAILURE) {
738 		return;
739 	}
740 
741 	if (name_len == 0 || ns_uri_len == 0) {
742 		php_error_docref(NULL, E_WARNING, "Attribute Name and Namespace URI cannot be empty");
743 		RETURN_FALSE;
744 	}
745 
746 	id = ZEND_THIS;
747 
748 	intern = Z_XMLREADER_P(id);
749 	if (intern && intern->ptr) {
750 		retval = xmlTextReaderMoveToAttributeNs(intern->ptr, (xmlChar *)name, (xmlChar *)ns_uri);
751 		if (retval == 1) {
752 			RETURN_TRUE;
753 		}
754 	}
755 
756 	RETURN_FALSE;
757 }
758 /* }}} */
759 
760 /* {{{ proto bool XMLReader::moveToElement()
761 Moves the position of the current instance to the node that contains the current Attribute node. */
PHP_METHODnull762 PHP_METHOD(xmlreader, moveToElement)
763 {
764 	php_xmlreader_no_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderMoveToElement);
765 }
766 /* }}} */
767 
768 /* {{{ proto bool XMLReader::moveToFirstAttribute()
769 Moves the position of the current instance to the first attribute associated with the current node. */
PHP_METHODnull770 PHP_METHOD(xmlreader, moveToFirstAttribute)
771 {
772 	php_xmlreader_no_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderMoveToFirstAttribute);
773 }
774 /* }}} */
775 
776 /* {{{ proto bool XMLReader::moveToNextAttribute()
777 Moves the position of the current instance to the next attribute associated with the current node. */
PHP_METHODnull778 PHP_METHOD(xmlreader, moveToNextAttribute)
779 {
780 	php_xmlreader_no_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderMoveToNextAttribute);
781 }
782 /* }}} */
783 
784 /* {{{ proto bool XMLReader::read()
785 Moves the position of the current instance to the next node in the stream. */
PHP_METHODnull786 PHP_METHOD(xmlreader, read)
787 {
788 	zval *id;
789 	int retval;
790 	xmlreader_object *intern;
791 
792 	id = ZEND_THIS;
793 	intern = Z_XMLREADER_P(id);
794 	if (intern != NULL && intern->ptr != NULL) {
795 		retval = xmlTextReaderRead(intern->ptr);
796 		if (retval == -1) {
797 			RETURN_FALSE;
798 		} else {
799 			RETURN_BOOL(retval);
800 		}
801 	}
802 
803 	php_error_docref(NULL, E_WARNING, "Load Data before trying to read");
804 	RETURN_FALSE;
805 }
806 /* }}} */
807 
808 /* {{{ proto bool XMLReader::next([string localname])
809 Moves the position of the current instance to the next node in the stream. */
PHP_METHODnull810 PHP_METHOD(xmlreader, next)
811 {
812 	zval *id;
813 	int retval;
814 	size_t name_len=0;
815 	xmlreader_object *intern;
816 	char *name = NULL;
817 
818 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &name, &name_len) == FAILURE) {
819 		return;
820 	}
821 
822 	id = ZEND_THIS;
823 	intern = Z_XMLREADER_P(id);
824 	if (intern != NULL && intern->ptr != NULL) {
825 		retval = xmlTextReaderNext(intern->ptr);
826 		while (name != NULL && retval == 1) {
827 			if (xmlStrEqual(xmlTextReaderConstLocalName(intern->ptr), (xmlChar *)name)) {
828 				RETURN_TRUE;
829 			}
830 			retval = xmlTextReaderNext(intern->ptr);
831 		}
832 		if (retval == -1) {
833 			RETURN_FALSE;
834 		} else {
835 			RETURN_BOOL(retval);
836 		}
837 	}
838 
839 	php_error_docref(NULL, E_WARNING, "Load Data before trying to read");
840 	RETURN_FALSE;
841 }
842 /* }}} */
843 
844 /* {{{ proto bool XMLReader::open(string URI [, string encoding [, int options]])
845 Sets the URI that the XMLReader will parse. */
PHP_METHODnull846 PHP_METHOD(xmlreader, open)
847 {
848 	zval *id;
849 	size_t source_len = 0, encoding_len = 0;
850 	zend_long options = 0;
851 	xmlreader_object *intern = NULL;
852 	char *source, *valid_file = NULL;
853 	char *encoding = NULL;
854 	char resolved_path[MAXPATHLEN + 1];
855 	xmlTextReaderPtr reader = NULL;
856 
857 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|s!l", &source, &source_len, &encoding, &encoding_len, &options) == FAILURE) {
858 		return;
859 	}
860 
861 	id = getThis();
862 	if (id != NULL) {
863 		if (! instanceof_function(Z_OBJCE_P(id), xmlreader_class_entry)) {
864 			id = NULL;
865 		} else {
866 			intern = Z_XMLREADER_P(id);
867 			xmlreader_free_resources(intern);
868 		}
869 	}
870 
871 	if (!source_len) {
872 		php_error_docref(NULL, E_WARNING, "Empty string supplied as input");
873 		RETURN_FALSE;
874 	}
875 
876 	valid_file = _xmlreader_get_valid_file_path(source, resolved_path, MAXPATHLEN );
877 
878 	if (valid_file) {
879 		reader = xmlReaderForFile(valid_file, encoding, options);
880 	}
881 
882 	if (reader == NULL) {
883 		php_error_docref(NULL, E_WARNING, "Unable to open source data");
884 		RETURN_FALSE;
885 	}
886 
887 	if (id == NULL) {
888 		object_init_ex(return_value, xmlreader_class_entry);
889 		intern = Z_XMLREADER_P(return_value);
890 		intern->ptr = reader;
891 		return;
892 	}
893 
894 	intern->ptr = reader;
895 
896 	RETURN_TRUE;
897 
898 }
899 /* }}} */
900 
901 /* Not Yet Implemented in libxml - functions exist just not coded
902 PHP_METHOD(xmlreader, resetState)
903 {
904 
905 }
906 */
907 
908 /* {{{ proto string XMLReader::readInnerXml()
909 Reads the contents of the current node, including child nodes and markup. */
PHP_METHODnull910 PHP_METHOD(xmlreader, readInnerXml)
911 {
912 	php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderReadInnerXml);
913 }
914 /* }}} */
915 
916 /* {{{ proto bool XMLReader::readOuterXml()
917 Reads the contents of the current node, including child nodes and markup. */
PHP_METHODnull918 PHP_METHOD(xmlreader, readOuterXml)
919 {
920 	php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderReadOuterXml);
921 }
922 /* }}} */
923 
924 /* {{{ proto bool XMLReader::readString()
925 Reads the contents of an element or a text node as a string. */
PHP_METHODnull926 PHP_METHOD(xmlreader, readString)
927 {
928 	php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderReadString);
929 }
930 /* }}} */
931 
932 /* {{{ proto bool XMLReader::setSchema(string filename)
933 Use W3C XSD schema to validate the document as it is processed. Activation is only possible before the first Read(). */
PHP_METHODnull934 PHP_METHOD(xmlreader, setSchema)
935 {
936 #ifdef LIBXML_SCHEMAS_ENABLED
937 	zval *id;
938 	size_t source_len = 0;
939 	int retval = -1;
940 	xmlreader_object *intern;
941 	char *source;
942 
943 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "p!", &source, &source_len) == FAILURE) {
944 		return;
945 	}
946 
947 	if (source != NULL && !source_len) {
948 		php_error_docref(NULL, E_WARNING, "Schema data source is required");
949 		RETURN_FALSE;
950 	}
951 
952 	id = ZEND_THIS;
953 
954 	intern = Z_XMLREADER_P(id);
955 	if (intern && intern->ptr) {
956 		retval = xmlTextReaderSchemaValidate(intern->ptr, source);
957 
958 		if (retval == 0) {
959 			RETURN_TRUE;
960 		}
961 	}
962 
963 	php_error_docref(NULL, E_WARNING, "Unable to set schema. This must be set prior to reading or schema contains errors.");
964 
965 	RETURN_FALSE;
966 #else
967 	php_error_docref(NULL, E_WARNING, "No Schema support built into libxml.");
968 
969 	RETURN_FALSE;
970 #endif
971 }
972 /* }}} */
973 
974 /* {{{ proto bool XMLReader::setParserProperty(int property, bool value)
975 Sets parser property (one of the parser option constants).
976 Properties must be set after open() or XML() and before the first read() is called */
PHP_METHODnull977 PHP_METHOD(xmlreader, setParserProperty)
978 {
979 	zval *id;
980 	zend_long property;
981 	int retval = -1;
982 	zend_bool value;
983 	xmlreader_object *intern;
984 
985 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "lb", &property, &value) == FAILURE) {
986 		return;
987 	}
988 
989 	id = ZEND_THIS;
990 
991 	intern = Z_XMLREADER_P(id);
992 	if (intern && intern->ptr) {
993 		retval = xmlTextReaderSetParserProp(intern->ptr,property, value);
994 	}
995 	if (retval == -1) {
996 		php_error_docref(NULL, E_WARNING, "Invalid parser property");
997 		RETURN_FALSE;
998 	}
999 
1000 	RETURN_TRUE;
1001 }
1002 /* }}} */
1003 
1004 /* {{{ proto bool XMLReader::setRelaxNGSchema(string filename)
1005 Sets the string that the XMLReader will parse. */
PHP_METHODnull1006 PHP_METHOD(xmlreader, setRelaxNGSchema)
1007 {
1008 	php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAM_PASSTHRU, XMLREADER_LOAD_FILE);
1009 }
1010 /* }}} */
1011 
1012 /* {{{ proto bool XMLReader::setRelaxNGSchemaSource(string source)
1013 Sets the string that the XMLReader will parse. */
PHP_METHODnull1014 PHP_METHOD(xmlreader, setRelaxNGSchemaSource)
1015 {
1016 	php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAM_PASSTHRU, XMLREADER_LOAD_STRING);
1017 }
1018 /* }}} */
1019 
1020 /* TODO
1021 XMLPUBFUN int XMLCALL
1022 		    xmlTextReaderSetSchema	(xmlTextReaderPtr reader,
1023 		    				 xmlSchemaPtr schema);
1024 */
1025 
1026 /* {{{ proto bool XMLReader::XML(string source [, string encoding [, int options]])
1027 Sets the string that the XMLReader will parse. */
PHP_METHODnull1028 PHP_METHOD(xmlreader, XML)
1029 {
1030 	zval *id;
1031 	size_t source_len = 0, encoding_len = 0;
1032 	zend_long options = 0;
1033 	xmlreader_object *intern = NULL;
1034 	char *source, *uri = NULL, *encoding = NULL;
1035 	int resolved_path_len, ret = 0;
1036 	char *directory=NULL, resolved_path[MAXPATHLEN];
1037 	xmlParserInputBufferPtr inputbfr;
1038 	xmlTextReaderPtr reader;
1039 
1040 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s!l", &source, &source_len, &encoding, &encoding_len, &options) == FAILURE) {
1041 		return;
1042 	}
1043 
1044 	id = getThis();
1045 	if (id != NULL && ! instanceof_function(Z_OBJCE_P(id), xmlreader_class_entry)) {
1046 		id = NULL;
1047 	}
1048 	if (id != NULL) {
1049 		intern = Z_XMLREADER_P(id);
1050 		xmlreader_free_resources(intern);
1051 	}
1052 
1053 	if (!source_len) {
1054 		php_error_docref(NULL, E_WARNING, "Empty string supplied as input");
1055 		RETURN_FALSE;
1056 	}
1057 
1058 	inputbfr = xmlParserInputBufferCreateMem(source, source_len, XML_CHAR_ENCODING_NONE);
1059 
1060     if (inputbfr != NULL) {
1061 /* Get the URI of the current script so that we can set the base directory in libxml */
1062 #if HAVE_GETCWD
1063 		directory = VCWD_GETCWD(resolved_path, MAXPATHLEN);
1064 #elif HAVE_GETWD
1065 		directory = VCWD_GETWD(resolved_path);
1066 #endif
1067 		if (directory) {
1068 			resolved_path_len = strlen(resolved_path);
1069 			if (resolved_path[resolved_path_len - 1] != DEFAULT_SLASH) {
1070 				resolved_path[resolved_path_len] = DEFAULT_SLASH;
1071 				resolved_path[++resolved_path_len] = '\0';
1072 			}
1073 			uri = (char *) xmlCanonicPath((const xmlChar *) resolved_path);
1074 		}
1075 		reader = xmlNewTextReader(inputbfr, uri);
1076 
1077 		if (reader != NULL) {
1078 			ret = xmlTextReaderSetup(reader, NULL, uri, encoding, options);
1079 			if (ret == 0) {
1080 				if (id == NULL) {
1081 					object_init_ex(return_value, xmlreader_class_entry);
1082 					intern = Z_XMLREADER_P(return_value);
1083 				} else {
1084 					RETVAL_TRUE;
1085 				}
1086 				intern->input = inputbfr;
1087 				intern->ptr = reader;
1088 
1089 				if (uri) {
1090 					xmlFree(uri);
1091 				}
1092 
1093 				return;
1094 			}
1095 		}
1096 	}
1097 
1098 	if (uri) {
1099 		xmlFree(uri);
1100 	}
1101 
1102 	if (inputbfr) {
1103 		xmlFreeParserInputBuffer(inputbfr);
1104 	}
1105 	php_error_docref(NULL, E_WARNING, "Unable to load source data");
1106 	RETURN_FALSE;
1107 }
1108 /* }}} */
1109 
1110 /* {{{ proto bool XMLReader::expand()
1111 Moves the position of the current instance to the next node in the stream. */
PHP_METHODnull1112 PHP_METHOD(xmlreader, expand)
1113 {
1114 #ifdef HAVE_DOM
1115 	zval *id, *basenode = NULL;
1116 	int ret;
1117 	xmlreader_object *intern;
1118 	xmlNode *node, *nodec;
1119 	xmlDocPtr docp = NULL;
1120 	php_libxml_node_object *domobj = NULL;
1121 
1122 	id = ZEND_THIS;
1123 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|O!", &basenode, dom_node_class_entry) == FAILURE) {
1124 		return;
1125 	}
1126 
1127 	if (basenode != NULL) {
1128 		NODE_GET_OBJ(node, basenode, xmlNodePtr, domobj);
1129 		docp = node->doc;
1130 	}
1131 
1132 	intern = Z_XMLREADER_P(id);
1133 
1134 	if (intern && intern->ptr) {
1135 		node = xmlTextReaderExpand(intern->ptr);
1136 
1137 		if (node == NULL) {
1138 			php_error_docref(NULL, E_WARNING, "An Error Occurred while expanding ");
1139 			RETURN_FALSE;
1140 		} else {
1141 			nodec = xmlDocCopyNode(node, docp, 1);
1142 			if (nodec == NULL) {
1143 				php_error_docref(NULL, E_NOTICE, "Cannot expand this node type");
1144 				RETURN_FALSE;
1145 			} else {
1146 				DOM_RET_OBJ(nodec, &ret, (dom_object *)domobj);
1147 			}
1148 		}
1149 	} else {
1150 		php_error_docref(NULL, E_WARNING, "Load Data before trying to expand");
1151 		RETURN_FALSE;
1152 	}
1153 #else
1154 	php_error(E_WARNING, "DOM support is not enabled");
1155 	return;
1156 #endif
1157 }
1158 /* }}} */
1159 
1160 /* {{{ arginfo */
1161 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_close, 0)
1162 ZEND_END_ARG_INFO()
1163 
1164 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_getAttribute, 0)
1165 	ZEND_ARG_INFO(0, name)
1166 ZEND_END_ARG_INFO()
1167 
1168 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_getAttributeNo, 0)
1169 	ZEND_ARG_INFO(0, index)
1170 ZEND_END_ARG_INFO()
1171 
1172 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_getAttributeNs, 0)
1173 	ZEND_ARG_INFO(0, name)
1174 	ZEND_ARG_INFO(0, namespaceURI)
1175 ZEND_END_ARG_INFO()
1176 
1177 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_getParserProperty, 0)
1178 	ZEND_ARG_INFO(0, property)
1179 ZEND_END_ARG_INFO()
1180 
1181 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_isValid, 0)
1182 ZEND_END_ARG_INFO()
1183 
1184 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_lookupNamespace, 0)
1185 ZEND_ARG_INFO(0, prefix)
1186 ZEND_END_ARG_INFO()
1187 
1188 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToAttribute, 0)
1189 	ZEND_ARG_INFO(0, name)
1190 ZEND_END_ARG_INFO()
1191 
1192 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToAttributeNo, 0)
1193 	ZEND_ARG_INFO(0, index)
1194 ZEND_END_ARG_INFO()
1195 
1196 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToAttributeNs, 0)
1197 	ZEND_ARG_INFO(0, name)
1198 	ZEND_ARG_INFO(0, namespaceURI)
1199 ZEND_END_ARG_INFO()
1200 
1201 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToElement, 0)
1202 ZEND_END_ARG_INFO()
1203 
1204 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToFirstAttribute, 0)
1205 ZEND_END_ARG_INFO()
1206 
1207 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToNextAttribute, 0)
1208 ZEND_END_ARG_INFO()
1209 
1210 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_read, 0)
1211 ZEND_END_ARG_INFO()
1212 
1213 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlreader_next, 0, 0, 0)
1214 	ZEND_ARG_INFO(0, localname)
1215 ZEND_END_ARG_INFO()
1216 
1217 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlreader_open, 0, 0, 1)
1218 	ZEND_ARG_INFO(0, URI)
1219 	ZEND_ARG_INFO(0, encoding)
1220 	ZEND_ARG_INFO(0, options)
1221 ZEND_END_ARG_INFO()
1222 
1223 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_readInnerXml, 0)
1224 ZEND_END_ARG_INFO()
1225 
1226 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_readOuterXml, 0)
1227 ZEND_END_ARG_INFO()
1228 
1229 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_readString, 0)
1230 ZEND_END_ARG_INFO()
1231 
1232 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_setSchema, 0)
1233 	ZEND_ARG_INFO(0, filename)
1234 ZEND_END_ARG_INFO()
1235 
1236 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_setParserProperty, 0)
1237 	ZEND_ARG_INFO(0, property)
1238 	ZEND_ARG_INFO(0, value)
1239 ZEND_END_ARG_INFO()
1240 
1241 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_setRelaxNGSchema, 0)
1242 	ZEND_ARG_INFO(0, filename)
1243 ZEND_END_ARG_INFO()
1244 
1245 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_setRelaxNGSchemaSource, 0)
1246 	ZEND_ARG_INFO(0, source)
1247 ZEND_END_ARG_INFO()
1248 
1249 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlreader_XML, 0, 0, 1)
1250 	ZEND_ARG_INFO(0, source)
1251 	ZEND_ARG_INFO(0, encoding)
1252 	ZEND_ARG_INFO(0, options)
1253 ZEND_END_ARG_INFO()
1254 
1255 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlreader_expand, 0, 0, 0)
1256 	ZEND_ARG_INFO(0, basenode)
1257 ZEND_END_ARG_INFO()
1258 /* }}} */
1259 
1260 static const zend_function_entry xmlreader_functions[] /* {{{ */ =  {
1261 	PHP_ME(xmlreader, close, arginfo_xmlreader_close, ZEND_ACC_PUBLIC)
1262 	PHP_ME(xmlreader, getAttribute, arginfo_xmlreader_getAttribute, ZEND_ACC_PUBLIC)
1263 	PHP_ME(xmlreader, getAttributeNo, arginfo_xmlreader_getAttributeNo, ZEND_ACC_PUBLIC)
1264 	PHP_ME(xmlreader, getAttributeNs, arginfo_xmlreader_getAttributeNs, ZEND_ACC_PUBLIC)
1265 	PHP_ME(xmlreader, getParserProperty, arginfo_xmlreader_getParserProperty, ZEND_ACC_PUBLIC)
1266 	PHP_ME(xmlreader, isValid, arginfo_xmlreader_isValid, ZEND_ACC_PUBLIC)
1267 	PHP_ME(xmlreader, lookupNamespace, arginfo_xmlreader_lookupNamespace, ZEND_ACC_PUBLIC)
1268 	PHP_ME(xmlreader, moveToAttributeNo, arginfo_xmlreader_moveToAttributeNo, ZEND_ACC_PUBLIC)
1269 	PHP_ME(xmlreader, moveToAttribute, arginfo_xmlreader_moveToAttribute, ZEND_ACC_PUBLIC)
1270 	PHP_ME(xmlreader, moveToAttributeNs, arginfo_xmlreader_moveToAttributeNs, ZEND_ACC_PUBLIC)
1271 	PHP_ME(xmlreader, moveToElement, arginfo_xmlreader_moveToElement, ZEND_ACC_PUBLIC)
1272 	PHP_ME(xmlreader, moveToFirstAttribute, arginfo_xmlreader_moveToFirstAttribute, ZEND_ACC_PUBLIC)
1273 	PHP_ME(xmlreader, moveToNextAttribute, arginfo_xmlreader_moveToNextAttribute, ZEND_ACC_PUBLIC)
1274 	PHP_ME(xmlreader, open, arginfo_xmlreader_open, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC)
1275 	PHP_ME(xmlreader, read, arginfo_xmlreader_read, ZEND_ACC_PUBLIC)
1276 	PHP_ME(xmlreader, next, arginfo_xmlreader_next, ZEND_ACC_PUBLIC)
1277 	PHP_ME(xmlreader, readInnerXml, arginfo_xmlreader_readInnerXml, ZEND_ACC_PUBLIC)
1278 	PHP_ME(xmlreader, readOuterXml, arginfo_xmlreader_readOuterXml, ZEND_ACC_PUBLIC)
1279 	PHP_ME(xmlreader, readString, arginfo_xmlreader_readString, ZEND_ACC_PUBLIC)
1280 	PHP_ME(xmlreader, setSchema, arginfo_xmlreader_setSchema, ZEND_ACC_PUBLIC)
1281 /* Not Yet Implemented though defined in libxml as of 2.6.9dev
1282 	PHP_ME(xmlreader, resetState, NULL, ZEND_ACC_PUBLIC)
1283 */
1284 	PHP_ME(xmlreader, setParserProperty, arginfo_xmlreader_setParserProperty, ZEND_ACC_PUBLIC)
1285 	PHP_ME(xmlreader, setRelaxNGSchema, arginfo_xmlreader_setRelaxNGSchema, ZEND_ACC_PUBLIC)
1286 	PHP_ME(xmlreader, setRelaxNGSchemaSource, arginfo_xmlreader_setRelaxNGSchemaSource, ZEND_ACC_PUBLIC)
1287 	PHP_ME(xmlreader, XML, arginfo_xmlreader_XML, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC)
1288 	PHP_ME(xmlreader, expand, arginfo_xmlreader_expand, ZEND_ACC_PUBLIC)
1289 	PHP_FE_END
1290 }; /* }}} */
1291 
1292 /* {{{ PHP_MINIT_FUNCTION
1293  */
PHP_MINIT_FUNCTIONnull1294 PHP_MINIT_FUNCTION(xmlreader)
1295 {
1296 
1297 	zend_class_entry ce;
1298 
1299 	memcpy(&xmlreader_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
1300 	xmlreader_object_handlers.offset = XtOffsetOf(xmlreader_object, std);
1301 	xmlreader_object_handlers.dtor_obj = zend_objects_destroy_object;
1302 	xmlreader_object_handlers.free_obj = xmlreader_objects_free_storage;
1303 	xmlreader_object_handlers.read_property = xmlreader_read_property;
1304 	xmlreader_object_handlers.write_property = xmlreader_write_property;
1305 	xmlreader_object_handlers.get_property_ptr_ptr = xmlreader_get_property_ptr_ptr;
1306 	xmlreader_object_handlers.clone_obj = NULL;
1307 
1308 	INIT_CLASS_ENTRY(ce, "XMLReader", xmlreader_functions);
1309 	ce.create_object = xmlreader_objects_new;
1310 	xmlreader_class_entry = zend_register_internal_class(&ce);
1311 
1312 	zend_hash_init(&xmlreader_prop_handlers, 0, NULL, php_xmlreader_free_prop_handler, 1);
1313 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "attributeCount", xmlTextReaderAttributeCount, NULL, IS_LONG);
1314 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "baseURI", NULL, xmlTextReaderConstBaseUri, IS_STRING);
1315 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "depth", xmlTextReaderDepth, NULL, IS_LONG);
1316 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "hasAttributes", xmlTextReaderHasAttributes, NULL, IS_FALSE);
1317 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "hasValue", xmlTextReaderHasValue, NULL, IS_FALSE);
1318 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "isDefault", xmlTextReaderIsDefault, NULL, IS_FALSE);
1319 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "isEmptyElement", xmlTextReaderIsEmptyElement, NULL, IS_FALSE);
1320 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "localName", NULL, xmlTextReaderConstLocalName, IS_STRING);
1321 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "name", NULL, xmlTextReaderConstName, IS_STRING);
1322 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "namespaceURI", NULL, xmlTextReaderConstNamespaceUri, IS_STRING);
1323 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "nodeType", xmlTextReaderNodeType, NULL, IS_LONG);
1324 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "prefix", NULL, xmlTextReaderConstPrefix, IS_STRING);
1325 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "value", NULL, xmlTextReaderConstValue, IS_STRING);
1326 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "xmlLang", NULL, xmlTextReaderConstXmlLang, IS_STRING);
1327 
1328 	/* Constants for NodeType - cannot define common types to share with dom as there are differences in these types */
1329 
1330 	REGISTER_XMLREADER_CLASS_CONST_LONG("NONE",	XML_READER_TYPE_NONE);
1331 	REGISTER_XMLREADER_CLASS_CONST_LONG("ELEMENT",	XML_READER_TYPE_ELEMENT);
1332 	REGISTER_XMLREADER_CLASS_CONST_LONG("ATTRIBUTE",	XML_READER_TYPE_ATTRIBUTE);
1333 	REGISTER_XMLREADER_CLASS_CONST_LONG("TEXT",	XML_READER_TYPE_TEXT);
1334 	REGISTER_XMLREADER_CLASS_CONST_LONG("CDATA",	XML_READER_TYPE_CDATA);
1335 	REGISTER_XMLREADER_CLASS_CONST_LONG("ENTITY_REF",	XML_READER_TYPE_ENTITY_REFERENCE);
1336 	REGISTER_XMLREADER_CLASS_CONST_LONG("ENTITY",	XML_READER_TYPE_ENTITY);
1337 	REGISTER_XMLREADER_CLASS_CONST_LONG("PI",	XML_READER_TYPE_PROCESSING_INSTRUCTION);
1338 	REGISTER_XMLREADER_CLASS_CONST_LONG("COMMENT",	XML_READER_TYPE_COMMENT);
1339 	REGISTER_XMLREADER_CLASS_CONST_LONG("DOC",	XML_READER_TYPE_DOCUMENT);
1340 	REGISTER_XMLREADER_CLASS_CONST_LONG("DOC_TYPE",	XML_READER_TYPE_DOCUMENT_TYPE);
1341 	REGISTER_XMLREADER_CLASS_CONST_LONG("DOC_FRAGMENT",	XML_READER_TYPE_DOCUMENT_FRAGMENT);
1342 	REGISTER_XMLREADER_CLASS_CONST_LONG("NOTATION",	XML_READER_TYPE_NOTATION);
1343 	REGISTER_XMLREADER_CLASS_CONST_LONG("WHITESPACE",	XML_READER_TYPE_WHITESPACE);
1344 	REGISTER_XMLREADER_CLASS_CONST_LONG("SIGNIFICANT_WHITESPACE",	XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
1345 	REGISTER_XMLREADER_CLASS_CONST_LONG("END_ELEMENT",	XML_READER_TYPE_END_ELEMENT);
1346 	REGISTER_XMLREADER_CLASS_CONST_LONG("END_ENTITY",	XML_READER_TYPE_END_ENTITY);
1347 	REGISTER_XMLREADER_CLASS_CONST_LONG("XML_DECLARATION",	XML_READER_TYPE_XML_DECLARATION);
1348 
1349 	/* Constants for Parser options */
1350 	REGISTER_XMLREADER_CLASS_CONST_LONG("LOADDTD",	XML_PARSER_LOADDTD);
1351 	REGISTER_XMLREADER_CLASS_CONST_LONG("DEFAULTATTRS",	XML_PARSER_DEFAULTATTRS);
1352 	REGISTER_XMLREADER_CLASS_CONST_LONG("VALIDATE",	XML_PARSER_VALIDATE);
1353 	REGISTER_XMLREADER_CLASS_CONST_LONG("SUBST_ENTITIES",	XML_PARSER_SUBST_ENTITIES);
1354 
1355 	/* Constants for Errors when loading - not yet used until we implement custom error handling
1356 	REGISTER_XMLREADER_CLASS_CONST_LONG("VALIDITY_WARNING",		XML_PARSER_SEVERITY_VALIDITY_WARNING,	CONST_CS | CONST_PERSISTENT);
1357 	REGISTER_XMLREADER_CLASS_CONST_LONG("VALIDITY_ERROR",		XML_PARSER_SEVERITY_VALIDITY_ERROR,		CONST_CS | CONST_PERSISTENT);
1358 	REGISTER_XMLREADER_CLASS_CONST_LONG("WARNING",				XML_PARSER_SEVERITY_WARNING,			CONST_CS | CONST_PERSISTENT);
1359 	REGISTER_XMLREADER_CLASS_CONST_LONG("ERROR",				XML_PARSER_SEVERITY_ERROR,				CONST_CS | CONST_PERSISTENT);
1360 	*/
1361 
1362 	return SUCCESS;
1363 }
1364 /* }}} */
1365 
1366 /* {{{ PHP_MSHUTDOWN_FUNCTION
1367  */
PHP_MSHUTDOWN_FUNCTIONnull1368 PHP_MSHUTDOWN_FUNCTION(xmlreader)
1369 {
1370 	zend_hash_destroy(&xmlreader_prop_handlers);
1371 	return SUCCESS;
1372 }
1373 /* }}} */
1374 
1375 /* {{{ PHP_MINFO_FUNCTION
1376  */
PHP_MINFO_FUNCTIONnull1377 PHP_MINFO_FUNCTION(xmlreader)
1378 {
1379 	php_info_print_table_start();
1380 	{
1381 		php_info_print_table_row(2, "XMLReader", "enabled");
1382 	}
1383 	php_info_print_table_end();
1384 }
1385 /* }}} */
1386