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