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