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