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