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