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