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