xref: /PHP-5.5/ext/xmlreader/php_xmlreader.c (revision 73c1be26)
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2015 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 		return;
592 	} else {
593 		RETURN_EMPTY_STRING();
594 	}
595 }
596 /* }}} */
597 
598 /* {{{ proto string XMLReader::getAttributeNs(string name, string namespaceURI)
599 Get value of a attribute via name and namespace from current element */
PHP_METHOD(xmlreader,getAttributeNs)600 PHP_METHOD(xmlreader, getAttributeNs)
601 {
602 	zval *id;
603 	int name_len = 0, ns_uri_len = 0;
604 	xmlreader_object *intern;
605 	char *name, *ns_uri, *retchar = NULL;
606 
607 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &ns_uri, &ns_uri_len) == FAILURE) {
608 		return;
609 	}
610 
611 	if (name_len == 0 || ns_uri_len == 0) {
612 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attribute Name and Namespace URI cannot be empty");
613 		RETURN_FALSE;
614 	}
615 
616 	id = getThis();
617 
618 	intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC);
619 	if (intern && intern->ptr) {
620 		retchar = (char *)xmlTextReaderGetAttributeNs(intern->ptr, (xmlChar *)name, (xmlChar *)ns_uri);
621 	}
622 	if (retchar) {
623 		RETVAL_STRING(retchar, 1);
624 		xmlFree(retchar);
625 		return;
626 	} else {
627 		RETURN_EMPTY_STRING();
628 	}
629 }
630 /* }}} */
631 
632 /* {{{ proto boolean XMLReader::getParserProperty(int property)
633 Indicates whether given property (one of the parser option constants) is set or not on parser */
PHP_METHOD(xmlreader,getParserProperty)634 PHP_METHOD(xmlreader, getParserProperty)
635 {
636 	zval *id;
637 	long property;
638 	int retval = -1;
639 	xmlreader_object *intern;
640 
641 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &property) == FAILURE) {
642 		return;
643 	}
644 
645 	id = getThis();
646 
647 	intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC);
648 	if (intern && intern->ptr) {
649 		retval = xmlTextReaderGetParserProp(intern->ptr,property);
650 	}
651 	if (retval == -1) {
652 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid parser property");
653 		RETURN_FALSE;
654 	}
655 
656 	RETURN_BOOL(retval);
657 }
658 /* }}} */
659 
660 /* {{{ proto boolean XMLReader::isValid()
661 Returns boolean indicating if parsed document is valid or not.
662 Must set XMLREADER_LOADDTD or XMLREADER_VALIDATE parser option prior to the first call to read
663 or this method will always return FALSE */
PHP_METHOD(xmlreader,isValid)664 PHP_METHOD(xmlreader, isValid)
665 {
666 	php_xmlreader_no_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderIsValid);
667 }
668 /* }}} */
669 
670 /* {{{ proto string XMLReader::lookupNamespace(string prefix)
671 Return namespaceURI for associated prefix on current node */
PHP_METHOD(xmlreader,lookupNamespace)672 PHP_METHOD(xmlreader, lookupNamespace)
673 {
674 	php_xmlreader_string_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderLookupNamespace);
675 }
676 /* }}} */
677 
678 /* {{{ proto boolean XMLReader::moveToAttribute(string name)
679 Positions reader at specified attribute - Returns TRUE on success and FALSE on failure */
PHP_METHOD(xmlreader,moveToAttribute)680 PHP_METHOD(xmlreader, moveToAttribute)
681 {
682 	zval *id;
683 	int name_len = 0, retval;
684 	xmlreader_object *intern;
685 	char *name;
686 
687 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
688 		return;
689 	}
690 
691 	if (name_len == 0) {
692 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attribute Name is required");
693 		RETURN_FALSE;
694 	}
695 
696 	id = getThis();
697 
698 	intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC);
699 	if (intern && intern->ptr) {
700 		retval = xmlTextReaderMoveToAttribute(intern->ptr, (xmlChar *)name);
701 		if (retval == 1) {
702 			RETURN_TRUE;
703 		}
704 	}
705 
706 	RETURN_FALSE;
707 }
708 /* }}} */
709 
710 /* {{{ proto boolean XMLReader::moveToAttributeNo(int index)
711 Positions reader at attribute at specified index.
712 Returns TRUE on success and FALSE on failure */
PHP_METHOD(xmlreader,moveToAttributeNo)713 PHP_METHOD(xmlreader, moveToAttributeNo)
714 {
715 	zval *id;
716 	long attr_pos;
717 	int retval;
718 	xmlreader_object *intern;
719 
720 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &attr_pos) == FAILURE) {
721 		return;
722 	}
723 
724 	id = getThis();
725 
726 	intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC);
727 	if (intern && intern->ptr) {
728 		retval = xmlTextReaderMoveToAttributeNo(intern->ptr, attr_pos);
729 		if (retval == 1) {
730 			RETURN_TRUE;
731 		}
732 	}
733 
734 	RETURN_FALSE;
735 }
736 /* }}} */
737 
738 /* {{{ proto boolean XMLReader::moveToAttributeNs(string name, string namespaceURI)
739 Positions reader at attribute spcified by name and namespaceURI.
740 Returns TRUE on success and FALSE on failure */
PHP_METHOD(xmlreader,moveToAttributeNs)741 PHP_METHOD(xmlreader, moveToAttributeNs)
742 {
743 	zval *id;
744 	int name_len=0, ns_uri_len=0, retval;
745 	xmlreader_object *intern;
746 	char *name, *ns_uri;
747 
748 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &ns_uri, &ns_uri_len) == FAILURE) {
749 		return;
750 	}
751 
752 	if (name_len == 0 || ns_uri_len == 0) {
753 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attribute Name and Namespace URI cannot be empty");
754 		RETURN_FALSE;
755 	}
756 
757 	id = getThis();
758 
759 	intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC);
760 	if (intern && intern->ptr) {
761 		retval = xmlTextReaderMoveToAttributeNs(intern->ptr, (xmlChar *)name, (xmlChar *)ns_uri);
762 		if (retval == 1) {
763 			RETURN_TRUE;
764 		}
765 	}
766 
767 	RETURN_FALSE;
768 }
769 /* }}} */
770 
771 /* {{{ proto boolean XMLReader::moveToElement()
772 Moves the position of the current instance to the node that contains the current Attribute node. */
PHP_METHOD(xmlreader,moveToElement)773 PHP_METHOD(xmlreader, moveToElement)
774 {
775 	php_xmlreader_no_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderMoveToElement);
776 }
777 /* }}} */
778 
779 /* {{{ proto boolean XMLReader::moveToFirstAttribute()
780 Moves the position of the current instance to the first attribute associated with the current node. */
PHP_METHOD(xmlreader,moveToFirstAttribute)781 PHP_METHOD(xmlreader, moveToFirstAttribute)
782 {
783 	php_xmlreader_no_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderMoveToFirstAttribute);
784 }
785 /* }}} */
786 
787 /* {{{ proto boolean XMLReader::moveToNextAttribute()
788 Moves the position of the current instance to the next attribute associated with the current node. */
PHP_METHOD(xmlreader,moveToNextAttribute)789 PHP_METHOD(xmlreader, moveToNextAttribute)
790 {
791 	php_xmlreader_no_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderMoveToNextAttribute);
792 }
793 /* }}} */
794 
795 /* {{{ proto boolean XMLReader::read()
796 Moves the position of the current instance to the next node in the stream. */
PHP_METHOD(xmlreader,read)797 PHP_METHOD(xmlreader, read)
798 {
799 	zval *id;
800 	int retval;
801 	xmlreader_object *intern;
802 
803 	id = getThis();
804 	intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC);
805 	if (intern != NULL && intern->ptr != NULL) {
806 		retval = xmlTextReaderRead(intern->ptr);
807 		if (retval == -1) {
808 			RETURN_FALSE;
809 		} else {
810 			RETURN_BOOL(retval);
811 		}
812 	}
813 
814 	php_error_docref(NULL TSRMLS_CC, E_WARNING, "Load Data before trying to read");
815 	RETURN_FALSE;
816 }
817 /* }}} */
818 
819 /* {{{ proto boolean XMLReader::next([string localname])
820 Moves the position of the current instance to the next node in the stream. */
PHP_METHOD(xmlreader,next)821 PHP_METHOD(xmlreader, next)
822 {
823 	zval *id;
824 	int retval, name_len=0;
825 	xmlreader_object *intern;
826 	char *name = NULL;
827 
828 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len) == FAILURE) {
829 		return;
830 	}
831 
832 	id = getThis();
833 	intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC);
834 	if (intern != NULL && intern->ptr != NULL) {
835 #if LIBXML_VERSION <= 20617
836 		/* Bug in libxml prevents a next in certain cases when positioned on end of element */
837 		if (xmlTextReaderNodeType(intern->ptr) == XML_READER_TYPE_END_ELEMENT) {
838 			retval = xmlTextReaderRead(intern->ptr);
839 		} else
840 #endif
841 		retval = xmlTextReaderNext(intern->ptr);
842 		while (name != NULL && retval == 1) {
843 			if (xmlStrEqual(xmlTextReaderConstLocalName(intern->ptr), (xmlChar *)name)) {
844 				RETURN_TRUE;
845 			}
846 			retval = xmlTextReaderNext(intern->ptr);
847 		}
848 		if (retval == -1) {
849 			RETURN_FALSE;
850 		} else {
851 			RETURN_BOOL(retval);
852 		}
853 	}
854 
855 	php_error_docref(NULL TSRMLS_CC, E_WARNING, "Load Data before trying to read");
856 	RETURN_FALSE;
857 }
858 /* }}} */
859 
860 /* {{{ proto boolean XMLReader::open(string URI [, string encoding [, int options]])
861 Sets the URI that the XMLReader will parse. */
PHP_METHOD(xmlreader,open)862 PHP_METHOD(xmlreader, open)
863 {
864 	zval *id;
865 	int source_len = 0, encoding_len = 0;
866 	long options = 0;
867 	xmlreader_object *intern = NULL;
868 	char *source, *valid_file = NULL;
869 	char *encoding = NULL;
870 	char resolved_path[MAXPATHLEN + 1];
871 	xmlTextReaderPtr reader = NULL;
872 
873 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|s!l", &source, &source_len, &encoding, &encoding_len, &options) == FAILURE) {
874 		return;
875 	}
876 
877 	id = getThis();
878 	if (id != NULL) {
879 		if (! instanceof_function(Z_OBJCE_P(id), xmlreader_class_entry TSRMLS_CC)) {
880 			id = NULL;
881 		} else {
882 			intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC);
883 			xmlreader_free_resources(intern);
884 		}
885 	}
886 
887 	if (!source_len) {
888 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string supplied as input");
889 		RETURN_FALSE;
890 	}
891 
892 	valid_file = _xmlreader_get_valid_file_path(source, resolved_path, MAXPATHLEN  TSRMLS_CC);
893 
894 	if (valid_file) {
895 		reader = xmlReaderForFile(valid_file, encoding, options);
896 	}
897 
898 	if (reader == NULL) {
899 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open source data");
900 		RETURN_FALSE;
901 	}
902 
903 	if (id == NULL) {
904 		object_init_ex(return_value, xmlreader_class_entry);
905 		intern = (xmlreader_object *)zend_objects_get_address(return_value TSRMLS_CC);
906 		intern->ptr = reader;
907 		return;
908 	}
909 
910 	intern->ptr = reader;
911 
912 	RETURN_TRUE;
913 
914 }
915 /* }}} */
916 
917 /* Not Yet Implemented in libxml - functions exist just not coded
918 PHP_METHOD(xmlreader, resetState)
919 {
920 
921 }
922 */
923 
924 #if LIBXML_VERSION >= 20620
925 /* {{{ proto string XMLReader::readInnerXml()
926 Reads the contents of the current node, including child nodes and markup. */
PHP_METHOD(xmlreader,readInnerXml)927 PHP_METHOD(xmlreader, readInnerXml)
928 {
929 	php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderReadInnerXml);
930 }
931 /* }}} */
932 
933 /* {{{ proto boolean XMLReader::readOuterXml()
934 Reads the contents of the current node, including child nodes and markup. */
PHP_METHOD(xmlreader,readOuterXml)935 PHP_METHOD(xmlreader, readOuterXml)
936 {
937 	php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderReadOuterXml);
938 }
939 /* }}} */
940 
941 /* {{{ proto boolean XMLReader::readString()
942 Reads the contents of an element or a text node as a string. */
PHP_METHOD(xmlreader,readString)943 PHP_METHOD(xmlreader, readString)
944 {
945 	php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderReadString);
946 }
947 /* }}} */
948 
949 /* {{{ proto boolean XMLReader::setSchema(string filename)
950 Use W3C XSD schema to validate the document as it is processed. Activation is only possible before the first Read(). */
PHP_METHOD(xmlreader,setSchema)951 PHP_METHOD(xmlreader, setSchema)
952 {
953 #ifdef LIBXML_SCHEMAS_ENABLED
954 	zval *id;
955 	int source_len = 0, retval = -1;
956 	xmlreader_object *intern;
957 	char *source;
958 
959 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p!", &source, &source_len) == FAILURE) {
960 		return;
961 	}
962 
963 	if (source != NULL && !source_len) {
964 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Schema data source is required");
965 		RETURN_FALSE;
966 	}
967 
968 	id = getThis();
969 
970 	intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC);
971 	if (intern && intern->ptr) {
972 		retval = xmlTextReaderSchemaValidate(intern->ptr, source);
973 
974 		if (retval == 0) {
975 			RETURN_TRUE;
976 		}
977 	}
978 
979 	php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set schema. This must be set prior to reading or schema contains errors.");
980 
981 	RETURN_FALSE;
982 #else
983 	php_error_docref(NULL TSRMLS_CC, E_WARNING, "No Schema support built into libxml.");
984 
985 	RETURN_FALSE;
986 #endif
987 }
988 /* }}} */
989 #endif
990 
991 /* {{{ proto boolean XMLReader::setParserProperty(int property, boolean value)
992 Sets parser property (one of the parser option constants).
993 Properties must be set after open() or XML() and before the first read() is called */
PHP_METHOD(xmlreader,setParserProperty)994 PHP_METHOD(xmlreader, setParserProperty)
995 {
996 	zval *id;
997 	long property;
998 	int retval = -1;
999 	zend_bool value;
1000 	xmlreader_object *intern;
1001 
1002 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lb", &property, &value) == FAILURE) {
1003 		return;
1004 	}
1005 
1006 	id = getThis();
1007 
1008 	intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC);
1009 	if (intern && intern->ptr) {
1010 		retval = xmlTextReaderSetParserProp(intern->ptr,property, value);
1011 	}
1012 	if (retval == -1) {
1013 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid parser property");
1014 		RETURN_FALSE;
1015 	}
1016 
1017 	RETURN_TRUE;
1018 }
1019 /* }}} */
1020 
1021 /* {{{ proto boolean XMLReader::setRelaxNGSchema(string filename)
1022 Sets the string that the XMLReader will parse. */
PHP_METHOD(xmlreader,setRelaxNGSchema)1023 PHP_METHOD(xmlreader, setRelaxNGSchema)
1024 {
1025 	php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAM_PASSTHRU, XMLREADER_LOAD_FILE);
1026 }
1027 /* }}} */
1028 
1029 /* {{{ proto boolean XMLReader::setRelaxNGSchemaSource(string source)
1030 Sets the string that the XMLReader will parse. */
PHP_METHOD(xmlreader,setRelaxNGSchemaSource)1031 PHP_METHOD(xmlreader, setRelaxNGSchemaSource)
1032 {
1033 	php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAM_PASSTHRU, XMLREADER_LOAD_STRING);
1034 }
1035 /* }}} */
1036 
1037 /* TODO
1038 XMLPUBFUN int XMLCALL
1039 		    xmlTextReaderSetSchema	(xmlTextReaderPtr reader,
1040 		    				 xmlSchemaPtr schema);
1041 */
1042 
1043 /* {{{ proto boolean XMLReader::XML(string source [, string encoding [, int options]])
1044 Sets the string that the XMLReader will parse. */
PHP_METHOD(xmlreader,XML)1045 PHP_METHOD(xmlreader, XML)
1046 {
1047 	zval *id;
1048 	int source_len = 0, encoding_len = 0;
1049 	long options = 0;
1050 	xmlreader_object *intern = NULL;
1051 	char *source, *uri = NULL, *encoding = NULL;
1052 	int resolved_path_len, ret = 0;
1053 	char *directory=NULL, resolved_path[MAXPATHLEN];
1054 	xmlParserInputBufferPtr inputbfr;
1055 	xmlTextReaderPtr reader;
1056 
1057 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!l", &source, &source_len, &encoding, &encoding_len, &options) == FAILURE) {
1058 		return;
1059 	}
1060 
1061 	id = getThis();
1062 	if (id != NULL && ! instanceof_function(Z_OBJCE_P(id), xmlreader_class_entry TSRMLS_CC)) {
1063 		id = NULL;
1064 	}
1065 	if (id != NULL) {
1066 		intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC);
1067 		xmlreader_free_resources(intern);
1068 	}
1069 
1070 	if (!source_len) {
1071 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string supplied as input");
1072 		RETURN_FALSE;
1073 	}
1074 
1075 	inputbfr = xmlParserInputBufferCreateMem(source, source_len, XML_CHAR_ENCODING_NONE);
1076 
1077     if (inputbfr != NULL) {
1078 /* Get the URI of the current script so that we can set the base directory in libxml */
1079 #if HAVE_GETCWD
1080 		directory = VCWD_GETCWD(resolved_path, MAXPATHLEN);
1081 #elif HAVE_GETWD
1082 		directory = VCWD_GETWD(resolved_path);
1083 #endif
1084 		if (directory) {
1085 			resolved_path_len = strlen(resolved_path);
1086 			if (resolved_path[resolved_path_len - 1] != DEFAULT_SLASH) {
1087 				resolved_path[resolved_path_len] = DEFAULT_SLASH;
1088 				resolved_path[++resolved_path_len] = '\0';
1089 			}
1090 			uri = (char *) xmlCanonicPath((const xmlChar *) resolved_path);
1091 		}
1092 		reader = xmlNewTextReader(inputbfr, uri);
1093 
1094 		if (reader != NULL) {
1095 #if LIBXML_VERSION >= 20628
1096 			ret = xmlTextReaderSetup(reader, NULL, uri, encoding, options);
1097 #endif
1098 			if (ret == 0) {
1099 				if (id == NULL) {
1100 					object_init_ex(return_value, xmlreader_class_entry);
1101 					intern = (xmlreader_object *)zend_objects_get_address(return_value TSRMLS_CC);
1102 				} else {
1103 					RETVAL_TRUE;
1104 				}
1105 				intern->input = inputbfr;
1106 				intern->ptr = reader;
1107 
1108 				if (uri) {
1109 					xmlFree(uri);
1110 				}
1111 
1112 				return;
1113 			}
1114 		}
1115 	}
1116 
1117 	if (uri) {
1118 		xmlFree(uri);
1119 	}
1120 
1121 	if (inputbfr) {
1122 		xmlFreeParserInputBuffer(inputbfr);
1123 	}
1124 	php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to load source data");
1125 	RETURN_FALSE;
1126 }
1127 /* }}} */
1128 
1129 /* {{{ proto boolean XMLReader::expand()
1130 Moves the position of the current instance to the next node in the stream. */
PHP_METHOD(xmlreader,expand)1131 PHP_METHOD(xmlreader, expand)
1132 {
1133 #ifdef HAVE_DOM
1134 	zval *id, *basenode = NULL;
1135 	int ret;
1136 	xmlreader_object *intern;
1137 	xmlNode *node, *nodec;
1138 	xmlDocPtr docp = NULL;
1139 	php_libxml_node_object *domobj = NULL;
1140 
1141 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|O!", &id, xmlreader_class_entry, &basenode, dom_node_class_entry) == FAILURE) {
1142 		return;
1143 	}
1144 
1145 	if (basenode != NULL) {
1146 		NODE_GET_OBJ(node, basenode, xmlNodePtr, domobj);
1147 		docp = node->doc;
1148 	}
1149 
1150 	intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC);
1151 
1152 	if (intern && intern->ptr) {
1153 		node = xmlTextReaderExpand(intern->ptr);
1154 
1155 		if (node == NULL) {
1156 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "An Error Occurred while expanding ");
1157 			RETURN_FALSE;
1158 		} else {
1159 			nodec = xmlDocCopyNode(node, docp, 1);
1160 			if (nodec == NULL) {
1161 				php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot expand this node type");
1162 				RETURN_FALSE;
1163 			} else {
1164 				DOM_RET_OBJ(nodec, &ret, (dom_object *)domobj);
1165 			}
1166 		}
1167 	} else {
1168 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Load Data before trying to expand");
1169 		RETURN_FALSE;
1170 	}
1171 #else
1172 	php_error(E_WARNING, "DOM support is not enabled");
1173 	return;
1174 #endif
1175 }
1176 /* }}} */
1177 /* {{{ arginfo */
1178 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_close, 0)
1179 ZEND_END_ARG_INFO()
1180 
1181 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_getAttribute, 0)
1182 	ZEND_ARG_INFO(0, name)
1183 ZEND_END_ARG_INFO()
1184 
1185 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_getAttributeNo, 0)
1186 	ZEND_ARG_INFO(0, index)
1187 ZEND_END_ARG_INFO()
1188 
1189 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_getAttributeNs, 0)
1190 	ZEND_ARG_INFO(0, name)
1191 	ZEND_ARG_INFO(0, namespaceURI)
1192 ZEND_END_ARG_INFO()
1193 
1194 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_getParserProperty, 0)
1195 	ZEND_ARG_INFO(0, property)
1196 ZEND_END_ARG_INFO()
1197 
1198 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_isValid, 0)
1199 ZEND_END_ARG_INFO()
1200 
1201 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_lookupNamespace, 0)
1202 ZEND_ARG_INFO(0, prefix)
1203 ZEND_END_ARG_INFO()
1204 
1205 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToAttribute, 0)
1206 	ZEND_ARG_INFO(0, name)
1207 ZEND_END_ARG_INFO()
1208 
1209 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToAttributeNo, 0)
1210 	ZEND_ARG_INFO(0, index)
1211 ZEND_END_ARG_INFO()
1212 
1213 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToAttributeNs, 0)
1214 	ZEND_ARG_INFO(0, name)
1215 	ZEND_ARG_INFO(0, namespaceURI)
1216 ZEND_END_ARG_INFO()
1217 
1218 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToElement, 0)
1219 ZEND_END_ARG_INFO()
1220 
1221 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToFirstAttribute, 0)
1222 ZEND_END_ARG_INFO()
1223 
1224 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToNextAttribute, 0)
1225 ZEND_END_ARG_INFO()
1226 
1227 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_read, 0)
1228 ZEND_END_ARG_INFO()
1229 
1230 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlreader_next, 0, 0, 0)
1231 	ZEND_ARG_INFO(0, localname)
1232 ZEND_END_ARG_INFO()
1233 
1234 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlreader_open, 0, 0, 1)
1235 	ZEND_ARG_INFO(0, URI)
1236 	ZEND_ARG_INFO(0, encoding)
1237 	ZEND_ARG_INFO(0, options)
1238 ZEND_END_ARG_INFO()
1239 
1240 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_readInnerXml, 0)
1241 ZEND_END_ARG_INFO()
1242 
1243 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_readOuterXml, 0)
1244 ZEND_END_ARG_INFO()
1245 
1246 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_readString, 0)
1247 ZEND_END_ARG_INFO()
1248 
1249 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_setSchema, 0)
1250 	ZEND_ARG_INFO(0, filename)
1251 ZEND_END_ARG_INFO()
1252 
1253 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_setParserProperty, 0)
1254 	ZEND_ARG_INFO(0, property)
1255 	ZEND_ARG_INFO(0, value)
1256 ZEND_END_ARG_INFO()
1257 
1258 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_setRelaxNGSchema, 0)
1259 	ZEND_ARG_INFO(0, filename)
1260 ZEND_END_ARG_INFO()
1261 
1262 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_setRelaxNGSchemaSource, 0)
1263 	ZEND_ARG_INFO(0, source)
1264 ZEND_END_ARG_INFO()
1265 
1266 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlreader_XML, 0, 0, 1)
1267 	ZEND_ARG_INFO(0, source)
1268 	ZEND_ARG_INFO(0, encoding)
1269 	ZEND_ARG_INFO(0, options)
1270 ZEND_END_ARG_INFO()
1271 
1272 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_expand, 0)
1273 ZEND_END_ARG_INFO()
1274 /* }}} */
1275 
1276 static const zend_function_entry xmlreader_functions[] = {
1277 	PHP_ME(xmlreader, close, arginfo_xmlreader_close, ZEND_ACC_PUBLIC)
1278 	PHP_ME(xmlreader, getAttribute, arginfo_xmlreader_getAttribute, ZEND_ACC_PUBLIC)
1279 	PHP_ME(xmlreader, getAttributeNo, arginfo_xmlreader_getAttributeNo, ZEND_ACC_PUBLIC)
1280 	PHP_ME(xmlreader, getAttributeNs, arginfo_xmlreader_getAttributeNs, ZEND_ACC_PUBLIC)
1281 	PHP_ME(xmlreader, getParserProperty, arginfo_xmlreader_getParserProperty, ZEND_ACC_PUBLIC)
1282 	PHP_ME(xmlreader, isValid, arginfo_xmlreader_isValid, ZEND_ACC_PUBLIC)
1283 	PHP_ME(xmlreader, lookupNamespace, arginfo_xmlreader_lookupNamespace, ZEND_ACC_PUBLIC)
1284 	PHP_ME(xmlreader, moveToAttributeNo, arginfo_xmlreader_moveToAttributeNo, ZEND_ACC_PUBLIC)
1285 	PHP_ME(xmlreader, moveToAttribute, arginfo_xmlreader_moveToAttribute, ZEND_ACC_PUBLIC)
1286 	PHP_ME(xmlreader, moveToAttributeNs, arginfo_xmlreader_moveToAttributeNs, ZEND_ACC_PUBLIC)
1287 	PHP_ME(xmlreader, moveToElement, arginfo_xmlreader_moveToElement, ZEND_ACC_PUBLIC)
1288 	PHP_ME(xmlreader, moveToFirstAttribute, arginfo_xmlreader_moveToFirstAttribute, ZEND_ACC_PUBLIC)
1289 	PHP_ME(xmlreader, moveToNextAttribute, arginfo_xmlreader_moveToNextAttribute, ZEND_ACC_PUBLIC)
1290 	PHP_ME(xmlreader, open, arginfo_xmlreader_open, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC)
1291 	PHP_ME(xmlreader, read, arginfo_xmlreader_read, ZEND_ACC_PUBLIC)
1292 	PHP_ME(xmlreader, next, arginfo_xmlreader_next, ZEND_ACC_PUBLIC)
1293 #if LIBXML_VERSION >= 20620
1294 	PHP_ME(xmlreader, readInnerXml, arginfo_xmlreader_readInnerXml, ZEND_ACC_PUBLIC)
1295 	PHP_ME(xmlreader, readOuterXml, arginfo_xmlreader_readOuterXml, ZEND_ACC_PUBLIC)
1296 	PHP_ME(xmlreader, readString, arginfo_xmlreader_readString, ZEND_ACC_PUBLIC)
1297 	PHP_ME(xmlreader, setSchema, arginfo_xmlreader_setSchema, ZEND_ACC_PUBLIC)
1298 #endif
1299 /* Not Yet Implemented though defined in libxml as of 2.6.9dev
1300 	PHP_ME(xmlreader, resetState, NULL, ZEND_ACC_PUBLIC)
1301 */
1302 	PHP_ME(xmlreader, setParserProperty, arginfo_xmlreader_setParserProperty, ZEND_ACC_PUBLIC)
1303 	PHP_ME(xmlreader, setRelaxNGSchema, arginfo_xmlreader_setRelaxNGSchema, ZEND_ACC_PUBLIC)
1304 	PHP_ME(xmlreader, setRelaxNGSchemaSource, arginfo_xmlreader_setRelaxNGSchemaSource, ZEND_ACC_PUBLIC)
1305 	PHP_ME(xmlreader, XML, arginfo_xmlreader_XML, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC)
1306 	PHP_ME(xmlreader, expand, arginfo_xmlreader_expand, ZEND_ACC_PUBLIC)
1307 	PHP_FE_END
1308 };
1309 
1310 /* {{{ PHP_MINIT_FUNCTION
1311  */
PHP_MINIT_FUNCTION(xmlreader)1312 PHP_MINIT_FUNCTION(xmlreader)
1313 {
1314 
1315 	zend_class_entry ce;
1316 
1317 	memcpy(&xmlreader_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1318 	xmlreader_object_handlers.read_property = xmlreader_read_property;
1319 	xmlreader_object_handlers.write_property = xmlreader_write_property;
1320 	xmlreader_object_handlers.get_property_ptr_ptr = xmlreader_get_property_ptr_ptr;
1321 	xmlreader_object_handlers.clone_obj = NULL;
1322 
1323 	INIT_CLASS_ENTRY(ce, "XMLReader", xmlreader_functions);
1324 	ce.create_object = xmlreader_objects_new;
1325 	xmlreader_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
1326 
1327 	zend_hash_init(&xmlreader_prop_handlers, 0, NULL, NULL, 1);
1328 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "attributeCount", xmlTextReaderAttributeCount, NULL, IS_LONG TSRMLS_CC);
1329 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "baseURI", NULL, xmlTextReaderConstBaseUri, IS_STRING TSRMLS_CC);
1330 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "depth", xmlTextReaderDepth, NULL, IS_LONG TSRMLS_CC);
1331 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "hasAttributes", xmlTextReaderHasAttributes, NULL, IS_BOOL TSRMLS_CC);
1332 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "hasValue", xmlTextReaderHasValue, NULL, IS_BOOL TSRMLS_CC);
1333 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "isDefault", xmlTextReaderIsDefault, NULL, IS_BOOL TSRMLS_CC);
1334 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "isEmptyElement", xmlTextReaderIsEmptyElement, NULL, IS_BOOL TSRMLS_CC);
1335 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "localName", NULL, xmlTextReaderConstLocalName, IS_STRING TSRMLS_CC);
1336 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "name", NULL, xmlTextReaderConstName, IS_STRING TSRMLS_CC);
1337 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "namespaceURI", NULL, xmlTextReaderConstNamespaceUri, IS_STRING TSRMLS_CC);
1338 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "nodeType", xmlTextReaderNodeType, NULL, IS_LONG TSRMLS_CC);
1339 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "prefix", NULL, xmlTextReaderConstPrefix, IS_STRING TSRMLS_CC);
1340 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "value", NULL, xmlTextReaderConstValue, IS_STRING TSRMLS_CC);
1341 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "xmlLang", NULL, xmlTextReaderConstXmlLang, IS_STRING TSRMLS_CC);
1342 
1343 	/* Constants for NodeType - cannot define common types to share with dom as there are differences in these types */
1344 
1345 	REGISTER_XMLREADER_CLASS_CONST_LONG("NONE",	XML_READER_TYPE_NONE);
1346 	REGISTER_XMLREADER_CLASS_CONST_LONG("ELEMENT",	XML_READER_TYPE_ELEMENT);
1347 	REGISTER_XMLREADER_CLASS_CONST_LONG("ATTRIBUTE",	XML_READER_TYPE_ATTRIBUTE);
1348 	REGISTER_XMLREADER_CLASS_CONST_LONG("TEXT",	XML_READER_TYPE_TEXT);
1349 	REGISTER_XMLREADER_CLASS_CONST_LONG("CDATA",	XML_READER_TYPE_CDATA);
1350 	REGISTER_XMLREADER_CLASS_CONST_LONG("ENTITY_REF",	XML_READER_TYPE_ENTITY_REFERENCE);
1351 	REGISTER_XMLREADER_CLASS_CONST_LONG("ENTITY",	XML_READER_TYPE_ENTITY);
1352 	REGISTER_XMLREADER_CLASS_CONST_LONG("PI",	XML_READER_TYPE_PROCESSING_INSTRUCTION);
1353 	REGISTER_XMLREADER_CLASS_CONST_LONG("COMMENT",	XML_READER_TYPE_COMMENT);
1354 	REGISTER_XMLREADER_CLASS_CONST_LONG("DOC",	XML_READER_TYPE_DOCUMENT);
1355 	REGISTER_XMLREADER_CLASS_CONST_LONG("DOC_TYPE",	XML_READER_TYPE_DOCUMENT_TYPE);
1356 	REGISTER_XMLREADER_CLASS_CONST_LONG("DOC_FRAGMENT",	XML_READER_TYPE_DOCUMENT_FRAGMENT);
1357 	REGISTER_XMLREADER_CLASS_CONST_LONG("NOTATION",	XML_READER_TYPE_NOTATION);
1358 	REGISTER_XMLREADER_CLASS_CONST_LONG("WHITESPACE",	XML_READER_TYPE_WHITESPACE);
1359 	REGISTER_XMLREADER_CLASS_CONST_LONG("SIGNIFICANT_WHITESPACE",	XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
1360 	REGISTER_XMLREADER_CLASS_CONST_LONG("END_ELEMENT",	XML_READER_TYPE_END_ELEMENT);
1361 	REGISTER_XMLREADER_CLASS_CONST_LONG("END_ENTITY",	XML_READER_TYPE_END_ENTITY);
1362 	REGISTER_XMLREADER_CLASS_CONST_LONG("XML_DECLARATION",	XML_READER_TYPE_XML_DECLARATION);
1363 
1364 	/* Constants for Parser options */
1365 	REGISTER_XMLREADER_CLASS_CONST_LONG("LOADDTD",	XML_PARSER_LOADDTD);
1366 	REGISTER_XMLREADER_CLASS_CONST_LONG("DEFAULTATTRS",	XML_PARSER_DEFAULTATTRS);
1367 	REGISTER_XMLREADER_CLASS_CONST_LONG("VALIDATE",	XML_PARSER_VALIDATE);
1368 	REGISTER_XMLREADER_CLASS_CONST_LONG("SUBST_ENTITIES",	XML_PARSER_SUBST_ENTITIES);
1369 
1370 	/* Constants for Errors when loading - not yet used until we implement custom error handling
1371 	REGISTER_XMLREADER_CLASS_CONST_LONG("VALIDITY_WARNING",		XML_PARSER_SEVERITY_VALIDITY_WARNING,	CONST_CS | CONST_PERSISTENT);
1372 	REGISTER_XMLREADER_CLASS_CONST_LONG("VALIDITY_ERROR",		XML_PARSER_SEVERITY_VALIDITY_ERROR,		CONST_CS | CONST_PERSISTENT);
1373 	REGISTER_XMLREADER_CLASS_CONST_LONG("WARNING",				XML_PARSER_SEVERITY_WARNING,			CONST_CS | CONST_PERSISTENT);
1374 	REGISTER_XMLREADER_CLASS_CONST_LONG("ERROR",				XML_PARSER_SEVERITY_ERROR,				CONST_CS | CONST_PERSISTENT);
1375 	*/
1376 
1377 	return SUCCESS;
1378 }
1379 /* }}} */
1380 
1381 /* {{{ PHP_MSHUTDOWN_FUNCTION
1382  */
PHP_MSHUTDOWN_FUNCTION(xmlreader)1383 PHP_MSHUTDOWN_FUNCTION(xmlreader)
1384 {
1385 	zend_hash_destroy(&xmlreader_prop_handlers);
1386 	return SUCCESS;
1387 }
1388 /* }}} */
1389 
1390 /* {{{ PHP_MINFO_FUNCTION
1391  */
PHP_MINFO_FUNCTION(xmlreader)1392 PHP_MINFO_FUNCTION(xmlreader)
1393 {
1394 	php_info_print_table_start();
1395 	{
1396 		php_info_print_table_row(2, "XMLReader", "enabled");
1397 	}
1398 	php_info_print_table_end();
1399 }
1400 /* }}} */
1401 
1402 /*
1403  * Local variables:
1404  * tab-width: 4
1405  * c-basic-offset: 4
1406  * End:
1407  * vim600: noet sw=4 ts=4 fdm=marker
1408  * vim<600: noet sw=4 ts=4
1409  */
1410