xref: /PHP-7.4/ext/xmlreader/php_xmlreader.c (revision 272df442)
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_MODULE(xmlreader)344 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_METHOD(xmlreader,close)538 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_METHOD(xmlreader,getAttribute)556 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_METHOD(xmlreader,getAttributeNo)564 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_METHOD(xmlreader,getAttributeNs)590 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_METHOD(xmlreader,getParserProperty)621 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_METHOD(xmlreader,isValid)651 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_METHOD(xmlreader,lookupNamespace)659 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_METHOD(xmlreader,moveToAttribute)667 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_METHOD(xmlreader,moveToAttributeNo)701 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_METHOD(xmlreader,moveToAttributeNs)729 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_METHOD(xmlreader,moveToElement)762 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_METHOD(xmlreader,moveToFirstAttribute)770 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_METHOD(xmlreader,moveToNextAttribute)778 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_METHOD(xmlreader,read)786 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_METHOD(xmlreader,next)810 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_METHOD(xmlreader,open)846 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 	if (encoding && CHECK_NULL_PATH(encoding, encoding_len)) {
877 		php_error_docref(NULL, E_WARNING, "Encoding must not contain NUL bytes");
878 		RETURN_FALSE;
879 	}
880 
881 	valid_file = _xmlreader_get_valid_file_path(source, resolved_path, MAXPATHLEN );
882 
883 	if (valid_file) {
884 		reader = xmlReaderForFile(valid_file, encoding, options);
885 	}
886 
887 	if (reader == NULL) {
888 		php_error_docref(NULL, E_WARNING, "Unable to open source data");
889 		RETURN_FALSE;
890 	}
891 
892 	if (id == NULL) {
893 		object_init_ex(return_value, xmlreader_class_entry);
894 		intern = Z_XMLREADER_P(return_value);
895 		intern->ptr = reader;
896 		return;
897 	}
898 
899 	intern->ptr = reader;
900 
901 	RETURN_TRUE;
902 
903 }
904 /* }}} */
905 
906 /* Not Yet Implemented in libxml - functions exist just not coded
907 PHP_METHOD(xmlreader, resetState)
908 {
909 
910 }
911 */
912 
913 /* {{{ proto string XMLReader::readInnerXml()
914 Reads the contents of the current node, including child nodes and markup. */
PHP_METHOD(xmlreader,readInnerXml)915 PHP_METHOD(xmlreader, readInnerXml)
916 {
917 	php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderReadInnerXml);
918 }
919 /* }}} */
920 
921 /* {{{ proto bool XMLReader::readOuterXml()
922 Reads the contents of the current node, including child nodes and markup. */
PHP_METHOD(xmlreader,readOuterXml)923 PHP_METHOD(xmlreader, readOuterXml)
924 {
925 	php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderReadOuterXml);
926 }
927 /* }}} */
928 
929 /* {{{ proto bool XMLReader::readString()
930 Reads the contents of an element or a text node as a string. */
PHP_METHOD(xmlreader,readString)931 PHP_METHOD(xmlreader, readString)
932 {
933 	php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderReadString);
934 }
935 /* }}} */
936 
937 /* {{{ proto bool XMLReader::setSchema(string filename)
938 Use W3C XSD schema to validate the document as it is processed. Activation is only possible before the first Read(). */
PHP_METHOD(xmlreader,setSchema)939 PHP_METHOD(xmlreader, setSchema)
940 {
941 #ifdef LIBXML_SCHEMAS_ENABLED
942 	zval *id;
943 	size_t source_len = 0;
944 	int retval = -1;
945 	xmlreader_object *intern;
946 	char *source;
947 
948 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "p!", &source, &source_len) == FAILURE) {
949 		return;
950 	}
951 
952 	if (source != NULL && !source_len) {
953 		php_error_docref(NULL, E_WARNING, "Schema data source is required");
954 		RETURN_FALSE;
955 	}
956 
957 	id = ZEND_THIS;
958 
959 	intern = Z_XMLREADER_P(id);
960 	if (intern && intern->ptr) {
961 		retval = xmlTextReaderSchemaValidate(intern->ptr, source);
962 
963 		if (retval == 0) {
964 			RETURN_TRUE;
965 		}
966 	}
967 
968 	php_error_docref(NULL, E_WARNING, "Unable to set schema. This must be set prior to reading or schema contains errors.");
969 
970 	RETURN_FALSE;
971 #else
972 	php_error_docref(NULL, E_WARNING, "No Schema support built into libxml.");
973 
974 	RETURN_FALSE;
975 #endif
976 }
977 /* }}} */
978 
979 /* {{{ proto bool XMLReader::setParserProperty(int property, bool value)
980 Sets parser property (one of the parser option constants).
981 Properties must be set after open() or XML() and before the first read() is called */
PHP_METHOD(xmlreader,setParserProperty)982 PHP_METHOD(xmlreader, setParserProperty)
983 {
984 	zval *id;
985 	zend_long property;
986 	int retval = -1;
987 	zend_bool value;
988 	xmlreader_object *intern;
989 
990 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "lb", &property, &value) == FAILURE) {
991 		return;
992 	}
993 
994 	id = ZEND_THIS;
995 
996 	intern = Z_XMLREADER_P(id);
997 	if (intern && intern->ptr) {
998 		retval = xmlTextReaderSetParserProp(intern->ptr,property, value);
999 	}
1000 	if (retval == -1) {
1001 		php_error_docref(NULL, E_WARNING, "Invalid parser property");
1002 		RETURN_FALSE;
1003 	}
1004 
1005 	RETURN_TRUE;
1006 }
1007 /* }}} */
1008 
1009 /* {{{ proto bool XMLReader::setRelaxNGSchema(string filename)
1010 Sets the string that the XMLReader will parse. */
PHP_METHOD(xmlreader,setRelaxNGSchema)1011 PHP_METHOD(xmlreader, setRelaxNGSchema)
1012 {
1013 	php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAM_PASSTHRU, XMLREADER_LOAD_FILE);
1014 }
1015 /* }}} */
1016 
1017 /* {{{ proto bool XMLReader::setRelaxNGSchemaSource(string source)
1018 Sets the string that the XMLReader will parse. */
PHP_METHOD(xmlreader,setRelaxNGSchemaSource)1019 PHP_METHOD(xmlreader, setRelaxNGSchemaSource)
1020 {
1021 	php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAM_PASSTHRU, XMLREADER_LOAD_STRING);
1022 }
1023 /* }}} */
1024 
1025 /* TODO
1026 XMLPUBFUN int XMLCALL
1027 		    xmlTextReaderSetSchema	(xmlTextReaderPtr reader,
1028 		    				 xmlSchemaPtr schema);
1029 */
1030 
1031 /* {{{ proto bool XMLReader::XML(string source [, string encoding [, int options]])
1032 Sets the string that the XMLReader will parse. */
PHP_METHOD(xmlreader,XML)1033 PHP_METHOD(xmlreader, XML)
1034 {
1035 	zval *id;
1036 	size_t source_len = 0, encoding_len = 0;
1037 	zend_long options = 0;
1038 	xmlreader_object *intern = NULL;
1039 	char *source, *uri = NULL, *encoding = NULL;
1040 	int resolved_path_len, ret = 0;
1041 	char *directory=NULL, resolved_path[MAXPATHLEN];
1042 	xmlParserInputBufferPtr inputbfr;
1043 	xmlTextReaderPtr reader;
1044 
1045 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s!l", &source, &source_len, &encoding, &encoding_len, &options) == FAILURE) {
1046 		return;
1047 	}
1048 
1049 	id = getThis();
1050 	if (id != NULL && ! instanceof_function(Z_OBJCE_P(id), xmlreader_class_entry)) {
1051 		id = NULL;
1052 	}
1053 	if (id != NULL) {
1054 		intern = Z_XMLREADER_P(id);
1055 		xmlreader_free_resources(intern);
1056 	}
1057 
1058 	if (!source_len) {
1059 		php_error_docref(NULL, E_WARNING, "Empty string supplied as input");
1060 		RETURN_FALSE;
1061 	}
1062 
1063 	if (encoding && CHECK_NULL_PATH(encoding, encoding_len)) {
1064 		php_error_docref(NULL, E_WARNING, "Encoding must not contain NUL bytes");
1065 		RETURN_FALSE;
1066 	}
1067 
1068 	inputbfr = xmlParserInputBufferCreateMem(source, source_len, XML_CHAR_ENCODING_NONE);
1069 
1070     if (inputbfr != NULL) {
1071 /* Get the URI of the current script so that we can set the base directory in libxml */
1072 #if HAVE_GETCWD
1073 		directory = VCWD_GETCWD(resolved_path, MAXPATHLEN);
1074 #elif HAVE_GETWD
1075 		directory = VCWD_GETWD(resolved_path);
1076 #endif
1077 		if (directory) {
1078 			resolved_path_len = strlen(resolved_path);
1079 			if (resolved_path[resolved_path_len - 1] != DEFAULT_SLASH) {
1080 				resolved_path[resolved_path_len] = DEFAULT_SLASH;
1081 				resolved_path[++resolved_path_len] = '\0';
1082 			}
1083 			uri = (char *) xmlCanonicPath((const xmlChar *) resolved_path);
1084 		}
1085 		reader = xmlNewTextReader(inputbfr, uri);
1086 
1087 		if (reader != NULL) {
1088 			ret = xmlTextReaderSetup(reader, NULL, uri, encoding, options);
1089 			if (ret == 0) {
1090 				if (id == NULL) {
1091 					object_init_ex(return_value, xmlreader_class_entry);
1092 					intern = Z_XMLREADER_P(return_value);
1093 				} else {
1094 					RETVAL_TRUE;
1095 				}
1096 				intern->input = inputbfr;
1097 				intern->ptr = reader;
1098 
1099 				if (uri) {
1100 					xmlFree(uri);
1101 				}
1102 
1103 				return;
1104 			}
1105 		}
1106 	}
1107 
1108 	if (uri) {
1109 		xmlFree(uri);
1110 	}
1111 
1112 	if (inputbfr) {
1113 		xmlFreeParserInputBuffer(inputbfr);
1114 	}
1115 	php_error_docref(NULL, E_WARNING, "Unable to load source data");
1116 	RETURN_FALSE;
1117 }
1118 /* }}} */
1119 
1120 /* {{{ proto bool XMLReader::expand()
1121 Moves the position of the current instance to the next node in the stream. */
PHP_METHOD(xmlreader,expand)1122 PHP_METHOD(xmlreader, expand)
1123 {
1124 #ifdef HAVE_DOM
1125 	zval *id, *basenode = NULL;
1126 	int ret;
1127 	xmlreader_object *intern;
1128 	xmlNode *node, *nodec;
1129 	xmlDocPtr docp = NULL;
1130 	php_libxml_node_object *domobj = NULL;
1131 
1132 	id = ZEND_THIS;
1133 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|O!", &basenode, dom_node_class_entry) == FAILURE) {
1134 		return;
1135 	}
1136 
1137 	if (basenode != NULL) {
1138 		NODE_GET_OBJ(node, basenode, xmlNodePtr, domobj);
1139 		docp = node->doc;
1140 	}
1141 
1142 	intern = Z_XMLREADER_P(id);
1143 
1144 	if (intern && intern->ptr) {
1145 		node = xmlTextReaderExpand(intern->ptr);
1146 
1147 		if (node == NULL) {
1148 			php_error_docref(NULL, E_WARNING, "An Error Occurred while expanding ");
1149 			RETURN_FALSE;
1150 		} else {
1151 			nodec = xmlDocCopyNode(node, docp, 1);
1152 			if (nodec == NULL) {
1153 				php_error_docref(NULL, E_NOTICE, "Cannot expand this node type");
1154 				RETURN_FALSE;
1155 			} else {
1156 				DOM_RET_OBJ(nodec, &ret, (dom_object *)domobj);
1157 			}
1158 		}
1159 	} else {
1160 		php_error_docref(NULL, E_WARNING, "Load Data before trying to expand");
1161 		RETURN_FALSE;
1162 	}
1163 #else
1164 	php_error(E_WARNING, "DOM support is not enabled");
1165 	return;
1166 #endif
1167 }
1168 /* }}} */
1169 
1170 /* {{{ arginfo */
1171 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_close, 0)
1172 ZEND_END_ARG_INFO()
1173 
1174 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_getAttribute, 0)
1175 	ZEND_ARG_INFO(0, name)
1176 ZEND_END_ARG_INFO()
1177 
1178 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_getAttributeNo, 0)
1179 	ZEND_ARG_INFO(0, index)
1180 ZEND_END_ARG_INFO()
1181 
1182 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_getAttributeNs, 0)
1183 	ZEND_ARG_INFO(0, name)
1184 	ZEND_ARG_INFO(0, namespaceURI)
1185 ZEND_END_ARG_INFO()
1186 
1187 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_getParserProperty, 0)
1188 	ZEND_ARG_INFO(0, property)
1189 ZEND_END_ARG_INFO()
1190 
1191 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_isValid, 0)
1192 ZEND_END_ARG_INFO()
1193 
1194 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_lookupNamespace, 0)
1195 ZEND_ARG_INFO(0, prefix)
1196 ZEND_END_ARG_INFO()
1197 
1198 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToAttribute, 0)
1199 	ZEND_ARG_INFO(0, name)
1200 ZEND_END_ARG_INFO()
1201 
1202 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToAttributeNo, 0)
1203 	ZEND_ARG_INFO(0, index)
1204 ZEND_END_ARG_INFO()
1205 
1206 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToAttributeNs, 0)
1207 	ZEND_ARG_INFO(0, name)
1208 	ZEND_ARG_INFO(0, namespaceURI)
1209 ZEND_END_ARG_INFO()
1210 
1211 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToElement, 0)
1212 ZEND_END_ARG_INFO()
1213 
1214 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToFirstAttribute, 0)
1215 ZEND_END_ARG_INFO()
1216 
1217 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToNextAttribute, 0)
1218 ZEND_END_ARG_INFO()
1219 
1220 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_read, 0)
1221 ZEND_END_ARG_INFO()
1222 
1223 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlreader_next, 0, 0, 0)
1224 	ZEND_ARG_INFO(0, localname)
1225 ZEND_END_ARG_INFO()
1226 
1227 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlreader_open, 0, 0, 1)
1228 	ZEND_ARG_INFO(0, URI)
1229 	ZEND_ARG_INFO(0, encoding)
1230 	ZEND_ARG_INFO(0, options)
1231 ZEND_END_ARG_INFO()
1232 
1233 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_readInnerXml, 0)
1234 ZEND_END_ARG_INFO()
1235 
1236 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_readOuterXml, 0)
1237 ZEND_END_ARG_INFO()
1238 
1239 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_readString, 0)
1240 ZEND_END_ARG_INFO()
1241 
1242 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_setSchema, 0)
1243 	ZEND_ARG_INFO(0, filename)
1244 ZEND_END_ARG_INFO()
1245 
1246 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_setParserProperty, 0)
1247 	ZEND_ARG_INFO(0, property)
1248 	ZEND_ARG_INFO(0, value)
1249 ZEND_END_ARG_INFO()
1250 
1251 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_setRelaxNGSchema, 0)
1252 	ZEND_ARG_INFO(0, filename)
1253 ZEND_END_ARG_INFO()
1254 
1255 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_setRelaxNGSchemaSource, 0)
1256 	ZEND_ARG_INFO(0, source)
1257 ZEND_END_ARG_INFO()
1258 
1259 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlreader_XML, 0, 0, 1)
1260 	ZEND_ARG_INFO(0, source)
1261 	ZEND_ARG_INFO(0, encoding)
1262 	ZEND_ARG_INFO(0, options)
1263 ZEND_END_ARG_INFO()
1264 
1265 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlreader_expand, 0, 0, 0)
1266 	ZEND_ARG_INFO(0, basenode)
1267 ZEND_END_ARG_INFO()
1268 /* }}} */
1269 
1270 static const zend_function_entry xmlreader_functions[] /* {{{ */ =  {
1271 	PHP_ME(xmlreader, close, arginfo_xmlreader_close, ZEND_ACC_PUBLIC)
1272 	PHP_ME(xmlreader, getAttribute, arginfo_xmlreader_getAttribute, ZEND_ACC_PUBLIC)
1273 	PHP_ME(xmlreader, getAttributeNo, arginfo_xmlreader_getAttributeNo, ZEND_ACC_PUBLIC)
1274 	PHP_ME(xmlreader, getAttributeNs, arginfo_xmlreader_getAttributeNs, ZEND_ACC_PUBLIC)
1275 	PHP_ME(xmlreader, getParserProperty, arginfo_xmlreader_getParserProperty, ZEND_ACC_PUBLIC)
1276 	PHP_ME(xmlreader, isValid, arginfo_xmlreader_isValid, ZEND_ACC_PUBLIC)
1277 	PHP_ME(xmlreader, lookupNamespace, arginfo_xmlreader_lookupNamespace, ZEND_ACC_PUBLIC)
1278 	PHP_ME(xmlreader, moveToAttributeNo, arginfo_xmlreader_moveToAttributeNo, ZEND_ACC_PUBLIC)
1279 	PHP_ME(xmlreader, moveToAttribute, arginfo_xmlreader_moveToAttribute, ZEND_ACC_PUBLIC)
1280 	PHP_ME(xmlreader, moveToAttributeNs, arginfo_xmlreader_moveToAttributeNs, ZEND_ACC_PUBLIC)
1281 	PHP_ME(xmlreader, moveToElement, arginfo_xmlreader_moveToElement, ZEND_ACC_PUBLIC)
1282 	PHP_ME(xmlreader, moveToFirstAttribute, arginfo_xmlreader_moveToFirstAttribute, ZEND_ACC_PUBLIC)
1283 	PHP_ME(xmlreader, moveToNextAttribute, arginfo_xmlreader_moveToNextAttribute, ZEND_ACC_PUBLIC)
1284 	PHP_ME(xmlreader, open, arginfo_xmlreader_open, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC)
1285 	PHP_ME(xmlreader, read, arginfo_xmlreader_read, ZEND_ACC_PUBLIC)
1286 	PHP_ME(xmlreader, next, arginfo_xmlreader_next, ZEND_ACC_PUBLIC)
1287 	PHP_ME(xmlreader, readInnerXml, arginfo_xmlreader_readInnerXml, ZEND_ACC_PUBLIC)
1288 	PHP_ME(xmlreader, readOuterXml, arginfo_xmlreader_readOuterXml, ZEND_ACC_PUBLIC)
1289 	PHP_ME(xmlreader, readString, arginfo_xmlreader_readString, ZEND_ACC_PUBLIC)
1290 	PHP_ME(xmlreader, setSchema, arginfo_xmlreader_setSchema, ZEND_ACC_PUBLIC)
1291 /* Not Yet Implemented though defined in libxml as of 2.6.9dev
1292 	PHP_ME(xmlreader, resetState, NULL, ZEND_ACC_PUBLIC)
1293 */
1294 	PHP_ME(xmlreader, setParserProperty, arginfo_xmlreader_setParserProperty, ZEND_ACC_PUBLIC)
1295 	PHP_ME(xmlreader, setRelaxNGSchema, arginfo_xmlreader_setRelaxNGSchema, ZEND_ACC_PUBLIC)
1296 	PHP_ME(xmlreader, setRelaxNGSchemaSource, arginfo_xmlreader_setRelaxNGSchemaSource, ZEND_ACC_PUBLIC)
1297 	PHP_ME(xmlreader, XML, arginfo_xmlreader_XML, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC)
1298 	PHP_ME(xmlreader, expand, arginfo_xmlreader_expand, ZEND_ACC_PUBLIC)
1299 	PHP_FE_END
1300 }; /* }}} */
1301 
1302 /* {{{ PHP_MINIT_FUNCTION
1303  */
PHP_MINIT_FUNCTION(xmlreader)1304 PHP_MINIT_FUNCTION(xmlreader)
1305 {
1306 
1307 	zend_class_entry ce;
1308 
1309 	memcpy(&xmlreader_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
1310 	xmlreader_object_handlers.offset = XtOffsetOf(xmlreader_object, std);
1311 	xmlreader_object_handlers.dtor_obj = zend_objects_destroy_object;
1312 	xmlreader_object_handlers.free_obj = xmlreader_objects_free_storage;
1313 	xmlreader_object_handlers.read_property = xmlreader_read_property;
1314 	xmlreader_object_handlers.write_property = xmlreader_write_property;
1315 	xmlreader_object_handlers.get_property_ptr_ptr = xmlreader_get_property_ptr_ptr;
1316 	xmlreader_object_handlers.clone_obj = NULL;
1317 
1318 	INIT_CLASS_ENTRY(ce, "XMLReader", xmlreader_functions);
1319 	ce.create_object = xmlreader_objects_new;
1320 	xmlreader_class_entry = zend_register_internal_class(&ce);
1321 
1322 	zend_hash_init(&xmlreader_prop_handlers, 0, NULL, php_xmlreader_free_prop_handler, 1);
1323 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "attributeCount", xmlTextReaderAttributeCount, NULL, IS_LONG);
1324 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "baseURI", NULL, xmlTextReaderConstBaseUri, IS_STRING);
1325 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "depth", xmlTextReaderDepth, NULL, IS_LONG);
1326 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "hasAttributes", xmlTextReaderHasAttributes, NULL, IS_FALSE);
1327 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "hasValue", xmlTextReaderHasValue, NULL, IS_FALSE);
1328 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "isDefault", xmlTextReaderIsDefault, NULL, IS_FALSE);
1329 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "isEmptyElement", xmlTextReaderIsEmptyElement, NULL, IS_FALSE);
1330 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "localName", NULL, xmlTextReaderConstLocalName, IS_STRING);
1331 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "name", NULL, xmlTextReaderConstName, IS_STRING);
1332 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "namespaceURI", NULL, xmlTextReaderConstNamespaceUri, IS_STRING);
1333 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "nodeType", xmlTextReaderNodeType, NULL, IS_LONG);
1334 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "prefix", NULL, xmlTextReaderConstPrefix, IS_STRING);
1335 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "value", NULL, xmlTextReaderConstValue, IS_STRING);
1336 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "xmlLang", NULL, xmlTextReaderConstXmlLang, IS_STRING);
1337 
1338 	/* Constants for NodeType - cannot define common types to share with dom as there are differences in these types */
1339 
1340 	REGISTER_XMLREADER_CLASS_CONST_LONG("NONE",	XML_READER_TYPE_NONE);
1341 	REGISTER_XMLREADER_CLASS_CONST_LONG("ELEMENT",	XML_READER_TYPE_ELEMENT);
1342 	REGISTER_XMLREADER_CLASS_CONST_LONG("ATTRIBUTE",	XML_READER_TYPE_ATTRIBUTE);
1343 	REGISTER_XMLREADER_CLASS_CONST_LONG("TEXT",	XML_READER_TYPE_TEXT);
1344 	REGISTER_XMLREADER_CLASS_CONST_LONG("CDATA",	XML_READER_TYPE_CDATA);
1345 	REGISTER_XMLREADER_CLASS_CONST_LONG("ENTITY_REF",	XML_READER_TYPE_ENTITY_REFERENCE);
1346 	REGISTER_XMLREADER_CLASS_CONST_LONG("ENTITY",	XML_READER_TYPE_ENTITY);
1347 	REGISTER_XMLREADER_CLASS_CONST_LONG("PI",	XML_READER_TYPE_PROCESSING_INSTRUCTION);
1348 	REGISTER_XMLREADER_CLASS_CONST_LONG("COMMENT",	XML_READER_TYPE_COMMENT);
1349 	REGISTER_XMLREADER_CLASS_CONST_LONG("DOC",	XML_READER_TYPE_DOCUMENT);
1350 	REGISTER_XMLREADER_CLASS_CONST_LONG("DOC_TYPE",	XML_READER_TYPE_DOCUMENT_TYPE);
1351 	REGISTER_XMLREADER_CLASS_CONST_LONG("DOC_FRAGMENT",	XML_READER_TYPE_DOCUMENT_FRAGMENT);
1352 	REGISTER_XMLREADER_CLASS_CONST_LONG("NOTATION",	XML_READER_TYPE_NOTATION);
1353 	REGISTER_XMLREADER_CLASS_CONST_LONG("WHITESPACE",	XML_READER_TYPE_WHITESPACE);
1354 	REGISTER_XMLREADER_CLASS_CONST_LONG("SIGNIFICANT_WHITESPACE",	XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
1355 	REGISTER_XMLREADER_CLASS_CONST_LONG("END_ELEMENT",	XML_READER_TYPE_END_ELEMENT);
1356 	REGISTER_XMLREADER_CLASS_CONST_LONG("END_ENTITY",	XML_READER_TYPE_END_ENTITY);
1357 	REGISTER_XMLREADER_CLASS_CONST_LONG("XML_DECLARATION",	XML_READER_TYPE_XML_DECLARATION);
1358 
1359 	/* Constants for Parser options */
1360 	REGISTER_XMLREADER_CLASS_CONST_LONG("LOADDTD",	XML_PARSER_LOADDTD);
1361 	REGISTER_XMLREADER_CLASS_CONST_LONG("DEFAULTATTRS",	XML_PARSER_DEFAULTATTRS);
1362 	REGISTER_XMLREADER_CLASS_CONST_LONG("VALIDATE",	XML_PARSER_VALIDATE);
1363 	REGISTER_XMLREADER_CLASS_CONST_LONG("SUBST_ENTITIES",	XML_PARSER_SUBST_ENTITIES);
1364 
1365 	/* Constants for Errors when loading - not yet used until we implement custom error handling
1366 	REGISTER_XMLREADER_CLASS_CONST_LONG("VALIDITY_WARNING",		XML_PARSER_SEVERITY_VALIDITY_WARNING,	CONST_CS | CONST_PERSISTENT);
1367 	REGISTER_XMLREADER_CLASS_CONST_LONG("VALIDITY_ERROR",		XML_PARSER_SEVERITY_VALIDITY_ERROR,		CONST_CS | CONST_PERSISTENT);
1368 	REGISTER_XMLREADER_CLASS_CONST_LONG("WARNING",				XML_PARSER_SEVERITY_WARNING,			CONST_CS | CONST_PERSISTENT);
1369 	REGISTER_XMLREADER_CLASS_CONST_LONG("ERROR",				XML_PARSER_SEVERITY_ERROR,				CONST_CS | CONST_PERSISTENT);
1370 	*/
1371 
1372 	return SUCCESS;
1373 }
1374 /* }}} */
1375 
1376 /* {{{ PHP_MSHUTDOWN_FUNCTION
1377  */
PHP_MSHUTDOWN_FUNCTION(xmlreader)1378 PHP_MSHUTDOWN_FUNCTION(xmlreader)
1379 {
1380 	zend_hash_destroy(&xmlreader_prop_handlers);
1381 	return SUCCESS;
1382 }
1383 /* }}} */
1384 
1385 /* {{{ PHP_MINFO_FUNCTION
1386  */
PHP_MINFO_FUNCTION(xmlreader)1387 PHP_MINFO_FUNCTION(xmlreader)
1388 {
1389 	php_info_print_table_start();
1390 	{
1391 		php_info_print_table_row(2, "XMLReader", "enabled");
1392 	}
1393 	php_info_print_table_end();
1394 }
1395 /* }}} */
1396