xref: /PHP-5.5/ext/dom/xpath.c (revision 73c1be26)
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    | Authors: Christian Stocker <chregu@php.net>                          |
16    |          Rob Richards <rrichards@php.net>                            |
17    +----------------------------------------------------------------------+
18 */
19 
20 /* $Id$ */
21 
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #include "php.h"
27 #if HAVE_LIBXML && HAVE_DOM
28 #include "php_dom.h"
29 
30 #define PHP_DOM_XPATH_QUERY 0
31 #define PHP_DOM_XPATH_EVALUATE 1
32 
33 /*
34 * class DOMXPath
35 */
36 
37 #if defined(LIBXML_XPATH_ENABLED)
38 
39 /* {{{ arginfo */
40 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_xpath_construct, 0, 0, 1)
41 	ZEND_ARG_OBJ_INFO(0, doc, DOMDocument, 0)
42 ZEND_END_ARG_INFO();
43 
44 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_xpath_register_ns, 0, 0, 2)
45 	ZEND_ARG_INFO(0, prefix)
46 	ZEND_ARG_INFO(0, uri)
47 ZEND_END_ARG_INFO();
48 
49 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_xpath_query, 0, 0, 1)
50 	ZEND_ARG_INFO(0, expr)
51 	ZEND_ARG_OBJ_INFO(0, context, DOMNode, 1)
52 	ZEND_ARG_INFO(0, registerNodeNS)
53 ZEND_END_ARG_INFO();
54 
55 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_xpath_evaluate, 0, 0, 1)
56 	ZEND_ARG_INFO(0, expr)
57 	ZEND_ARG_OBJ_INFO(0, context, DOMNode, 1)
58 	ZEND_ARG_INFO(0, registerNodeNS)
59 ZEND_END_ARG_INFO();
60 
61 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_xpath_register_php_functions, 0, 0, 0)
62 ZEND_END_ARG_INFO();
63 /* }}} */
64 
65 const zend_function_entry php_dom_xpath_class_functions[] = {
66 	PHP_ME(domxpath, __construct, arginfo_dom_xpath_construct, ZEND_ACC_PUBLIC)
67 	PHP_FALIAS(registerNamespace, dom_xpath_register_ns, arginfo_dom_xpath_register_ns)
68 	PHP_FALIAS(query, dom_xpath_query, arginfo_dom_xpath_query)
69 	PHP_FALIAS(evaluate, dom_xpath_evaluate, arginfo_dom_xpath_evaluate)
70 	PHP_FALIAS(registerPhpFunctions, dom_xpath_register_php_functions, arginfo_dom_xpath_register_php_functions)
71 	PHP_FE_END
72 };
73 
74 
dom_xpath_ext_function_php(xmlXPathParserContextPtr ctxt,int nargs,int type)75 static void dom_xpath_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int type) /* {{{ */
76 {
77 	zval **args = NULL;
78 	zval *retval;
79 	int result, i, ret;
80 	int error = 0;
81 	zend_fcall_info fci;
82 	zval handler;
83 	xmlXPathObjectPtr obj;
84 	char *str;
85 	char *callable = NULL;
86 	dom_xpath_object *intern;
87 
88 	TSRMLS_FETCH();
89 
90 	if (! zend_is_executing(TSRMLS_C)) {
91 		xmlGenericError(xmlGenericErrorContext,
92 		"xmlExtFunctionTest: Function called from outside of PHP\n");
93 		error = 1;
94 	} else {
95 		intern = (dom_xpath_object *) ctxt->context->userData;
96 		if (intern == NULL) {
97 			xmlGenericError(xmlGenericErrorContext,
98 			"xmlExtFunctionTest: failed to get the internal object\n");
99 			error = 1;
100 		}
101 		else if (intern->registerPhpFunctions == 0) {
102 			xmlGenericError(xmlGenericErrorContext,
103 			"xmlExtFunctionTest: PHP Object did not register PHP functions\n");
104 			error = 1;
105 		}
106 	}
107 
108 	if (error == 1) {
109 		for (i = nargs - 1; i >= 0; i--) {
110 			obj = valuePop(ctxt);
111 			xmlXPathFreeObject(obj);
112 		}
113 		return;
114 	}
115 
116 	fci.param_count = nargs - 1;
117 	if (fci.param_count > 0) {
118 		fci.params = safe_emalloc(fci.param_count, sizeof(zval**), 0);
119 		args = safe_emalloc(fci.param_count, sizeof(zval *), 0);
120 	}
121 	/* Reverse order to pop values off ctxt stack */
122 	for (i = nargs - 2; i >= 0; i--) {
123 		obj = valuePop(ctxt);
124 		MAKE_STD_ZVAL(args[i]);
125 		switch (obj->type) {
126 			case XPATH_STRING:
127 				ZVAL_STRING(args[i],  (char *)obj->stringval, 1);
128 				break;
129 			case XPATH_BOOLEAN:
130 				ZVAL_BOOL(args[i],  obj->boolval);
131 				break;
132 			case XPATH_NUMBER:
133 				ZVAL_DOUBLE(args[i], obj->floatval);
134 				break;
135 			case XPATH_NODESET:
136 				if (type == 1) {
137 					str = (char *)xmlXPathCastToString(obj);
138 					ZVAL_STRING(args[i], str, 1);
139 					xmlFree(str);
140 				} else if (type == 2) {
141 					int j;
142 					array_init(args[i]);
143 					if (obj->nodesetval && obj->nodesetval->nodeNr > 0) {
144 						for (j = 0; j < obj->nodesetval->nodeNr; j++) {
145 							xmlNodePtr node = obj->nodesetval->nodeTab[j];
146 							zval *child;
147 							MAKE_STD_ZVAL(child);
148 							/* not sure, if we need this... it's copied from xpath.c */
149 							if (node->type == XML_NAMESPACE_DECL) {
150 								xmlNsPtr curns;
151 								xmlNodePtr nsparent;
152 
153 								nsparent = node->_private;
154 								curns = xmlNewNs(NULL, node->name, NULL);
155 								if (node->children) {
156 									curns->prefix = xmlStrdup((xmlChar *) node->children);
157 								}
158 								if (node->children) {
159 									node = xmlNewDocNode(node->doc, NULL, (xmlChar *) node->children, node->name);
160 								} else {
161 									node = xmlNewDocNode(node->doc, NULL, (xmlChar *) "xmlns", node->name);
162 								}
163 								node->type = XML_NAMESPACE_DECL;
164 								node->parent = nsparent;
165 								node->ns = curns;
166 							}
167 							child = php_dom_create_object(node, &ret, child, (dom_object *)intern TSRMLS_CC);
168 							add_next_index_zval(args[i], child);
169 						}
170 					}
171 				}
172 				break;
173 			default:
174 			ZVAL_STRING(args[i], (char *)xmlXPathCastToString(obj), 1);
175 		}
176 		xmlXPathFreeObject(obj);
177 		fci.params[i] = &args[i];
178 	}
179 
180 	fci.size = sizeof(fci);
181 	fci.function_table = EG(function_table);
182 
183 	obj = valuePop(ctxt);
184 	if (obj->stringval == NULL) {
185 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Handler name must be a string");
186 		xmlXPathFreeObject(obj);
187 		if (fci.param_count > 0) {
188 			for (i = 0; i < nargs - 1; i++) {
189 				zval_ptr_dtor(&args[i]);
190 			}
191 			efree(args);
192 			efree(fci.params);
193 		}
194 		return;
195 	}
196 	INIT_PZVAL(&handler);
197 	ZVAL_STRING(&handler, obj->stringval, 1);
198 	xmlXPathFreeObject(obj);
199 
200 	fci.function_name = &handler;
201 	fci.symbol_table = NULL;
202 	fci.object_ptr = NULL;
203 	fci.retval_ptr_ptr = &retval;
204 	fci.no_separation = 0;
205 
206 	if (!zend_make_callable(&handler, &callable TSRMLS_CC)) {
207 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler %s()", callable);
208 
209 	} else if ( intern->registerPhpFunctions == 2 && zend_hash_exists(intern->registered_phpfunctions, callable, strlen(callable) + 1) == 0) {
210 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not allowed to call handler '%s()'.", callable);
211 		/* Push an empty string, so that we at least have an xslt result... */
212 		valuePush(ctxt, xmlXPathNewString((xmlChar *)""));
213 	} else {
214 		result = zend_call_function(&fci, NULL TSRMLS_CC);
215 		if (result == FAILURE) {
216 			if (Z_TYPE(handler) == IS_STRING) {
217 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call handler %s()", Z_STRVAL_P(&handler));
218 			}
219 		/* retval is == NULL, when an exception occurred, don't report anything, because PHP itself will handle that */
220 		} else if (retval == NULL) {
221 		} else {
222 			if (retval->type == IS_OBJECT && instanceof_function( Z_OBJCE_P(retval), dom_node_class_entry TSRMLS_CC)) {
223 				xmlNode *nodep;
224 				dom_object *obj;
225 				if (intern->node_list == NULL) {
226 					ALLOC_HASHTABLE(intern->node_list);
227 					zend_hash_init(intern->node_list, 0, NULL, ZVAL_PTR_DTOR, 0);
228 				}
229 				zval_add_ref(&retval);
230 				zend_hash_next_index_insert(intern->node_list, &retval, sizeof(zval *), NULL);
231 				obj = (dom_object *)zend_object_store_get_object(retval TSRMLS_CC);
232 				nodep = dom_object_get_node(obj);
233 				valuePush(ctxt, xmlXPathNewNodeSet(nodep));
234 			} else if (retval->type == IS_BOOL) {
235 				valuePush(ctxt, xmlXPathNewBoolean(retval->value.lval));
236 			} else if (retval->type == IS_OBJECT) {
237 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "A PHP Object cannot be converted to a XPath-string");
238 				valuePush(ctxt, xmlXPathNewString((xmlChar *)""));
239 			} else {
240 				convert_to_string_ex(&retval);
241 				valuePush(ctxt, xmlXPathNewString( Z_STRVAL_P(retval)));
242 			}
243 			zval_ptr_dtor(&retval);
244 		}
245 	}
246 	efree(callable);
247 	zval_dtor(&handler);
248 	if (fci.param_count > 0) {
249 		for (i = 0; i < nargs - 1; i++) {
250 			zval_ptr_dtor(&args[i]);
251 		}
252 		efree(args);
253 		efree(fci.params);
254 	}
255 }
256 /* }}} */
257 
dom_xpath_ext_function_string_php(xmlXPathParserContextPtr ctxt,int nargs)258 static void dom_xpath_ext_function_string_php(xmlXPathParserContextPtr ctxt, int nargs) /* {{{ */
259 {
260 	dom_xpath_ext_function_php(ctxt, nargs, 1);
261 }
262 /* }}} */
263 
dom_xpath_ext_function_object_php(xmlXPathParserContextPtr ctxt,int nargs)264 static void dom_xpath_ext_function_object_php(xmlXPathParserContextPtr ctxt, int nargs) /* {{{ */
265 {
266 	dom_xpath_ext_function_php(ctxt, nargs, 2);
267 }
268 /* }}} */
269 
270 /* {{{ proto void DOMXPath::__construct(DOMDocument doc) U */
PHP_METHOD(domxpath,__construct)271 PHP_METHOD(domxpath, __construct)
272 {
273 	zval *id, *doc;
274 	xmlDocPtr docp = NULL;
275 	dom_object *docobj;
276 	dom_xpath_object *intern;
277 	xmlXPathContextPtr ctx, oldctx;
278 	zend_error_handling error_handling;
279 
280 	zend_replace_error_handling(EH_THROW, dom_domexception_class_entry, &error_handling TSRMLS_CC);
281 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OO", &id, dom_xpath_class_entry, &doc, dom_document_class_entry) == FAILURE) {
282 		zend_restore_error_handling(&error_handling TSRMLS_CC);
283 		return;
284 	}
285 
286 	zend_restore_error_handling(&error_handling TSRMLS_CC);
287 	DOM_GET_OBJ(docp, doc, xmlDocPtr, docobj);
288 
289 	ctx = xmlXPathNewContext(docp);
290 	if (ctx == NULL) {
291 		php_dom_throw_error(INVALID_STATE_ERR, 1 TSRMLS_CC);
292 		RETURN_FALSE;
293 	}
294 
295 	intern = (dom_xpath_object *)zend_object_store_get_object(id TSRMLS_CC);
296 	if (intern != NULL) {
297 		oldctx = (xmlXPathContextPtr)intern->ptr;
298 		if (oldctx != NULL) {
299 			php_libxml_decrement_doc_ref((php_libxml_node_object *)intern TSRMLS_CC);
300 			xmlXPathFreeContext(oldctx);
301 		}
302 
303 		xmlXPathRegisterFuncNS (ctx, (const xmlChar *) "functionString",
304 					   (const xmlChar *) "http://php.net/xpath",
305 					   dom_xpath_ext_function_string_php);
306 		xmlXPathRegisterFuncNS (ctx, (const xmlChar *) "function",
307 					   (const xmlChar *) "http://php.net/xpath",
308 					   dom_xpath_ext_function_object_php);
309 
310 		intern->ptr = ctx;
311 		ctx->userData = (void *)intern;
312 		intern->document = docobj->document;
313 		php_libxml_increment_doc_ref((php_libxml_node_object *)intern, docp TSRMLS_CC);
314 	}
315 }
316 /* }}} end DOMXPath::__construct */
317 
318 /* {{{ document DOMDocument*/
dom_xpath_document_read(dom_object * obj,zval ** retval TSRMLS_DC)319 int dom_xpath_document_read(dom_object *obj, zval **retval TSRMLS_DC)
320 {
321 	xmlDoc *docp = NULL;
322 	xmlXPathContextPtr ctx;
323 	int ret;
324 	zval *tmp;
325 
326 	ctx = (xmlXPathContextPtr) obj->ptr;
327 
328 	if (ctx) {
329 		docp = (xmlDocPtr) ctx->doc;
330 	}
331 
332 	ALLOC_ZVAL(*retval);
333 	tmp = *retval;
334 
335 	if (NULL == (*retval = php_dom_create_object((xmlNodePtr) docp, &ret, *retval, obj TSRMLS_CC))) {
336 		FREE_ZVAL(tmp);
337 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object");
338 		return FAILURE;
339 	}
340 	if (tmp != *retval) {
341 		FREE_ZVAL(tmp);
342 	}
343 	return SUCCESS;
344 }
345 /* }}} */
346 
347 /* {{{ proto boolean dom_xpath_register_ns(string prefix, string uri); */
PHP_FUNCTION(dom_xpath_register_ns)348 PHP_FUNCTION(dom_xpath_register_ns)
349 {
350 	zval *id;
351 	xmlXPathContextPtr ctxp;
352 	int prefix_len, ns_uri_len;
353 	dom_xpath_object *intern;
354 	unsigned char *prefix, *ns_uri;
355 
356 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oss", &id, dom_xpath_class_entry, &prefix, &prefix_len, &ns_uri, &ns_uri_len) == FAILURE) {
357 		return;
358 	}
359 
360 	intern = (dom_xpath_object *)zend_object_store_get_object(id TSRMLS_CC);
361 
362 	ctxp = (xmlXPathContextPtr) intern->ptr;
363 	if (ctxp == NULL) {
364 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid XPath Context");
365 		RETURN_FALSE;
366 	}
367 
368 	if (xmlXPathRegisterNs(ctxp, prefix, ns_uri) != 0) {
369 		RETURN_FALSE
370 	}
371 	RETURN_TRUE;
372 }
373 /* }}} */
374 
dom_xpath_iter(zval * baseobj,dom_object * intern)375 static void dom_xpath_iter(zval *baseobj, dom_object *intern) /* {{{ */
376 {
377 	dom_nnodemap_object *mapptr;
378 
379 	mapptr = (dom_nnodemap_object *)intern->ptr;
380 	mapptr->baseobjptr = baseobj;
381 	mapptr->nodetype = DOM_NODESET;
382 
383 }
384 /* }}} */
385 
php_xpath_eval(INTERNAL_FUNCTION_PARAMETERS,int type)386 static void php_xpath_eval(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
387 {
388 	zval *id, *retval, *context = NULL;
389 	xmlXPathContextPtr ctxp;
390 	xmlNodePtr nodep = NULL;
391 	xmlXPathObjectPtr xpathobjp;
392 	int expr_len, ret, nsnbr = 0, xpath_type;
393 	dom_xpath_object *intern;
394 	dom_object *nodeobj;
395 	char *expr;
396 	xmlDoc *docp = NULL;
397 	xmlNsPtr *ns = NULL;
398 	zend_bool register_node_ns = 1;
399 
400 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os|O!b", &id, dom_xpath_class_entry, &expr, &expr_len, &context, dom_node_class_entry, &register_node_ns) == FAILURE) {
401 		return;
402 	}
403 
404 	intern = (dom_xpath_object *)zend_object_store_get_object(id TSRMLS_CC);
405 
406 	ctxp = (xmlXPathContextPtr) intern->ptr;
407 	if (ctxp == NULL) {
408 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid XPath Context");
409 		RETURN_FALSE;
410 	}
411 
412 	docp = (xmlDocPtr) ctxp->doc;
413 	if (docp == NULL) {
414 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid XPath Document Pointer");
415 		RETURN_FALSE;
416 	}
417 
418 	if (context != NULL) {
419 		DOM_GET_OBJ(nodep, context, xmlNodePtr, nodeobj);
420 	}
421 
422 	if (!nodep) {
423 		nodep = xmlDocGetRootElement(docp);
424 	}
425 
426 	if (nodep && docp != nodep->doc) {
427 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Node From Wrong Document");
428 		RETURN_FALSE;
429 	}
430 
431 	ctxp->node = nodep;
432 
433 	if (register_node_ns) {
434 		/* Register namespaces in the node */
435 		ns = xmlGetNsList(docp, nodep);
436 
437 		if (ns != NULL) {
438 			while (ns[nsnbr] != NULL)
439 			nsnbr++;
440 		}
441 	}
442 
443 
444     ctxp->namespaces = ns;
445     ctxp->nsNr = nsnbr;
446 
447 	xpathobjp = xmlXPathEvalExpression(expr, ctxp);
448 	ctxp->node = NULL;
449 
450 	if (ns != NULL) {
451 		xmlFree(ns);
452 		ctxp->namespaces = NULL;
453 		ctxp->nsNr = 0;
454 	}
455 
456 	if (! xpathobjp) {
457 		RETURN_FALSE;
458 	}
459 
460 	if (type == PHP_DOM_XPATH_QUERY) {
461 		xpath_type = XPATH_NODESET;
462 	} else {
463 		xpath_type = xpathobjp->type;
464 	}
465 
466 	switch (xpath_type) {
467 
468 		case  XPATH_NODESET:
469 		{
470 			int i;
471 			xmlNodeSetPtr nodesetp;
472 
473 			MAKE_STD_ZVAL(retval);
474 			array_init(retval);
475 
476 			if (xpathobjp->type == XPATH_NODESET && NULL != (nodesetp = xpathobjp->nodesetval)) {
477 
478 				for (i = 0; i < nodesetp->nodeNr; i++) {
479 					xmlNodePtr node = nodesetp->nodeTab[i];
480 					zval *child;
481 
482 					MAKE_STD_ZVAL(child);
483 
484 					if (node->type == XML_NAMESPACE_DECL) {
485 						xmlNsPtr curns;
486 						xmlNodePtr nsparent;
487 
488 						nsparent = node->_private;
489 						curns = xmlNewNs(NULL, node->name, NULL);
490 						if (node->children) {
491 							curns->prefix = xmlStrdup((char *) node->children);
492 						}
493 						if (node->children) {
494 							node = xmlNewDocNode(docp, NULL, (char *) node->children, node->name);
495 						} else {
496 							node = xmlNewDocNode(docp, NULL, "xmlns", node->name);
497 						}
498 						node->type = XML_NAMESPACE_DECL;
499 						node->parent = nsparent;
500 						node->ns = curns;
501 					}
502 					child = php_dom_create_object(node, &ret, child, (dom_object *)intern TSRMLS_CC);
503 					add_next_index_zval(retval, child);
504 				}
505 			}
506 			php_dom_create_interator(return_value, DOM_NODELIST TSRMLS_CC);
507 			nodeobj = (dom_object *)zend_objects_get_address(return_value TSRMLS_CC);
508 			dom_xpath_iter(retval, nodeobj);
509 			break;
510 		}
511 
512 		case XPATH_BOOLEAN:
513 			RETVAL_BOOL(xpathobjp->boolval);
514 			break;
515 
516 		case XPATH_NUMBER:
517 			RETVAL_DOUBLE(xpathobjp->floatval)
518 			break;
519 
520 		case XPATH_STRING:
521 			RETVAL_STRING(xpathobjp->stringval, 1);
522 			break;
523 
524 		default:
525 			RETVAL_NULL();
526 			break;
527 	}
528 
529 	xmlXPathFreeObject(xpathobjp);
530 }
531 /* }}} */
532 
533 /* {{{ proto DOMNodeList dom_xpath_query(string expr [,DOMNode context [, boolean registerNodeNS]]); */
PHP_FUNCTION(dom_xpath_query)534 PHP_FUNCTION(dom_xpath_query)
535 {
536 	php_xpath_eval(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_DOM_XPATH_QUERY);
537 }
538 /* }}} end dom_xpath_query */
539 
540 /* {{{ proto mixed dom_xpath_evaluate(string expr [,DOMNode context [, boolean registerNodeNS]]); */
PHP_FUNCTION(dom_xpath_evaluate)541 PHP_FUNCTION(dom_xpath_evaluate)
542 {
543 	php_xpath_eval(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_DOM_XPATH_EVALUATE);
544 }
545 /* }}} end dom_xpath_evaluate */
546 
547 /* {{{ proto void dom_xpath_register_php_functions() */
PHP_FUNCTION(dom_xpath_register_php_functions)548 PHP_FUNCTION(dom_xpath_register_php_functions)
549 {
550 	zval *id;
551 	dom_xpath_object *intern;
552 	zval *array_value, **entry, *new_string;
553 	int  name_len = 0;
554 	char *name;
555 
556 	DOM_GET_THIS(id);
557 
558 	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "a",  &array_value) == SUCCESS) {
559 		intern = (dom_xpath_object *)zend_object_store_get_object(id TSRMLS_CC);
560 		zend_hash_internal_pointer_reset(Z_ARRVAL_P(array_value));
561 
562 		while (zend_hash_get_current_data(Z_ARRVAL_P(array_value), (void **)&entry) == SUCCESS) {
563 			SEPARATE_ZVAL(entry);
564 			convert_to_string_ex(entry);
565 
566 			MAKE_STD_ZVAL(new_string);
567 			ZVAL_LONG(new_string,1);
568 
569 			zend_hash_update(intern->registered_phpfunctions, Z_STRVAL_PP(entry), Z_STRLEN_PP(entry) + 1, &new_string, sizeof(zval*), NULL);
570 			zend_hash_move_forward(Z_ARRVAL_P(array_value));
571 		}
572 		intern->registerPhpFunctions = 2;
573 		RETURN_TRUE;
574 
575 	} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "s",  &name, &name_len) == SUCCESS) {
576 		intern = (dom_xpath_object *)zend_object_store_get_object(id TSRMLS_CC);
577 
578 		MAKE_STD_ZVAL(new_string);
579 		ZVAL_LONG(new_string,1);
580 		zend_hash_update(intern->registered_phpfunctions, name, name_len + 1, &new_string, sizeof(zval*), NULL);
581 		intern->registerPhpFunctions = 2;
582 
583 	} else {
584 		intern = (dom_xpath_object *)zend_object_store_get_object(id TSRMLS_CC);
585 		intern->registerPhpFunctions = 1;
586 	}
587 
588 }
589 /* }}} end dom_xpath_register_php_functions */
590 
591 #endif /* LIBXML_XPATH_ENABLED */
592 
593 #endif
594 
595 /*
596  * Local variables:
597  * tab-width: 4
598  * c-basic-offset: 4
599  * End:
600  * vim600: noet sw=4 ts=4 fdm=marker
601  * vim<600: noet sw=4 ts=4
602  */
603