xref: /PHP-5.3/ext/xmlreader/php_xmlreader.c (revision a2045ff3)
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2013 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/uri.h>
34 
35 zend_class_entry *xmlreader_class_entry;
36 
37 static zend_object_handlers xmlreader_object_handlers;
38 
39 static HashTable xmlreader_prop_handlers;
40 
41 typedef int (*xmlreader_read_int_t)(xmlTextReaderPtr reader);
42 typedef unsigned char *(*xmlreader_read_char_t)(xmlTextReaderPtr reader);
43 typedef const unsigned char *(*xmlreader_read_const_char_t)(xmlTextReaderPtr reader);
44 typedef int (*xmlreader_write_t)(xmlreader_object *obj, zval *newval TSRMLS_DC);
45 
46 typedef unsigned char *(*xmlreader_read_one_char_t)(xmlTextReaderPtr reader, const unsigned char *);
47 
48 typedef struct _xmlreader_prop_handler {
49 	xmlreader_read_int_t read_int_func;
50 	xmlreader_read_const_char_t read_char_func;
51 	xmlreader_write_t write_func;
52 	int type;
53 } xmlreader_prop_handler;
54 
55 #define XMLREADER_LOAD_STRING 0
56 #define XMLREADER_LOAD_FILE 1
57 
58 /* {{{ xmlreader_register_prop_handler */
xmlreader_register_prop_handler(HashTable * prop_handler,char * name,xmlreader_read_int_t read_int_func,xmlreader_read_const_char_t read_char_func,int rettype TSRMLS_DC)59 static void xmlreader_register_prop_handler(HashTable *prop_handler, char *name, xmlreader_read_int_t read_int_func, xmlreader_read_const_char_t read_char_func, int rettype TSRMLS_DC)
60 {
61 	xmlreader_prop_handler hnd;
62 
63 	hnd.read_char_func = read_char_func;
64 	hnd.read_int_func = read_int_func;
65 	hnd.type = rettype;
66 	zend_hash_add(prop_handler, name, strlen(name)+1, &hnd, sizeof(xmlreader_prop_handler), NULL);
67 }
68 /* }}} */
69 
70 /* {{{ xmlreader_property_reader */
xmlreader_property_reader(xmlreader_object * obj,xmlreader_prop_handler * hnd,zval ** retval TSRMLS_DC)71 static int xmlreader_property_reader(xmlreader_object *obj, xmlreader_prop_handler *hnd, zval **retval TSRMLS_DC)
72 {
73 	const xmlChar *retchar = NULL;
74 	int retint = 0;
75 
76 	if (obj->ptr != NULL) {
77 		if (hnd->read_char_func) {
78 			retchar = hnd->read_char_func(obj->ptr);
79 		} else {
80 			if (hnd->read_int_func) {
81 				retint = hnd->read_int_func(obj->ptr);
82 				if (retint == -1) {
83 					php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal libxml error returned");
84 					return FAILURE;
85 				}
86 			}
87 		}
88 	}
89 
90 	ALLOC_ZVAL(*retval);
91 
92 	switch (hnd->type) {
93 		case IS_STRING:
94 			if (retchar) {
95 				ZVAL_STRING(*retval, (char *) retchar, 1);
96 			} else {
97 				ZVAL_EMPTY_STRING(*retval);
98 			}
99 			break;
100 		case IS_BOOL:
101 			ZVAL_BOOL(*retval, retint);
102 			break;
103 		case IS_LONG:
104 			ZVAL_LONG(*retval, retint);
105 			break;
106 		default:
107 			ZVAL_NULL(*retval);
108 	}
109 
110 	return SUCCESS;
111 }
112 /* }}} */
113 
114 /* {{{ xmlreader_get_property_ptr_ptr */
xmlreader_get_property_ptr_ptr(zval * object,zval * member TSRMLS_DC)115 zval **xmlreader_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC)
116 {
117 	xmlreader_object *obj;
118 	zval tmp_member;
119 	zval **retval = NULL;
120 	xmlreader_prop_handler *hnd;
121 	zend_object_handlers *std_hnd;
122 	int ret = FAILURE;
123 
124  	if (member->type != IS_STRING) {
125 		tmp_member = *member;
126 		zval_copy_ctor(&tmp_member);
127 		convert_to_string(&tmp_member);
128 		member = &tmp_member;
129 	}
130 
131 	obj = (xmlreader_object *)zend_objects_get_address(object TSRMLS_CC);
132 
133 	if (obj->prop_handler != NULL) {
134 		ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
135 	}
136 	if (ret == FAILURE) {
137 		std_hnd = zend_get_std_object_handlers();
138 		retval = std_hnd->get_property_ptr_ptr(object, member TSRMLS_CC);
139 	}
140 
141 	if (member == &tmp_member) {
142 		zval_dtor(member);
143 	}
144 	return retval;
145 }
146 /* }}} */
147 
148 /* {{{ xmlreader_read_property */
xmlreader_read_property(zval * object,zval * member,int type TSRMLS_DC)149 zval *xmlreader_read_property(zval *object, zval *member, int type TSRMLS_DC)
150 {
151 	xmlreader_object *obj;
152 	zval tmp_member;
153 	zval *retval;
154 	xmlreader_prop_handler *hnd;
155 	zend_object_handlers *std_hnd;
156 	int ret;
157 
158  	if (member->type != IS_STRING) {
159 		tmp_member = *member;
160 		zval_copy_ctor(&tmp_member);
161 		convert_to_string(&tmp_member);
162 		member = &tmp_member;
163 	}
164 
165 	ret = FAILURE;
166 	obj = (xmlreader_object *)zend_objects_get_address(object TSRMLS_CC);
167 
168 	if (obj->prop_handler != NULL) {
169 		ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
170 	}
171 	if (ret == SUCCESS) {
172 		ret = xmlreader_property_reader(obj, hnd, &retval TSRMLS_CC);
173 		if (ret == SUCCESS) {
174 			/* ensure we're creating a temporary variable */
175 			Z_SET_REFCOUNT_P(retval, 0);
176 		} else {
177 			retval = EG(uninitialized_zval_ptr);
178 		}
179 	} else {
180 		std_hnd = zend_get_std_object_handlers();
181 		retval = std_hnd->read_property(object, member, type TSRMLS_CC);
182 	}
183 
184 	if (member == &tmp_member) {
185 		zval_dtor(member);
186 	}
187 	return retval;
188 }
189 /* }}} */
190 
191 /* {{{ xmlreader_write_property */
xmlreader_write_property(zval * object,zval * member,zval * value TSRMLS_DC)192 void xmlreader_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
193 {
194 	xmlreader_object *obj;
195 	zval tmp_member;
196 	xmlreader_prop_handler *hnd;
197 	zend_object_handlers *std_hnd;
198 	int ret;
199 
200  	if (member->type != IS_STRING) {
201 		tmp_member = *member;
202 		zval_copy_ctor(&tmp_member);
203 		convert_to_string(&tmp_member);
204 		member = &tmp_member;
205 	}
206 
207 	ret = FAILURE;
208 	obj = (xmlreader_object *)zend_objects_get_address(object TSRMLS_CC);
209 
210 	if (obj->prop_handler != NULL) {
211 		ret = zend_hash_find((HashTable *)obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd);
212 	}
213 	if (ret == SUCCESS) {
214 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot write to read-only property");
215 	} else {
216 		std_hnd = zend_get_std_object_handlers();
217 		std_hnd->write_property(object, member, value TSRMLS_CC);
218 	}
219 
220 	if (member == &tmp_member) {
221 		zval_dtor(member);
222 	}
223 }
224 /* }}} */
225 
226 /* {{{ _xmlreader_get_valid_file_path */
227 /* _xmlreader_get_valid_file_path and _xmlreader_get_relaxNG should be made a
228 	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)229 char *_xmlreader_get_valid_file_path(char *source, char *resolved_path, int resolved_path_len  TSRMLS_DC) {
230 	xmlURI *uri;
231 	xmlChar *escsource;
232 	char *file_dest;
233 	int isFileUri = 0;
234 
235 	uri = xmlCreateURI();
236 	escsource = xmlURIEscapeStr((xmlChar *)source, (xmlChar *)":");
237 	xmlParseURIReference(uri, (const char *)escsource);
238 	xmlFree(escsource);
239 
240 	if (uri->scheme != NULL) {
241 		/* absolute file uris - libxml only supports localhost or empty host */
242 		if (strncasecmp(source, "file:///",8) == 0) {
243 			isFileUri = 1;
244 #ifdef PHP_WIN32
245 			source += 8;
246 #else
247 			source += 7;
248 #endif
249 		} else if (strncasecmp(source, "file://localhost/",17) == 0) {
250 			isFileUri = 1;
251 #ifdef PHP_WIN32
252 			source += 17;
253 #else
254 			source += 16;
255 #endif
256 		}
257 	}
258 
259 	file_dest = source;
260 
261 	if ((uri->scheme == NULL || isFileUri)) {
262 		if (!VCWD_REALPATH(source, resolved_path) && !expand_filepath(source, resolved_path TSRMLS_CC)) {
263 			xmlFreeURI(uri);
264 			return NULL;
265 		}
266 		file_dest = resolved_path;
267 	}
268 
269 	xmlFreeURI(uri);
270 
271 	return file_dest;
272 }
273 /* }}} */
274 
275 #ifdef LIBXML_SCHEMAS_ENABLED
276 /* {{{ _xmlreader_get_relaxNG */
_xmlreader_get_relaxNG(char * source,int source_len,int type,xmlRelaxNGValidityErrorFunc error_func,xmlRelaxNGValidityWarningFunc warn_func TSRMLS_DC)277 static xmlRelaxNGPtr _xmlreader_get_relaxNG(char *source, int source_len, int type,
278 											xmlRelaxNGValidityErrorFunc error_func,
279 											xmlRelaxNGValidityWarningFunc warn_func TSRMLS_DC)
280 {
281 	char *valid_file = NULL;
282 	xmlRelaxNGParserCtxtPtr parser = NULL;
283 	xmlRelaxNGPtr           sptr;
284 	char resolved_path[MAXPATHLEN + 1];
285 
286 	switch (type) {
287 	case XMLREADER_LOAD_FILE:
288 		valid_file = _xmlreader_get_valid_file_path(source, resolved_path, MAXPATHLEN  TSRMLS_CC);
289 		if (!valid_file) {
290 			return NULL;
291 		}
292 		parser = xmlRelaxNGNewParserCtxt(valid_file);
293 		break;
294 	case XMLREADER_LOAD_STRING:
295 		parser = xmlRelaxNGNewMemParserCtxt(source, source_len);
296 		/* If loading from memory, we need to set the base directory for the document
297 		   but it is not apparent how to do that for schema's */
298 		break;
299 	default:
300 		return NULL;
301 	}
302 
303 	if (parser == NULL) {
304 		return NULL;
305 	}
306 
307 	if (error_func || warn_func) {
308 		xmlRelaxNGSetParserErrors(parser,
309 			(xmlRelaxNGValidityErrorFunc) error_func,
310 			(xmlRelaxNGValidityWarningFunc) warn_func,
311 			parser);
312 	}
313 	sptr = xmlRelaxNGParse(parser);
314 	xmlRelaxNGFreeParserCtxt(parser);
315 
316 	return sptr;
317 }
318 /* }}} */
319 #endif
320 
321 static const zend_module_dep xmlreader_deps[] = {
322 	ZEND_MOD_REQUIRED("libxml")
323 	ZEND_MOD_END
324 };
325 
326 /* {{{ xmlreader_module_entry
327  */
328 zend_module_entry xmlreader_module_entry = {
329 	STANDARD_MODULE_HEADER_EX, NULL,
330 	xmlreader_deps,
331 	"xmlreader",
332 	NULL,
333 	PHP_MINIT(xmlreader),
334 	PHP_MSHUTDOWN(xmlreader),
335 	NULL,
336 	NULL,
337 	PHP_MINFO(xmlreader),
338 	"0.1", /* Replace with version number for your extension */
339 	STANDARD_MODULE_PROPERTIES
340 };
341 /* }}} */
342 
343 #ifdef COMPILE_DL_XMLREADER
ZEND_GET_MODULE(xmlreader)344 ZEND_GET_MODULE(xmlreader)
345 #endif
346 
347 /* {{{ xmlreader_objects_clone */
348 void xmlreader_objects_clone(void *object, void **object_clone TSRMLS_DC)
349 {
350 	/* TODO */
351 }
352 /* }}} */
353 
354 /* {{{ xmlreader_free_resources */
xmlreader_free_resources(xmlreader_object * intern)355 static void xmlreader_free_resources(xmlreader_object *intern) {
356 	if (intern) {
357 		if (intern->input) {
358 			xmlFreeParserInputBuffer(intern->input);
359 			intern->input = NULL;
360 		}
361 
362 		if (intern->ptr) {
363 			xmlFreeTextReader(intern->ptr);
364 			intern->ptr = NULL;
365 		}
366 #ifdef LIBXML_SCHEMAS_ENABLED
367 		if (intern->schema) {
368 			xmlRelaxNGFree((xmlRelaxNGPtr) intern->schema);
369 			intern->schema = NULL;
370 		}
371 #endif
372 	}
373 }
374 /* }}} */
375 
376 /* {{{ xmlreader_objects_free_storage */
xmlreader_objects_free_storage(void * object TSRMLS_DC)377 void xmlreader_objects_free_storage(void *object TSRMLS_DC)
378 {
379 	xmlreader_object *intern = (xmlreader_object *)object;
380 
381 	zend_object_std_dtor(&intern->std TSRMLS_CC);
382 
383 	xmlreader_free_resources(intern);
384 
385 	efree(object);
386 }
387 /* }}} */
388 
389 /* {{{ xmlreader_objects_new */
xmlreader_objects_new(zend_class_entry * class_type TSRMLS_DC)390 zend_object_value xmlreader_objects_new(zend_class_entry *class_type TSRMLS_DC)
391 {
392 	zend_object_value retval;
393 	xmlreader_object *intern;
394 	zval *tmp;
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 	zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *));
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, "s!", &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 spcecified 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 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "An Error Occured while reading");
809 			RETURN_FALSE;
810 		} else {
811 			RETURN_BOOL(retval);
812 		}
813 	}
814 
815 	php_error_docref(NULL TSRMLS_CC, E_WARNING, "Load Data before trying to read");
816 	RETURN_FALSE;
817 }
818 /* }}} */
819 
820 /* {{{ proto boolean XMLReader::next([string localname])
821 Moves the position of the current instance to the next node in the stream. */
PHP_METHOD(xmlreader,next)822 PHP_METHOD(xmlreader, next)
823 {
824 	zval *id;
825 	int retval, name_len=0;
826 	xmlreader_object *intern;
827 	char *name = NULL;
828 
829 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len) == FAILURE) {
830 		return;
831 	}
832 
833 	id = getThis();
834 	intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC);
835 	if (intern != NULL && intern->ptr != NULL) {
836 #if LIBXML_VERSION <= 20617
837 		/* Bug in libxml prevents a next in certain cases when positioned on end of element */
838 		if (xmlTextReaderNodeType(intern->ptr) == XML_READER_TYPE_END_ELEMENT) {
839 			retval = xmlTextReaderRead(intern->ptr);
840 		} else
841 #endif
842 		retval = xmlTextReaderNext(intern->ptr);
843 		while (name != NULL && retval == 1) {
844 			if (xmlStrEqual(xmlTextReaderConstLocalName(intern->ptr), (xmlChar *)name)) {
845 				RETURN_TRUE;
846 			}
847 			retval = xmlTextReaderNext(intern->ptr);
848 		}
849 		if (retval == -1) {
850 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "An Error Occured while reading");
851 			RETURN_FALSE;
852 		} else {
853 			RETURN_BOOL(retval);
854 		}
855 	}
856 
857 	php_error_docref(NULL TSRMLS_CC, E_WARNING, "Load Data before trying to read");
858 	RETURN_FALSE;
859 }
860 /* }}} */
861 
862 /* {{{ proto boolean XMLReader::open(string URI [, string encoding [, int options]])
863 Sets the URI that the XMLReader will parse. */
PHP_METHOD(xmlreader,open)864 PHP_METHOD(xmlreader, open)
865 {
866 	zval *id;
867 	int source_len = 0, encoding_len = 0;
868 	long options = 0;
869 	xmlreader_object *intern = NULL;
870 	char *source, *valid_file = NULL;
871 	char *encoding = NULL;
872 	char resolved_path[MAXPATHLEN + 1];
873 	xmlTextReaderPtr reader = NULL;
874 
875 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!l", &source, &source_len, &encoding, &encoding_len, &options) == FAILURE) {
876 		return;
877 	}
878 
879 	id = getThis();
880 	if (id != NULL) {
881 		if (! instanceof_function(Z_OBJCE_P(id), xmlreader_class_entry TSRMLS_CC)) {
882 			id = NULL;
883 		} else {
884 			intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC);
885 			xmlreader_free_resources(intern);
886 		}
887 	}
888 
889 	if (!source_len) {
890 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string supplied as input");
891 		RETURN_FALSE;
892 	}
893 
894 	valid_file = _xmlreader_get_valid_file_path(source, resolved_path, MAXPATHLEN  TSRMLS_CC);
895 
896 	if (valid_file) {
897 		reader = xmlReaderForFile(valid_file, encoding, options);
898 	}
899 
900 	if (reader == NULL) {
901 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open source data");
902 		RETURN_FALSE;
903 	}
904 
905 	if (id == NULL) {
906 		object_init_ex(return_value, xmlreader_class_entry);
907 		intern = (xmlreader_object *)zend_objects_get_address(return_value TSRMLS_CC);
908 		intern->ptr = reader;
909 		return;
910 	}
911 
912 	intern->ptr = reader;
913 
914 	RETURN_TRUE;
915 
916 }
917 /* }}} */
918 
919 /* Not Yet Implemented in libxml - functions exist just not coded
920 PHP_METHOD(xmlreader, resetState)
921 {
922 
923 }
924 */
925 
926 #if LIBXML_VERSION >= 20620
927 /* {{{ proto string XMLReader::readInnerXml()
928 Reads the contents of the current node, including child nodes and markup. */
PHP_METHOD(xmlreader,readInnerXml)929 PHP_METHOD(xmlreader, readInnerXml)
930 {
931 	php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderReadInnerXml);
932 }
933 /* }}} */
934 
935 /* {{{ proto boolean XMLReader::readOuterXml()
936 Reads the contents of the current node, including child nodes and markup. */
PHP_METHOD(xmlreader,readOuterXml)937 PHP_METHOD(xmlreader, readOuterXml)
938 {
939 	php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderReadOuterXml);
940 }
941 /* }}} */
942 
943 /* {{{ proto boolean XMLReader::readString()
944 Reads the contents of an element or a text node as a string. */
PHP_METHOD(xmlreader,readString)945 PHP_METHOD(xmlreader, readString)
946 {
947 	php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderReadString);
948 }
949 /* }}} */
950 
951 /* {{{ proto boolean XMLReader::setSchema(string filename)
952 Use W3C XSD schema to validate the document as it is processed. Activation is only possible before the first Read(). */
PHP_METHOD(xmlreader,setSchema)953 PHP_METHOD(xmlreader, setSchema)
954 {
955 #ifdef LIBXML_SCHEMAS_ENABLED
956 	zval *id;
957 	int source_len = 0, retval = -1;
958 	xmlreader_object *intern;
959 	char *source;
960 
961 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!", &source, &source_len) == FAILURE) {
962 		return;
963 	}
964 
965 	if (source != NULL && !source_len) {
966 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Schema data source is required");
967 		RETURN_FALSE;
968 	}
969 
970 	id = getThis();
971 
972 	intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC);
973 	if (intern && intern->ptr) {
974 		retval = xmlTextReaderSchemaValidate(intern->ptr, source);
975 
976 		if (retval == 0) {
977 			RETURN_TRUE;
978 		}
979 	}
980 
981 	php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set schema. This must be set prior to reading or schema contains errors.");
982 
983 	RETURN_FALSE;
984 #else
985 	php_error_docref(NULL TSRMLS_CC, E_WARNING, "No Schema support built into libxml.");
986 
987 	RETURN_FALSE;
988 #endif
989 }
990 /* }}} */
991 #endif
992 
993 /* {{{ proto boolean XMLReader::setParserProperty(int property, boolean value)
994 Sets parser property (one of the parser option constants).
995 Properties must be set after open() or XML() and before the first read() is called */
PHP_METHOD(xmlreader,setParserProperty)996 PHP_METHOD(xmlreader, setParserProperty)
997 {
998 	zval *id;
999 	long property;
1000 	int retval = -1;
1001 	zend_bool value;
1002 	xmlreader_object *intern;
1003 
1004 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lb", &property, &value) == FAILURE) {
1005 		return;
1006 	}
1007 
1008 	id = getThis();
1009 
1010 	intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC);
1011 	if (intern && intern->ptr) {
1012 		retval = xmlTextReaderSetParserProp(intern->ptr,property, value);
1013 	}
1014 	if (retval == -1) {
1015 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid parser property");
1016 		RETURN_FALSE;
1017 	}
1018 
1019 	RETURN_TRUE;
1020 }
1021 /* }}} */
1022 
1023 /* {{{ proto boolean XMLReader::setRelaxNGSchema(string filename)
1024 Sets the string that the XMLReader will parse. */
PHP_METHOD(xmlreader,setRelaxNGSchema)1025 PHP_METHOD(xmlreader, setRelaxNGSchema)
1026 {
1027 	php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAM_PASSTHRU, XMLREADER_LOAD_FILE);
1028 }
1029 /* }}} */
1030 
1031 /* {{{ proto boolean XMLReader::setRelaxNGSchemaSource(string source)
1032 Sets the string that the XMLReader will parse. */
PHP_METHOD(xmlreader,setRelaxNGSchemaSource)1033 PHP_METHOD(xmlreader, setRelaxNGSchemaSource)
1034 {
1035 	php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAM_PASSTHRU, XMLREADER_LOAD_STRING);
1036 }
1037 /* }}} */
1038 
1039 /* TODO
1040 XMLPUBFUN int XMLCALL
1041 		    xmlTextReaderSetSchema	(xmlTextReaderPtr reader,
1042 		    				 xmlSchemaPtr schema);
1043 */
1044 
1045 /* {{{ proto boolean XMLReader::XML(string source [, string encoding [, int options]])
1046 Sets the string that the XMLReader will parse. */
PHP_METHOD(xmlreader,XML)1047 PHP_METHOD(xmlreader, XML)
1048 {
1049 	zval *id;
1050 	int source_len = 0, encoding_len = 0;
1051 	long options = 0;
1052 	xmlreader_object *intern = NULL;
1053 	char *source, *uri = NULL, *encoding = NULL;
1054 	int resolved_path_len, ret = 0;
1055 	char *directory=NULL, resolved_path[MAXPATHLEN];
1056 	xmlParserInputBufferPtr inputbfr;
1057 	xmlTextReaderPtr reader;
1058 
1059 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!l", &source, &source_len, &encoding, &encoding_len, &options) == FAILURE) {
1060 		return;
1061 	}
1062 
1063 	id = getThis();
1064 	if (id != NULL && ! instanceof_function(Z_OBJCE_P(id), xmlreader_class_entry TSRMLS_CC)) {
1065 		id = NULL;
1066 	}
1067 	if (id != NULL) {
1068 		intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC);
1069 		xmlreader_free_resources(intern);
1070 	}
1071 
1072 	if (!source_len) {
1073 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty string supplied as input");
1074 		RETURN_FALSE;
1075 	}
1076 
1077 	inputbfr = xmlParserInputBufferCreateMem(source, source_len, XML_CHAR_ENCODING_NONE);
1078 
1079     if (inputbfr != NULL) {
1080 /* Get the URI of the current script so that we can set the base directory in libxml */
1081 #if HAVE_GETCWD
1082 		directory = VCWD_GETCWD(resolved_path, MAXPATHLEN);
1083 #elif HAVE_GETWD
1084 		directory = VCWD_GETWD(resolved_path);
1085 #endif
1086 		if (directory) {
1087 			resolved_path_len = strlen(resolved_path);
1088 			if (resolved_path[resolved_path_len - 1] != DEFAULT_SLASH) {
1089 				resolved_path[resolved_path_len] = DEFAULT_SLASH;
1090 				resolved_path[++resolved_path_len] = '\0';
1091 			}
1092 			uri = (char *) xmlCanonicPath((const xmlChar *) resolved_path);
1093 		}
1094 		reader = xmlNewTextReader(inputbfr, uri);
1095 
1096 		if (reader != NULL) {
1097 #if LIBXML_VERSION >= 20628
1098 			ret = xmlTextReaderSetup(reader, NULL, uri, encoding, options);
1099 #endif
1100 			if (ret == 0) {
1101 				if (id == NULL) {
1102 					object_init_ex(return_value, xmlreader_class_entry);
1103 					intern = (xmlreader_object *)zend_objects_get_address(return_value TSRMLS_CC);
1104 				} else {
1105 					RETVAL_TRUE;
1106 				}
1107 				intern->input = inputbfr;
1108 				intern->ptr = reader;
1109 
1110 				if (uri) {
1111 					xmlFree(uri);
1112 				}
1113 
1114 				return;
1115 			}
1116 		}
1117 	}
1118 
1119 	if (uri) {
1120 		xmlFree(uri);
1121 	}
1122 
1123 	if (inputbfr) {
1124 		xmlFreeParserInputBuffer(inputbfr);
1125 	}
1126 	php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to load source data");
1127 	RETURN_FALSE;
1128 }
1129 /* }}} */
1130 
1131 /* {{{ proto boolean XMLReader::expand()
1132 Moves the position of the current instance to the next node in the stream. */
PHP_METHOD(xmlreader,expand)1133 PHP_METHOD(xmlreader, expand)
1134 {
1135 #ifdef HAVE_DOM
1136 	zval *id, *rv = NULL, *basenode = NULL;
1137 	int ret;
1138 	xmlreader_object *intern;
1139 	xmlNode *node, *nodec;
1140 	xmlDocPtr docp = NULL;
1141 	php_libxml_node_object *domobj = NULL;
1142 
1143 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|O!", &id, xmlreader_class_entry, &basenode, dom_node_class_entry) == FAILURE) {
1144 		return;
1145 	}
1146 
1147 	if (basenode != NULL) {
1148 		NODE_GET_OBJ(node, basenode, xmlNodePtr, domobj);
1149 		docp = node->doc;
1150 	}
1151 
1152 	intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC);
1153 
1154 	if (intern && intern->ptr) {
1155 		node = xmlTextReaderExpand(intern->ptr);
1156 
1157 		if (node == NULL) {
1158 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "An Error Occured while expanding ");
1159 			RETURN_FALSE;
1160 		} else {
1161 			nodec = xmlDocCopyNode(node, docp, 1);
1162 			if (nodec == NULL) {
1163 				php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot expand this node type");
1164 				RETURN_FALSE;
1165 			} else {
1166 				DOM_RET_OBJ(rv, nodec, &ret, (dom_object *)domobj);
1167 			}
1168 		}
1169 	} else {
1170 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Load Data before trying to expand");
1171 		RETURN_FALSE;
1172 	}
1173 #else
1174 	php_error(E_WARNING, "DOM support is not enabled");
1175 	return;
1176 #endif
1177 }
1178 /* }}} */
1179 /* {{{ arginfo */
1180 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_close, 0)
1181 ZEND_END_ARG_INFO()
1182 
1183 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_getAttribute, 0)
1184 	ZEND_ARG_INFO(0, name)
1185 ZEND_END_ARG_INFO()
1186 
1187 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_getAttributeNo, 0)
1188 	ZEND_ARG_INFO(0, index)
1189 ZEND_END_ARG_INFO()
1190 
1191 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_getAttributeNs, 0)
1192 	ZEND_ARG_INFO(0, name)
1193 	ZEND_ARG_INFO(0, namespaceURI)
1194 ZEND_END_ARG_INFO()
1195 
1196 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_getParserProperty, 0)
1197 	ZEND_ARG_INFO(0, property)
1198 ZEND_END_ARG_INFO()
1199 
1200 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_isValid, 0)
1201 ZEND_END_ARG_INFO()
1202 
1203 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_lookupNamespace, 0)
1204 ZEND_ARG_INFO(0, prefix)
1205 ZEND_END_ARG_INFO()
1206 
1207 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToAttribute, 0)
1208 	ZEND_ARG_INFO(0, name)
1209 ZEND_END_ARG_INFO()
1210 
1211 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToAttributeNo, 0)
1212 	ZEND_ARG_INFO(0, index)
1213 ZEND_END_ARG_INFO()
1214 
1215 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToAttributeNs, 0)
1216 	ZEND_ARG_INFO(0, name)
1217 	ZEND_ARG_INFO(0, namespaceURI)
1218 ZEND_END_ARG_INFO()
1219 
1220 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToElement, 0)
1221 ZEND_END_ARG_INFO()
1222 
1223 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToFirstAttribute, 0)
1224 ZEND_END_ARG_INFO()
1225 
1226 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToNextAttribute, 0)
1227 ZEND_END_ARG_INFO()
1228 
1229 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_read, 0)
1230 ZEND_END_ARG_INFO()
1231 
1232 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlreader_next, 0, 0, 0)
1233 	ZEND_ARG_INFO(0, localname)
1234 ZEND_END_ARG_INFO()
1235 
1236 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlreader_open, 0, 0, 1)
1237 	ZEND_ARG_INFO(0, URI)
1238 	ZEND_ARG_INFO(0, encoding)
1239 	ZEND_ARG_INFO(0, options)
1240 ZEND_END_ARG_INFO()
1241 
1242 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_readInnerXml, 0)
1243 ZEND_END_ARG_INFO()
1244 
1245 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_readOuterXml, 0)
1246 ZEND_END_ARG_INFO()
1247 
1248 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_readString, 0)
1249 ZEND_END_ARG_INFO()
1250 
1251 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_setSchema, 0)
1252 	ZEND_ARG_INFO(0, filename)
1253 ZEND_END_ARG_INFO()
1254 
1255 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_setParserProperty, 0)
1256 	ZEND_ARG_INFO(0, property)
1257 	ZEND_ARG_INFO(0, value)
1258 ZEND_END_ARG_INFO()
1259 
1260 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_setRelaxNGSchema, 0)
1261 	ZEND_ARG_INFO(0, filename)
1262 ZEND_END_ARG_INFO()
1263 
1264 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_setRelaxNGSchemaSource, 0)
1265 	ZEND_ARG_INFO(0, source)
1266 ZEND_END_ARG_INFO()
1267 
1268 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlreader_XML, 0, 0, 1)
1269 	ZEND_ARG_INFO(0, source)
1270 	ZEND_ARG_INFO(0, encoding)
1271 	ZEND_ARG_INFO(0, options)
1272 ZEND_END_ARG_INFO()
1273 
1274 ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_expand, 0)
1275 ZEND_END_ARG_INFO()
1276 /* }}} */
1277 
1278 static const zend_function_entry xmlreader_functions[] = {
1279 	PHP_ME(xmlreader, close, arginfo_xmlreader_close, ZEND_ACC_PUBLIC)
1280 	PHP_ME(xmlreader, getAttribute, arginfo_xmlreader_getAttribute, ZEND_ACC_PUBLIC)
1281 	PHP_ME(xmlreader, getAttributeNo, arginfo_xmlreader_getAttributeNo, ZEND_ACC_PUBLIC)
1282 	PHP_ME(xmlreader, getAttributeNs, arginfo_xmlreader_getAttributeNs, ZEND_ACC_PUBLIC)
1283 	PHP_ME(xmlreader, getParserProperty, arginfo_xmlreader_getParserProperty, ZEND_ACC_PUBLIC)
1284 	PHP_ME(xmlreader, isValid, arginfo_xmlreader_isValid, ZEND_ACC_PUBLIC)
1285 	PHP_ME(xmlreader, lookupNamespace, arginfo_xmlreader_lookupNamespace, ZEND_ACC_PUBLIC)
1286 	PHP_ME(xmlreader, moveToAttributeNo, arginfo_xmlreader_moveToAttributeNo, ZEND_ACC_PUBLIC)
1287 	PHP_ME(xmlreader, moveToAttribute, arginfo_xmlreader_moveToAttribute, ZEND_ACC_PUBLIC)
1288 	PHP_ME(xmlreader, moveToAttributeNs, arginfo_xmlreader_moveToAttributeNs, ZEND_ACC_PUBLIC)
1289 	PHP_ME(xmlreader, moveToElement, arginfo_xmlreader_moveToElement, ZEND_ACC_PUBLIC)
1290 	PHP_ME(xmlreader, moveToFirstAttribute, arginfo_xmlreader_moveToFirstAttribute, ZEND_ACC_PUBLIC)
1291 	PHP_ME(xmlreader, moveToNextAttribute, arginfo_xmlreader_moveToNextAttribute, ZEND_ACC_PUBLIC)
1292 	PHP_ME(xmlreader, open, arginfo_xmlreader_open, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC)
1293 	PHP_ME(xmlreader, read, arginfo_xmlreader_read, ZEND_ACC_PUBLIC)
1294 	PHP_ME(xmlreader, next, arginfo_xmlreader_next, ZEND_ACC_PUBLIC)
1295 #if LIBXML_VERSION >= 20620
1296 	PHP_ME(xmlreader, readInnerXml, arginfo_xmlreader_readInnerXml, ZEND_ACC_PUBLIC)
1297 	PHP_ME(xmlreader, readOuterXml, arginfo_xmlreader_readOuterXml, ZEND_ACC_PUBLIC)
1298 	PHP_ME(xmlreader, readString, arginfo_xmlreader_readString, ZEND_ACC_PUBLIC)
1299 	PHP_ME(xmlreader, setSchema, arginfo_xmlreader_setSchema, ZEND_ACC_PUBLIC)
1300 #endif
1301 /* Not Yet Implemented though defined in libxml as of 2.6.9dev
1302 	PHP_ME(xmlreader, resetState, NULL, ZEND_ACC_PUBLIC)
1303 */
1304 	PHP_ME(xmlreader, setParserProperty, arginfo_xmlreader_setParserProperty, ZEND_ACC_PUBLIC)
1305 	PHP_ME(xmlreader, setRelaxNGSchema, arginfo_xmlreader_setRelaxNGSchema, ZEND_ACC_PUBLIC)
1306 	PHP_ME(xmlreader, setRelaxNGSchemaSource, arginfo_xmlreader_setRelaxNGSchemaSource, ZEND_ACC_PUBLIC)
1307 	PHP_ME(xmlreader, XML, arginfo_xmlreader_XML, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC)
1308 	PHP_ME(xmlreader, expand, arginfo_xmlreader_expand, ZEND_ACC_PUBLIC)
1309 	PHP_FE_END
1310 };
1311 
1312 /* {{{ PHP_MINIT_FUNCTION
1313  */
PHP_MINIT_FUNCTION(xmlreader)1314 PHP_MINIT_FUNCTION(xmlreader)
1315 {
1316 
1317 	zend_class_entry ce;
1318 
1319 	memcpy(&xmlreader_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1320 	xmlreader_object_handlers.read_property = xmlreader_read_property;
1321 	xmlreader_object_handlers.write_property = xmlreader_write_property;
1322 	xmlreader_object_handlers.get_property_ptr_ptr = xmlreader_get_property_ptr_ptr;
1323 
1324 	INIT_CLASS_ENTRY(ce, "XMLReader", xmlreader_functions);
1325 	ce.create_object = xmlreader_objects_new;
1326 	xmlreader_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
1327 
1328 	zend_hash_init(&xmlreader_prop_handlers, 0, NULL, NULL, 1);
1329 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "attributeCount", xmlTextReaderAttributeCount, NULL, IS_LONG TSRMLS_CC);
1330 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "baseURI", NULL, xmlTextReaderConstBaseUri, IS_STRING TSRMLS_CC);
1331 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "depth", xmlTextReaderDepth, NULL, IS_LONG TSRMLS_CC);
1332 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "hasAttributes", xmlTextReaderHasAttributes, NULL, IS_BOOL TSRMLS_CC);
1333 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "hasValue", xmlTextReaderHasValue, NULL, IS_BOOL TSRMLS_CC);
1334 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "isDefault", xmlTextReaderIsDefault, NULL, IS_BOOL TSRMLS_CC);
1335 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "isEmptyElement", xmlTextReaderIsEmptyElement, NULL, IS_BOOL TSRMLS_CC);
1336 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "localName", NULL, xmlTextReaderConstLocalName, IS_STRING TSRMLS_CC);
1337 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "name", NULL, xmlTextReaderConstName, IS_STRING TSRMLS_CC);
1338 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "namespaceURI", NULL, xmlTextReaderConstNamespaceUri, IS_STRING TSRMLS_CC);
1339 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "nodeType", xmlTextReaderNodeType, NULL, IS_LONG TSRMLS_CC);
1340 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "prefix", NULL, xmlTextReaderConstPrefix, IS_STRING TSRMLS_CC);
1341 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "value", NULL, xmlTextReaderConstValue, IS_STRING TSRMLS_CC);
1342 	xmlreader_register_prop_handler(&xmlreader_prop_handlers, "xmlLang", NULL, xmlTextReaderConstXmlLang, IS_STRING TSRMLS_CC);
1343 
1344 	/* Constants for NodeType - cannot define common types to share with dom as there are differences in these types */
1345 
1346 	REGISTER_XMLREADER_CLASS_CONST_LONG("NONE",	XML_READER_TYPE_NONE);
1347 	REGISTER_XMLREADER_CLASS_CONST_LONG("ELEMENT",	XML_READER_TYPE_ELEMENT);
1348 	REGISTER_XMLREADER_CLASS_CONST_LONG("ATTRIBUTE",	XML_READER_TYPE_ATTRIBUTE);
1349 	REGISTER_XMLREADER_CLASS_CONST_LONG("TEXT",	XML_READER_TYPE_TEXT);
1350 	REGISTER_XMLREADER_CLASS_CONST_LONG("CDATA",	XML_READER_TYPE_CDATA);
1351 	REGISTER_XMLREADER_CLASS_CONST_LONG("ENTITY_REF",	XML_READER_TYPE_ENTITY_REFERENCE);
1352 	REGISTER_XMLREADER_CLASS_CONST_LONG("ENTITY",	XML_READER_TYPE_ENTITY);
1353 	REGISTER_XMLREADER_CLASS_CONST_LONG("PI",	XML_READER_TYPE_PROCESSING_INSTRUCTION);
1354 	REGISTER_XMLREADER_CLASS_CONST_LONG("COMMENT",	XML_READER_TYPE_COMMENT);
1355 	REGISTER_XMLREADER_CLASS_CONST_LONG("DOC",	XML_READER_TYPE_DOCUMENT);
1356 	REGISTER_XMLREADER_CLASS_CONST_LONG("DOC_TYPE",	XML_READER_TYPE_DOCUMENT_TYPE);
1357 	REGISTER_XMLREADER_CLASS_CONST_LONG("DOC_FRAGMENT",	XML_READER_TYPE_DOCUMENT_FRAGMENT);
1358 	REGISTER_XMLREADER_CLASS_CONST_LONG("NOTATION",	XML_READER_TYPE_NOTATION);
1359 	REGISTER_XMLREADER_CLASS_CONST_LONG("WHITESPACE",	XML_READER_TYPE_WHITESPACE);
1360 	REGISTER_XMLREADER_CLASS_CONST_LONG("SIGNIFICANT_WHITESPACE",	XML_READER_TYPE_SIGNIFICANT_WHITESPACE);
1361 	REGISTER_XMLREADER_CLASS_CONST_LONG("END_ELEMENT",	XML_READER_TYPE_END_ELEMENT);
1362 	REGISTER_XMLREADER_CLASS_CONST_LONG("END_ENTITY",	XML_READER_TYPE_END_ENTITY);
1363 	REGISTER_XMLREADER_CLASS_CONST_LONG("XML_DECLARATION",	XML_READER_TYPE_XML_DECLARATION);
1364 
1365 	/* Constants for Parser options */
1366 	REGISTER_XMLREADER_CLASS_CONST_LONG("LOADDTD",	XML_PARSER_LOADDTD);
1367 	REGISTER_XMLREADER_CLASS_CONST_LONG("DEFAULTATTRS",	XML_PARSER_DEFAULTATTRS);
1368 	REGISTER_XMLREADER_CLASS_CONST_LONG("VALIDATE",	XML_PARSER_VALIDATE);
1369 	REGISTER_XMLREADER_CLASS_CONST_LONG("SUBST_ENTITIES",	XML_PARSER_SUBST_ENTITIES);
1370 
1371 	/* Constants for Errors when loading - not yet used until we implement custom error handling
1372 	REGISTER_XMLREADER_CLASS_CONST_LONG("VALIDITY_WARNING",		XML_PARSER_SEVERITY_VALIDITY_WARNING,	CONST_CS | CONST_PERSISTENT);
1373 	REGISTER_XMLREADER_CLASS_CONST_LONG("VALIDITY_ERROR",		XML_PARSER_SEVERITY_VALIDITY_ERROR,		CONST_CS | CONST_PERSISTENT);
1374 	REGISTER_XMLREADER_CLASS_CONST_LONG("WARNING",				XML_PARSER_SEVERITY_WARNING,			CONST_CS | CONST_PERSISTENT);
1375 	REGISTER_XMLREADER_CLASS_CONST_LONG("ERROR",				XML_PARSER_SEVERITY_ERROR,				CONST_CS | CONST_PERSISTENT);
1376 	*/
1377 
1378 	return SUCCESS;
1379 }
1380 /* }}} */
1381 
1382 /* {{{ PHP_MSHUTDOWN_FUNCTION
1383  */
PHP_MSHUTDOWN_FUNCTION(xmlreader)1384 PHP_MSHUTDOWN_FUNCTION(xmlreader)
1385 {
1386 	zend_hash_destroy(&xmlreader_prop_handlers);
1387 	return SUCCESS;
1388 }
1389 /* }}} */
1390 
1391 /* {{{ PHP_MINFO_FUNCTION
1392  */
PHP_MINFO_FUNCTION(xmlreader)1393 PHP_MINFO_FUNCTION(xmlreader)
1394 {
1395 	php_info_print_table_start();
1396 	{
1397 		php_info_print_table_row(2, "XMLReader", "enabled");
1398 	}
1399 	php_info_print_table_end();
1400 }
1401 /* }}} */
1402 
1403 /*
1404  * Local variables:
1405  * tab-width: 4
1406  * c-basic-offset: 4
1407  * End:
1408  * vim600: noet sw=4 ts=4 fdm=marker
1409  * vim<600: noet sw=4 ts=4
1410  */
1411