1 | /* |
2 | +----------------------------------------------------------------------+ |
3 | | PHP Version 5 | |
4 | +----------------------------------------------------------------------+ |
5 | | Copyright (c) 1997-2015 The PHP Group | |
6 | +----------------------------------------------------------------------+ |
7 | | This source file is subject to version 3.01 of the PHP license, | |
8 | | that is bundled with this package in the file LICENSE, and is | |
9 | | available through the world-wide-web at the following url: | |
10 | | http://www.php.net/license/3_01.txt | |
11 | | If you did not receive a copy of the PHP license and are unable to | |
12 | | obtain it through the world-wide-web, please send a note to | |
13 | | license@php.net so we can mail you a copy immediately. | |
14 | +----------------------------------------------------------------------+ |
15 | | Author: Rob Richards <rrichards@php.net> | |
16 | +----------------------------------------------------------------------+ |
17 | */ |
18 | |
19 | /* $Id$ */ |
20 | |
21 | #ifdef HAVE_CONFIG_H |
22 | #include "config.h" |
23 | #endif |
24 | |
25 | |
26 | #include "php.h" |
27 | #include "php_ini.h" |
28 | #include "ext/standard/info.h" |
29 | #include "php_xmlreader.h" |
30 | #ifdef HAVE_DOM |
31 | #include "ext/dom/xml_common.h" |
32 | #endif |
33 | #include <libxml/xmlreader.h> |
34 | #include <libxml/uri.h> |
35 | |
36 | zend_class_entry *xmlreader_class_entry; |
37 | |
38 | static zend_object_handlers xmlreader_object_handlers; |
39 | |
40 | static HashTable xmlreader_prop_handlers; |
41 | |
42 | typedef int (*xmlreader_read_int_t)(xmlTextReaderPtr reader); |
43 | typedef unsigned char *(*xmlreader_read_char_t)(xmlTextReaderPtr reader); |
44 | typedef const unsigned char *(*xmlreader_read_const_char_t)(xmlTextReaderPtr reader); |
45 | typedef int (*xmlreader_write_t)(xmlreader_object *obj, zval *newval TSRMLS_DC); |
46 | |
47 | typedef unsigned char *(*xmlreader_read_one_char_t)(xmlTextReaderPtr reader, const unsigned char *); |
48 | |
49 | typedef struct _xmlreader_prop_handler { |
50 | xmlreader_read_int_t read_int_func; |
51 | xmlreader_read_const_char_t read_char_func; |
52 | xmlreader_write_t write_func; |
53 | int type; |
54 | } xmlreader_prop_handler; |
55 | |
56 | #define XMLREADER_LOAD_STRING 0 |
57 | #define XMLREADER_LOAD_FILE 1 |
58 | |
59 | /* {{{ xmlreader_register_prop_handler */ |
60 | static void xmlreader_register_prop_handler(HashTable *prop_handler, char *name, xmlreader_read_int_t read_int_func, xmlreader_read_const_char_t read_char_func, int rettype TSRMLS_DC) |
61 | { |
62 | xmlreader_prop_handler hnd; |
63 | |
64 | hnd.read_char_func = read_char_func; |
65 | hnd.read_int_func = read_int_func; |
66 | hnd.type = rettype; |
67 | zend_hash_add(prop_handler, name, strlen(name)+1, &hnd, sizeof(xmlreader_prop_handler), NULL); |
68 | } |
69 | /* }}} */ |
70 | |
71 | /* {{{ xmlreader_property_reader */ |
72 | static int xmlreader_property_reader(xmlreader_object *obj, xmlreader_prop_handler *hnd, zval **retval TSRMLS_DC) |
73 | { |
74 | const xmlChar *retchar = NULL; |
75 | int retint = 0; |
76 | |
77 | if (obj->ptr != NULL) { |
78 | if (hnd->read_char_func) { |
79 | retchar = hnd->read_char_func(obj->ptr); |
80 | } else { |
81 | if (hnd->read_int_func) { |
82 | retint = hnd->read_int_func(obj->ptr); |
83 | if (retint == -1) { |
84 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal libxml error returned" ); |
85 | return FAILURE; |
86 | } |
87 | } |
88 | } |
89 | } |
90 | |
91 | ALLOC_ZVAL(*retval); |
92 | |
93 | switch (hnd->type) { |
94 | case IS_STRING: |
95 | if (retchar) { |
96 | ZVAL_STRING(*retval, (char *) retchar, 1); |
97 | } else { |
98 | ZVAL_EMPTY_STRING(*retval); |
99 | } |
100 | break; |
101 | case IS_BOOL: |
102 | ZVAL_BOOL(*retval, retint); |
103 | break; |
104 | case IS_LONG: |
105 | ZVAL_LONG(*retval, retint); |
106 | break; |
107 | default: |
108 | ZVAL_NULL(*retval); |
109 | } |
110 | |
111 | return SUCCESS; |
112 | } |
113 | /* }}} */ |
114 | |
115 | /* {{{ xmlreader_get_property_ptr_ptr */ |
116 | zval **xmlreader_get_property_ptr_ptr(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) |
117 | { |
118 | xmlreader_object *obj; |
119 | zval tmp_member; |
120 | zval **retval = NULL; |
121 | xmlreader_prop_handler *hnd; |
122 | zend_object_handlers *std_hnd; |
123 | int ret = FAILURE; |
124 | |
125 | if (member->type != IS_STRING) { |
126 | tmp_member = *member; |
127 | zval_copy_ctor(&tmp_member); |
128 | convert_to_string(&tmp_member); |
129 | member = &tmp_member; |
130 | } |
131 | |
132 | obj = (xmlreader_object *)zend_objects_get_address(object TSRMLS_CC); |
133 | |
134 | if (obj->prop_handler != NULL) { |
135 | ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd); |
136 | } |
137 | if (ret == FAILURE) { |
138 | std_hnd = zend_get_std_object_handlers(); |
139 | retval = std_hnd->get_property_ptr_ptr(object, member, type, key TSRMLS_CC); |
140 | } |
141 | |
142 | if (member == &tmp_member) { |
143 | zval_dtor(member); |
144 | } |
145 | return retval; |
146 | } |
147 | /* }}} */ |
148 | |
149 | /* {{{ xmlreader_read_property */ |
150 | zval *xmlreader_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) |
151 | { |
152 | xmlreader_object *obj; |
153 | zval tmp_member; |
154 | zval *retval; |
155 | xmlreader_prop_handler *hnd; |
156 | zend_object_handlers *std_hnd; |
157 | int ret; |
158 | |
159 | if (member->type != IS_STRING) { |
160 | tmp_member = *member; |
161 | zval_copy_ctor(&tmp_member); |
162 | convert_to_string(&tmp_member); |
163 | member = &tmp_member; |
164 | } |
165 | |
166 | ret = FAILURE; |
167 | obj = (xmlreader_object *)zend_objects_get_address(object TSRMLS_CC); |
168 | |
169 | if (obj->prop_handler != NULL) { |
170 | ret = zend_hash_find(obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd); |
171 | } |
172 | if (ret == SUCCESS) { |
173 | ret = xmlreader_property_reader(obj, hnd, &retval TSRMLS_CC); |
174 | if (ret == SUCCESS) { |
175 | /* ensure we're creating a temporary variable */ |
176 | Z_SET_REFCOUNT_P(retval, 0); |
177 | } else { |
178 | retval = EG(uninitialized_zval_ptr); |
179 | } |
180 | } else { |
181 | std_hnd = zend_get_std_object_handlers(); |
182 | retval = std_hnd->read_property(object, member, type, key TSRMLS_CC); |
183 | } |
184 | |
185 | if (member == &tmp_member) { |
186 | zval_dtor(member); |
187 | } |
188 | return retval; |
189 | } |
190 | /* }}} */ |
191 | |
192 | /* {{{ xmlreader_write_property */ |
193 | void xmlreader_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC) |
194 | { |
195 | xmlreader_object *obj; |
196 | zval tmp_member; |
197 | xmlreader_prop_handler *hnd; |
198 | zend_object_handlers *std_hnd; |
199 | int ret; |
200 | |
201 | if (member->type != IS_STRING) { |
202 | tmp_member = *member; |
203 | zval_copy_ctor(&tmp_member); |
204 | convert_to_string(&tmp_member); |
205 | member = &tmp_member; |
206 | } |
207 | |
208 | ret = FAILURE; |
209 | obj = (xmlreader_object *)zend_objects_get_address(object TSRMLS_CC); |
210 | |
211 | if (obj->prop_handler != NULL) { |
212 | ret = zend_hash_find((HashTable *)obj->prop_handler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &hnd); |
213 | } |
214 | if (ret == SUCCESS) { |
215 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot write to read-only property" ); |
216 | } else { |
217 | std_hnd = zend_get_std_object_handlers(); |
218 | std_hnd->write_property(object, member, value, key TSRMLS_CC); |
219 | } |
220 | |
221 | if (member == &tmp_member) { |
222 | zval_dtor(member); |
223 | } |
224 | } |
225 | /* }}} */ |
226 | |
227 | /* {{{ _xmlreader_get_valid_file_path */ |
228 | /* _xmlreader_get_valid_file_path and _xmlreader_get_relaxNG should be made a |
229 | common function in libxml extension as code is common to a few xml extensions */ |
230 | char *_xmlreader_get_valid_file_path(char *source, char *resolved_path, int resolved_path_len TSRMLS_DC) { |
231 | xmlURI *uri; |
232 | xmlChar *escsource; |
233 | char *file_dest; |
234 | int isFileUri = 0; |
235 | |
236 | uri = xmlCreateURI(); |
237 | escsource = xmlURIEscapeStr((xmlChar *)source, (xmlChar *)":" ); |
238 | xmlParseURIReference(uri, (const char *)escsource); |
239 | xmlFree(escsource); |
240 | |
241 | if (uri->scheme != NULL) { |
242 | /* absolute file uris - libxml only supports localhost or empty host */ |
243 | if (strncasecmp(source, "file:///" ,8) == 0) { |
244 | isFileUri = 1; |
245 | #ifdef PHP_WIN32 |
246 | source += 8; |
247 | #else |
248 | source += 7; |
249 | #endif |
250 | } else if (strncasecmp(source, "file://localhost/" ,17) == 0) { |
251 | isFileUri = 1; |
252 | #ifdef PHP_WIN32 |
253 | source += 17; |
254 | #else |
255 | source += 16; |
256 | #endif |
257 | } |
258 | } |
259 | |
260 | file_dest = source; |
261 | |
262 | if ((uri->scheme == NULL || isFileUri)) { |
263 | if (!VCWD_REALPATH(source, resolved_path) && !expand_filepath(source, resolved_path TSRMLS_CC)) { |
264 | xmlFreeURI(uri); |
265 | return NULL; |
266 | } |
267 | file_dest = resolved_path; |
268 | } |
269 | |
270 | xmlFreeURI(uri); |
271 | |
272 | return file_dest; |
273 | } |
274 | /* }}} */ |
275 | |
276 | #ifdef LIBXML_SCHEMAS_ENABLED |
277 | /* {{{ _xmlreader_get_relaxNG */ |
278 | static xmlRelaxNGPtr _xmlreader_get_relaxNG(char *source, int source_len, int type, |
279 | xmlRelaxNGValidityErrorFunc error_func, |
280 | xmlRelaxNGValidityWarningFunc warn_func TSRMLS_DC) |
281 | { |
282 | char *valid_file = NULL; |
283 | xmlRelaxNGParserCtxtPtr parser = NULL; |
284 | xmlRelaxNGPtr sptr; |
285 | char resolved_path[MAXPATHLEN + 1]; |
286 | |
287 | switch (type) { |
288 | case XMLREADER_LOAD_FILE: |
289 | valid_file = _xmlreader_get_valid_file_path(source, resolved_path, MAXPATHLEN TSRMLS_CC); |
290 | if (!valid_file) { |
291 | return NULL; |
292 | } |
293 | parser = xmlRelaxNGNewParserCtxt(valid_file); |
294 | break; |
295 | case XMLREADER_LOAD_STRING: |
296 | parser = xmlRelaxNGNewMemParserCtxt(source, source_len); |
297 | /* If loading from memory, we need to set the base directory for the document |
298 | but it is not apparent how to do that for schema's */ |
299 | break; |
300 | default: |
301 | return NULL; |
302 | } |
303 | |
304 | if (parser == NULL) { |
305 | return NULL; |
306 | } |
307 | |
308 | if (error_func || warn_func) { |
309 | xmlRelaxNGSetParserErrors(parser, |
310 | (xmlRelaxNGValidityErrorFunc) error_func, |
311 | (xmlRelaxNGValidityWarningFunc) warn_func, |
312 | parser); |
313 | } |
314 | sptr = xmlRelaxNGParse(parser); |
315 | xmlRelaxNGFreeParserCtxt(parser); |
316 | |
317 | return sptr; |
318 | } |
319 | /* }}} */ |
320 | #endif |
321 | |
322 | static const zend_module_dep xmlreader_deps[] = { |
323 | ZEND_MOD_REQUIRED("libxml" ) |
324 | ZEND_MOD_END |
325 | }; |
326 | |
327 | /* {{{ xmlreader_module_entry |
328 | */ |
329 | zend_module_entry xmlreader_module_entry = { |
330 | STANDARD_MODULE_HEADER_EX, NULL, |
331 | xmlreader_deps, |
332 | "xmlreader" , |
333 | NULL, |
334 | PHP_MINIT(xmlreader), |
335 | PHP_MSHUTDOWN(xmlreader), |
336 | NULL, |
337 | NULL, |
338 | PHP_MINFO(xmlreader), |
339 | "0.1" , /* Replace with version number for your extension */ |
340 | STANDARD_MODULE_PROPERTIES |
341 | }; |
342 | /* }}} */ |
343 | |
344 | #ifdef COMPILE_DL_XMLREADER |
345 | ZEND_GET_MODULE(xmlreader) |
346 | #endif |
347 | |
348 | /* {{{ xmlreader_objects_clone */ |
349 | void xmlreader_objects_clone(void *object, void **object_clone TSRMLS_DC) |
350 | { |
351 | /* TODO */ |
352 | } |
353 | /* }}} */ |
354 | |
355 | /* {{{ xmlreader_free_resources */ |
356 | static void xmlreader_free_resources(xmlreader_object *intern) { |
357 | if (intern) { |
358 | if (intern->input) { |
359 | xmlFreeParserInputBuffer(intern->input); |
360 | intern->input = NULL; |
361 | } |
362 | |
363 | if (intern->ptr) { |
364 | xmlFreeTextReader(intern->ptr); |
365 | intern->ptr = NULL; |
366 | } |
367 | #ifdef LIBXML_SCHEMAS_ENABLED |
368 | if (intern->schema) { |
369 | xmlRelaxNGFree((xmlRelaxNGPtr) intern->schema); |
370 | intern->schema = NULL; |
371 | } |
372 | #endif |
373 | } |
374 | } |
375 | /* }}} */ |
376 | |
377 | /* {{{ xmlreader_objects_free_storage */ |
378 | void xmlreader_objects_free_storage(void *object TSRMLS_DC) |
379 | { |
380 | xmlreader_object *intern = (xmlreader_object *)object; |
381 | |
382 | zend_object_std_dtor(&intern->std TSRMLS_CC); |
383 | |
384 | xmlreader_free_resources(intern); |
385 | |
386 | efree(object); |
387 | } |
388 | /* }}} */ |
389 | |
390 | /* {{{ xmlreader_objects_new */ |
391 | zend_object_value xmlreader_objects_new(zend_class_entry *class_type TSRMLS_DC) |
392 | { |
393 | zend_object_value retval; |
394 | xmlreader_object *intern; |
395 | |
396 | intern = emalloc(sizeof(xmlreader_object)); |
397 | memset(&intern->std, 0, sizeof(zend_object)); |
398 | intern->ptr = NULL; |
399 | intern->input = NULL; |
400 | intern->schema = NULL; |
401 | intern->prop_handler = &xmlreader_prop_handlers; |
402 | |
403 | zend_object_std_init(&intern->std, class_type TSRMLS_CC); |
404 | object_properties_init(&intern->std, class_type); |
405 | retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) xmlreader_objects_free_storage, xmlreader_objects_clone TSRMLS_CC); |
406 | intern->handle = retval.handle; |
407 | retval.handlers = &xmlreader_object_handlers; |
408 | return retval; |
409 | } |
410 | /* }}} */ |
411 | |
412 | /* {{{ php_xmlreader_string_arg */ |
413 | static void php_xmlreader_string_arg(INTERNAL_FUNCTION_PARAMETERS, xmlreader_read_one_char_t internal_function) { |
414 | zval *id; |
415 | int name_len = 0; |
416 | char *retchar = NULL; |
417 | xmlreader_object *intern; |
418 | char *name; |
419 | |
420 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s" , &name, &name_len) == FAILURE) { |
421 | return; |
422 | } |
423 | |
424 | if (!name_len) { |
425 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument cannot be an empty string" ); |
426 | RETURN_FALSE; |
427 | } |
428 | |
429 | id = getThis(); |
430 | |
431 | intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); |
432 | if (intern && intern->ptr) { |
433 | retchar = (char *)internal_function(intern->ptr, (const unsigned char *)name); |
434 | } |
435 | if (retchar) { |
436 | RETVAL_STRING(retchar, 1); |
437 | xmlFree(retchar); |
438 | return; |
439 | } else { |
440 | RETVAL_NULL(); |
441 | } |
442 | } |
443 | /* }}} */ |
444 | |
445 | /* {{{ php_xmlreader_no_arg */ |
446 | static void php_xmlreader_no_arg(INTERNAL_FUNCTION_PARAMETERS, xmlreader_read_int_t internal_function) { |
447 | zval *id; |
448 | int retval; |
449 | xmlreader_object *intern; |
450 | |
451 | id = getThis(); |
452 | |
453 | intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); |
454 | if (intern && intern->ptr) { |
455 | retval = internal_function(intern->ptr); |
456 | if (retval == 1) { |
457 | RETURN_TRUE; |
458 | } |
459 | } |
460 | |
461 | RETURN_FALSE; |
462 | } |
463 | /* }}} */ |
464 | |
465 | #if LIBXML_VERSION >= 20620 |
466 | /* {{{ php_xmlreader_no_arg_string */ |
467 | static void php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAMETERS, xmlreader_read_char_t internal_function) { |
468 | zval *id; |
469 | char *retchar = NULL; |
470 | xmlreader_object *intern; |
471 | |
472 | id = getThis(); |
473 | |
474 | intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); |
475 | if (intern && intern->ptr) { |
476 | retchar = (char *)internal_function(intern->ptr); |
477 | } |
478 | if (retchar) { |
479 | RETVAL_STRING(retchar, 1); |
480 | xmlFree(retchar); |
481 | return; |
482 | } else { |
483 | RETVAL_EMPTY_STRING(); |
484 | } |
485 | } |
486 | /* }}} */ |
487 | #endif |
488 | |
489 | /* {{{ php_xmlreader_set_relaxng_schema */ |
490 | static void php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAMETERS, int type) { |
491 | #ifdef LIBXML_SCHEMAS_ENABLED |
492 | zval *id; |
493 | int source_len = 0, retval = -1; |
494 | xmlreader_object *intern; |
495 | xmlRelaxNGPtr schema = NULL; |
496 | char *source; |
497 | |
498 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p!" , &source, &source_len) == FAILURE) { |
499 | return; |
500 | } |
501 | |
502 | if (source != NULL && !source_len) { |
503 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Schema data source is required" ); |
504 | RETURN_FALSE; |
505 | } |
506 | |
507 | id = getThis(); |
508 | |
509 | intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); |
510 | if (intern && intern->ptr) { |
511 | if (source) { |
512 | schema = _xmlreader_get_relaxNG(source, source_len, type, NULL, NULL TSRMLS_CC); |
513 | if (schema) { |
514 | retval = xmlTextReaderRelaxNGSetSchema(intern->ptr, schema); |
515 | } |
516 | } else { |
517 | /* unset the associated relaxNG context and schema if one exists */ |
518 | retval = xmlTextReaderRelaxNGSetSchema(intern->ptr, NULL); |
519 | } |
520 | |
521 | if (retval == 0) { |
522 | if (intern->schema) { |
523 | xmlRelaxNGFree((xmlRelaxNGPtr) intern->schema); |
524 | } |
525 | |
526 | intern->schema = schema; |
527 | |
528 | RETURN_TRUE; |
529 | } |
530 | } |
531 | |
532 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set schema. This must be set prior to reading or schema contains errors." ); |
533 | |
534 | RETURN_FALSE; |
535 | #else |
536 | php_error_docref(NULL TSRMLS_CC, E_WARNING, "No Schema support built into libxml." ); |
537 | |
538 | RETURN_FALSE; |
539 | #endif |
540 | } |
541 | /* }}} */ |
542 | |
543 | /* {{{ proto boolean XMLReader::close() |
544 | Closes xmlreader - current frees resources until xmlTextReaderClose is fixed in libxml */ |
545 | PHP_METHOD(xmlreader, close) |
546 | { |
547 | zval *id; |
548 | xmlreader_object *intern; |
549 | |
550 | id = getThis(); |
551 | intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); |
552 | /* libxml is segfaulting in versions up to 2.6.8 using xmlTextReaderClose so for |
553 | now we will free the whole reader when close is called as it would get rebuilt on |
554 | a new load anyways */ |
555 | xmlreader_free_resources(intern); |
556 | |
557 | RETURN_TRUE; |
558 | } |
559 | /* }}} */ |
560 | |
561 | /* {{{ proto string XMLReader::getAttribute(string name) |
562 | Get value of an attribute from current element */ |
563 | PHP_METHOD(xmlreader, getAttribute) |
564 | { |
565 | php_xmlreader_string_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderGetAttribute); |
566 | } |
567 | /* }}} */ |
568 | |
569 | /* {{{ proto string XMLReader::getAttributeNo(int index) |
570 | Get value of an attribute at index from current element */ |
571 | PHP_METHOD(xmlreader, getAttributeNo) |
572 | { |
573 | zval *id; |
574 | long attr_pos; |
575 | char *retchar = NULL; |
576 | xmlreader_object *intern; |
577 | |
578 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l" , &attr_pos) == FAILURE) { |
579 | return; |
580 | } |
581 | |
582 | id = getThis(); |
583 | |
584 | intern = (xmlreader_object *)zend_object_store_get_object(id TSRMLS_CC); |
585 | if (intern && intern->ptr) { |
586 | retchar = (char *)xmlTextReaderGetAttributeNo(intern->ptr, attr_pos); |
587 | } |
588 | if (retchar) { |
589 | RETVAL_STRING(retchar, 1); |
590 | xmlFree(retchar); |
591 | } |
592 | } |
593 | /* }}} */ |
594 | |
595 | /* {{{ proto string XMLReader::getAttributeNs(string name, string namespaceURI) |
596 | Get value of a attribute via name and namespace from current element */ |
597 | PHP_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) |
627 | Indicates whether given property (one of the parser option constants) is set or not on parser */ |
628 | PHP_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() |
655 | Returns boolean indicating if parsed document is valid or not. |
656 | Must set XMLREADER_LOADDTD or XMLREADER_VALIDATE parser option prior to the first call to read |
657 | or this method will always return FALSE */ |
658 | PHP_METHOD(xmlreader, isValid) |
659 | { |
660 | php_xmlreader_no_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderIsValid); |
661 | } |
662 | /* }}} */ |
663 | |
664 | /* {{{ proto string XMLReader::lookupNamespace(string prefix) |
665 | Return namespaceURI for associated prefix on current node */ |
666 | PHP_METHOD(xmlreader, lookupNamespace) |
667 | { |
668 | php_xmlreader_string_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderLookupNamespace); |
669 | } |
670 | /* }}} */ |
671 | |
672 | /* {{{ proto boolean XMLReader::moveToAttribute(string name) |
673 | Positions reader at specified attribute - Returns TRUE on success and FALSE on failure */ |
674 | PHP_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) |
705 | Positions reader at attribute at specified index. |
706 | Returns TRUE on success and FALSE on failure */ |
707 | PHP_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) |
733 | Positions reader at attribute spcified by name and namespaceURI. |
734 | Returns TRUE on success and FALSE on failure */ |
735 | PHP_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() |
766 | Moves the position of the current instance to the node that contains the current Attribute node. */ |
767 | PHP_METHOD(xmlreader, moveToElement) |
768 | { |
769 | php_xmlreader_no_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderMoveToElement); |
770 | } |
771 | /* }}} */ |
772 | |
773 | /* {{{ proto boolean XMLReader::moveToFirstAttribute() |
774 | Moves the position of the current instance to the first attribute associated with the current node. */ |
775 | PHP_METHOD(xmlreader, moveToFirstAttribute) |
776 | { |
777 | php_xmlreader_no_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderMoveToFirstAttribute); |
778 | } |
779 | /* }}} */ |
780 | |
781 | /* {{{ proto boolean XMLReader::moveToNextAttribute() |
782 | Moves the position of the current instance to the next attribute associated with the current node. */ |
783 | PHP_METHOD(xmlreader, moveToNextAttribute) |
784 | { |
785 | php_xmlreader_no_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderMoveToNextAttribute); |
786 | } |
787 | /* }}} */ |
788 | |
789 | /* {{{ proto boolean XMLReader::read() |
790 | Moves the position of the current instance to the next node in the stream. */ |
791 | PHP_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]) |
814 | Moves the position of the current instance to the next node in the stream. */ |
815 | PHP_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]]) |
855 | Sets the URI that the XMLReader will parse. */ |
856 | PHP_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 |
912 | PHP_METHOD(xmlreader, resetState) |
913 | { |
914 | |
915 | } |
916 | */ |
917 | |
918 | #if LIBXML_VERSION >= 20620 |
919 | /* {{{ proto string XMLReader::readInnerXml() |
920 | Reads the contents of the current node, including child nodes and markup. */ |
921 | PHP_METHOD(xmlreader, readInnerXml) |
922 | { |
923 | php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderReadInnerXml); |
924 | } |
925 | /* }}} */ |
926 | |
927 | /* {{{ proto boolean XMLReader::readOuterXml() |
928 | Reads the contents of the current node, including child nodes and markup. */ |
929 | PHP_METHOD(xmlreader, readOuterXml) |
930 | { |
931 | php_xmlreader_no_arg_string(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextReaderReadOuterXml); |
932 | } |
933 | /* }}} */ |
934 | |
935 | /* {{{ proto boolean XMLReader::readString() |
936 | Reads the contents of an element or a text node as a string. */ |
937 | PHP_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) |
944 | Use W3C XSD schema to validate the document as it is processed. Activation is only possible before the first Read(). */ |
945 | PHP_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) |
986 | Sets parser property (one of the parser option constants). |
987 | Properties must be set after open() or XML() and before the first read() is called */ |
988 | PHP_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) |
1016 | Sets the string that the XMLReader will parse. */ |
1017 | PHP_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) |
1024 | Sets the string that the XMLReader will parse. */ |
1025 | PHP_METHOD(xmlreader, setRelaxNGSchemaSource) |
1026 | { |
1027 | php_xmlreader_set_relaxng_schema(INTERNAL_FUNCTION_PARAM_PASSTHRU, XMLREADER_LOAD_STRING); |
1028 | } |
1029 | /* }}} */ |
1030 | |
1031 | /* TODO |
1032 | XMLPUBFUN int XMLCALL |
1033 | xmlTextReaderSetSchema (xmlTextReaderPtr reader, |
1034 | xmlSchemaPtr schema); |
1035 | */ |
1036 | |
1037 | /* {{{ proto boolean XMLReader::XML(string source [, string encoding [, int options]]) |
1038 | Sets the string that the XMLReader will parse. */ |
1039 | PHP_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() |
1124 | Moves the position of the current instance to the next node in the stream. */ |
1125 | PHP_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 */ |
1172 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_close, 0) |
1173 | ZEND_END_ARG_INFO() |
1174 | |
1175 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_getAttribute, 0) |
1176 | ZEND_ARG_INFO(0, name) |
1177 | ZEND_END_ARG_INFO() |
1178 | |
1179 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_getAttributeNo, 0) |
1180 | ZEND_ARG_INFO(0, index) |
1181 | ZEND_END_ARG_INFO() |
1182 | |
1183 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_getAttributeNs, 0) |
1184 | ZEND_ARG_INFO(0, name) |
1185 | ZEND_ARG_INFO(0, namespaceURI) |
1186 | ZEND_END_ARG_INFO() |
1187 | |
1188 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_getParserProperty, 0) |
1189 | ZEND_ARG_INFO(0, property) |
1190 | ZEND_END_ARG_INFO() |
1191 | |
1192 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_isValid, 0) |
1193 | ZEND_END_ARG_INFO() |
1194 | |
1195 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_lookupNamespace, 0) |
1196 | ZEND_ARG_INFO(0, prefix) |
1197 | ZEND_END_ARG_INFO() |
1198 | |
1199 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToAttribute, 0) |
1200 | ZEND_ARG_INFO(0, name) |
1201 | ZEND_END_ARG_INFO() |
1202 | |
1203 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToAttributeNo, 0) |
1204 | ZEND_ARG_INFO(0, index) |
1205 | ZEND_END_ARG_INFO() |
1206 | |
1207 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToAttributeNs, 0) |
1208 | ZEND_ARG_INFO(0, name) |
1209 | ZEND_ARG_INFO(0, namespaceURI) |
1210 | ZEND_END_ARG_INFO() |
1211 | |
1212 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToElement, 0) |
1213 | ZEND_END_ARG_INFO() |
1214 | |
1215 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToFirstAttribute, 0) |
1216 | ZEND_END_ARG_INFO() |
1217 | |
1218 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_moveToNextAttribute, 0) |
1219 | ZEND_END_ARG_INFO() |
1220 | |
1221 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_read, 0) |
1222 | ZEND_END_ARG_INFO() |
1223 | |
1224 | ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlreader_next, 0, 0, 0) |
1225 | ZEND_ARG_INFO(0, localname) |
1226 | ZEND_END_ARG_INFO() |
1227 | |
1228 | ZEND_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) |
1232 | ZEND_END_ARG_INFO() |
1233 | |
1234 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_readInnerXml, 0) |
1235 | ZEND_END_ARG_INFO() |
1236 | |
1237 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_readOuterXml, 0) |
1238 | ZEND_END_ARG_INFO() |
1239 | |
1240 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_readString, 0) |
1241 | ZEND_END_ARG_INFO() |
1242 | |
1243 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_setSchema, 0) |
1244 | ZEND_ARG_INFO(0, filename) |
1245 | ZEND_END_ARG_INFO() |
1246 | |
1247 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_setParserProperty, 0) |
1248 | ZEND_ARG_INFO(0, property) |
1249 | ZEND_ARG_INFO(0, value) |
1250 | ZEND_END_ARG_INFO() |
1251 | |
1252 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_setRelaxNGSchema, 0) |
1253 | ZEND_ARG_INFO(0, filename) |
1254 | ZEND_END_ARG_INFO() |
1255 | |
1256 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_setRelaxNGSchemaSource, 0) |
1257 | ZEND_ARG_INFO(0, source) |
1258 | ZEND_END_ARG_INFO() |
1259 | |
1260 | ZEND_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) |
1264 | ZEND_END_ARG_INFO() |
1265 | |
1266 | ZEND_BEGIN_ARG_INFO(arginfo_xmlreader_expand, 0) |
1267 | ZEND_END_ARG_INFO() |
1268 | /* }}} */ |
1269 | |
1270 | static 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 | */ |
1306 | PHP_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 | */ |
1377 | PHP_MSHUTDOWN_FUNCTION(xmlreader) |
1378 | { |
1379 | zend_hash_destroy(&xmlreader_prop_handlers); |
1380 | return SUCCESS; |
1381 | } |
1382 | /* }}} */ |
1383 | |
1384 | /* {{{ PHP_MINFO_FUNCTION |
1385 | */ |
1386 | PHP_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 | |