php-src/ext/domxml/php_domxml.c
Joseph Tate 7ad4b465ca Commented out a few lines that were causing a segfault in the unlink code.
This fixes bug #14522.  I've tested that it does not cause a segfault under
RH 7.2, and retains all functionality.  I recommend that this patch be
considered for the PHP_4_2_0 tree as well, as having a function that core
dumps every time is a bad thing(TM).
2002-03-07 23:52:57 +00:00

3620 lines
92 KiB
C

/*
+----------------------------------------------------------------------+
| PHP Version 4 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2002 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 2.02 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available at through the world-wide-web at |
| http://www.php.net/license/2_02.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Uwe Steinmann <steinm@php.net> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
/* TODO
* - Support Notation Nodes
* */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_domxml.h"
#if HAVE_DOMXML
#include "ext/standard/info.h"
#define PHP_XPATH 1
#define PHP_XPTR 2
/* General macros used by domxml */
#define DOMXML_DOMOBJ_NEW(zval, obj, ret) if (NULL == (zval = php_domobject_new(obj, ret TSRMLS_CC))) { \
php_error(E_WARNING, "%s(): cannot create required DOM object", \
get_active_function_name(TSRMLS_C)); \
RETURN_FALSE; \
}
#define DOMXML_RET_ZVAL(zval) SEPARATE_ZVAL(&zval); \
*return_value = *zval; \
FREE_ZVAL(zval);
#define DOMXML_RET_OBJ(zval, obj, ret) DOMXML_DOMOBJ_NEW(zval, obj, ret); \
DOMXML_RET_ZVAL(zval);
#define DOMXML_GET_THIS(zval) if (NULL == (zval = getThis())) { \
php_error(E_WARNING, "%s(): underlying object missing", \
get_active_function_name(TSRMLS_C)); \
RETURN_FALSE; \
}
#define DOMXML_GET_OBJ(ret, zval, le) if (NULL == (ret = php_dom_get_object(zval, le, 0 TSRMLS_CC))) { \
php_error(E_WARNING, "%s(): cannot fetch DOM object", \
get_active_function_name(TSRMLS_C)); \
RETURN_FALSE; \
}
#define DOMXML_GET_THIS_OBJ(ret, zval, le) DOMXML_GET_THIS(zval); \
DOMXML_GET_OBJ(ret, zval, le);
#define DOMXML_NO_ARGS() if (ZEND_NUM_ARGS() != 0) { \
php_error(E_WARNING, "%s() expects exactly 0 parameters, %d given", \
get_active_function_name(TSRMLS_C), ZEND_NUM_ARGS()); \
return; \
}
#define DOMXML_NOT_IMPLEMENTED() php_error(E_WARNING, "%s() not yet implemented", \
get_active_function_name(TSRMLS_C)); \
return;
/* WARNING: The number of parameters is actually the
* number of passed variables to zend_parse_parameters(),
* *NOT* the number of parameters expected by the PHP function. */
#define DOMXML_PARAM_NONE(ret, zval, le) if (NULL == (zval = getThis())) { \
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &zval) == FAILURE) { \
return; \
} \
} \
DOMXML_GET_OBJ(ret, zval, le);
#define DOMXML_PARAM_ONE(ret, zval, le, s, p1) if (NULL == (zval = getThis())) { \
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o"s, &zval, p1) == FAILURE) { \
return; \
} \
} else { \
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, s, p1) == FAILURE) { \
return; \
} \
} \
DOMXML_GET_OBJ(ret, zval, le);
#define DOMXML_PARAM_TWO(ret, zval, le, s, p1, p2) if (NULL == (zval = getThis())) { \
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o"s, &zval, p1, p2) == FAILURE) { \
return; \
} \
} else { \
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, s, p1, p2) == FAILURE) { \
return; \
} \
} \
DOMXML_GET_OBJ(ret, zval, le);
#define DOMXML_PARAM_THREE(ret, zval, le, s, p1, p2, p3) if (NULL == (zval = getThis())) { \
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o"s, &zval, p1, p2, p3) == FAILURE) { \
return; \
} \
} else { \
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, s, p1, p2, p3) == FAILURE) { \
return; \
} \
} \
DOMXML_GET_OBJ(ret, zval, le);
#define DOMXML_PARAM_FOUR(ret, zval, le, s, p1, p2, p3, p4) if (NULL == (zval = getThis())) { \
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o"s, &zval, p1, p2, p3, p4) == FAILURE) { \
return; \
} \
} else { \
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, s, p1, p2, p3, p4) == FAILURE) { \
return; \
} \
} \
DOMXML_GET_OBJ(ret, zval, le);
static int le_domxmldocp;
static int le_domxmldoctypep;
static int le_domxmldtdp;
static int le_domxmlnodep;
static int le_domxmlelementp;
static int le_domxmlattrp;
static int le_domxmlcdatap;
static int le_domxmltextp;
static int le_domxmlpip;
static int le_domxmlcommentp;
static int le_domxmlnotationp;
/*static int le_domxmlentityp;*/
static int le_domxmlentityrefp;
/*static int le_domxmlnsp;*/
#if HAVE_DOMXSLT
static int le_domxsltstylesheetp;
#endif
#if defined(LIBXML_XPATH_ENABLED)
static int le_xpathctxp;
static int le_xpathobjectp;
#endif
zend_class_entry *domxmldoc_class_entry;
zend_class_entry *domxmldoctype_class_entry;
zend_class_entry *domxmlelement_class_entry;
zend_class_entry *domxmldtd_class_entry;
zend_class_entry *domxmlnode_class_entry;
zend_class_entry *domxmlattr_class_entry;
zend_class_entry *domxmlcdata_class_entry;
zend_class_entry *domxmltext_class_entry;
zend_class_entry *domxmlpi_class_entry;
zend_class_entry *domxmlcomment_class_entry;
zend_class_entry *domxmlnotation_class_entry;
zend_class_entry *domxmlentity_class_entry;
zend_class_entry *domxmlentityref_class_entry;
zend_class_entry *domxmlns_class_entry;
#if defined(LIBXML_XPATH_ENABLED)
zend_class_entry *xpathctx_class_entry;
zend_class_entry *xpathobject_class_entry;
#endif
#if HAVE_DOMXSLT
zend_class_entry *domxsltstylesheet_class_entry;
#endif
static int node_attributes(zval **attributes, xmlNode *nodep TSRMLS_DC);
static int node_children(zval **children, xmlNode *nodep TSRMLS_DC);
static zend_function_entry domxml_functions[] = {
PHP_FE(domxml_version, NULL)
PHP_FE(xmldoc, NULL)
PHP_FE(xmldocfile, NULL)
#if defined(LIBXML_HTML_ENABLED)
PHP_FE(html_doc, NULL)
PHP_FE(html_doc_file, NULL)
#endif
PHP_FE(xmltree, NULL)
PHP_FE(domxml_substitute_entities_default, NULL)
PHP_FE(domxml_add_root, NULL)
PHP_FE(domxml_dump_mem, NULL)
PHP_FE(domxml_dump_mem_file, NULL)
PHP_FE(domxml_dump_node, NULL)
#if defined(LIBXML_HTML_ENABLED)
PHP_FE(domxml_html_dump_mem, NULL)
#endif
PHP_FE(domxml_node_attributes, NULL)
PHP_FE(domxml_elem_get_attribute, NULL)
PHP_FE(domxml_elem_set_attribute, NULL)
PHP_FE(domxml_node_children, NULL)
PHP_FE(domxml_node_has_attributes, NULL)
PHP_FE(domxml_node_new_child, NULL)
PHP_FE(domxml_node, NULL)
PHP_FE(domxml_node_unlink_node, NULL)
PHP_FE(domxml_node_set_content, NULL)
PHP_FE(domxml_node_get_content, NULL)
PHP_FE(domxml_new_xmldoc, NULL)
#if defined(LIBXML_XPATH_ENABLED)
PHP_FE(xpath_new_context, NULL)
PHP_FE(xpath_eval, NULL)
PHP_FE(xpath_eval_expression, NULL)
PHP_FE(xpath_register_ns, NULL)
#endif
#if defined(LIBXML_XPTR_ENABLED)
PHP_FE(xptr_new_context, NULL)
PHP_FE(xptr_eval, NULL)
#endif
#if HAVE_DOMXSLT
PHP_FE(domxml_xslt_version, NULL)
PHP_FE(domxml_xslt_stylesheet, NULL)
PHP_FE(domxml_xslt_stylesheet_doc, NULL)
PHP_FE(domxml_xslt_stylesheet_file, NULL)
PHP_FE(domxml_xslt_process, NULL)
#endif
PHP_FALIAS(domxml_root, domxml_doc_document_element, NULL)
PHP_FALIAS(domxml_attributes, domxml_node_attributes, NULL)
PHP_FALIAS(domxml_get_attribute, domxml_elem_get_attribute, NULL)
PHP_FALIAS(domxml_getattr, domxml_elem_get_attribute, NULL)
PHP_FALIAS(domxml_set_attribute, domxml_elem_set_attribute, NULL)
PHP_FALIAS(domxml_setattr, domxml_elem_set_attribute, NULL)
PHP_FALIAS(domxml_children, domxml_node_children, NULL)
PHP_FALIAS(domxml_new_child, domxml_node_new_child, NULL)
PHP_FALIAS(domxml_unlink_node, domxml_node_unlink_node, NULL)
PHP_FALIAS(set_content, domxml_node_set_content, NULL)
PHP_FALIAS(new_xmldoc, domxml_new_xmldoc, NULL)
PHP_FALIAS(domxml_dumpmem, domxml_dump_mem, NULL)
{NULL, NULL, NULL}
};
static function_entry php_domxmldoc_class_functions[] = {
/* PHP_FALIAS(domdocument, xmldoc, NULL) */
{"domdocument", PHP_FN(xmldoc), NULL},
PHP_FALIAS(doctype, domxml_doc_doctype, NULL)
PHP_FALIAS(implementation, domxml_doc_implementation, NULL)
PHP_FALIAS(root, domxml_doc_document_element, NULL) /* not DOM */
PHP_FALIAS(document_element, domxml_doc_document_element, NULL)
PHP_FALIAS(create_element, domxml_doc_create_element, NULL)
PHP_FALIAS(create_text_node, domxml_doc_create_text_node, NULL)
PHP_FALIAS(create_comment, domxml_doc_create_comment, NULL)
PHP_FALIAS(create_attribute, domxml_doc_create_attribute, NULL)
PHP_FALIAS(create_cdata_section, domxml_doc_create_cdata_section, NULL)
PHP_FALIAS(create_entity_reference, domxml_doc_create_entity_reference, NULL)
PHP_FALIAS(create_processing_instruction, domxml_doc_create_processing_instruction, NULL)
PHP_FALIAS(children, domxml_node_children, NULL)
PHP_FALIAS(add_root, domxml_add_root, NULL)
PHP_FALIAS(imported_node, domxml_doc_imported_node, NULL)
PHP_FALIAS(dtd, domxml_intdtd, NULL)
PHP_FALIAS(dumpmem, domxml_dump_mem, NULL)
PHP_FALIAS(dump_mem, domxml_dump_mem, NULL)
PHP_FALIAS(dump_mem_file, domxml_dump_mem_file, NULL)
#if defined(LIBXML_HTML_ENABLED)
PHP_FALIAS(html_dump_mem, domxml_html_dump_mem, NULL)
#endif
#if defined(LIBXML_XPATH_ENABLED)
PHP_FALIAS(xpath_init, xpath_init, NULL)
PHP_FALIAS(xpath_new_context, xpath_new_context, NULL)
PHP_FALIAS(xptr_new_context, xptr_new_context, NULL)
#endif
{NULL, NULL, NULL}
};
static function_entry php_domxmldoctype_class_functions[] = {
PHP_FALIAS(name, domxml_doctype_name, NULL)
/*
PHP_FALIAS(entities, domxml_doctype_entities, NULL)
PHP_FALIAS(notations, domxml_doctype_notations, NULL)
PHP_FALIAS(system_id, domxml_doctype_system_id, NULL)
PHP_FALIAS(public_id, domxml_doctype_public_id, NULL)
PHP_FALIAS(internal_subset, domxml_doctype_internal_subset, NULL)
*/
{NULL, NULL, NULL}
};
static zend_function_entry php_domxmldtd_class_functions[] = {
{NULL, NULL, NULL}
};
static zend_function_entry php_domxmlnode_class_functions[] = {
PHP_FALIAS(domnode, domxml_node, NULL)
PHP_FALIAS(first_child, domxml_node_first_child, NULL)
PHP_FALIAS(last_child, domxml_node_last_child, NULL)
PHP_FALIAS(add_child, domxml_node_add_child, NULL)
PHP_FALIAS(children, domxml_node_children, NULL)
PHP_FALIAS(child_nodes, domxml_node_children, NULL)
PHP_FALIAS(previous_sibling, domxml_node_previous_sibling, NULL)
PHP_FALIAS(next_sibling, domxml_node_next_sibling, NULL)
PHP_FALIAS(has_child_nodes, domxml_node_has_child_nodes, NULL)
PHP_FALIAS(prefix, domxml_node_prefix, NULL)
PHP_FALIAS(parent, domxml_node_parent, NULL)
PHP_FALIAS(parent_node, domxml_node_parent, NULL)
PHP_FALIAS(insert_before, domxml_node_insert_before, NULL)
PHP_FALIAS(append_child, domxml_node_append_child, NULL)
PHP_FALIAS(owner_document, domxml_node_owner_document, NULL)
PHP_FALIAS(new_child, domxml_node_new_child, NULL)
PHP_FALIAS(attributes, domxml_node_attributes, NULL)
PHP_FALIAS(has_attributes, domxml_node_has_attributes, NULL)
PHP_FALIAS(node, domxml_node, NULL)
PHP_FALIAS(unlink, domxml_node_unlink_node, NULL)
PHP_FALIAS(replace_node, domxml_node_replace_node, NULL)
PHP_FALIAS(set_content, domxml_node_set_content, NULL)
PHP_FALIAS(get_content, domxml_node_get_content, NULL)
PHP_FALIAS(text_concat, domxml_node_text_concat, NULL)
PHP_FALIAS(set_name, domxml_node_set_name, NULL)
PHP_FALIAS(node_name, domxml_node_name, NULL)
PHP_FALIAS(node_type, domxml_node_type, NULL)
PHP_FALIAS(node_value, domxml_node_value, NULL)
PHP_FALIAS(clone_node, domxml_clone_node, NULL)
PHP_FALIAS(is_blank_node, domxml_is_blank_node, NULL)
PHP_FALIAS(dump_node, domxml_dump_node, NULL)
{NULL, NULL, NULL}
};
static zend_function_entry php_domxmlelement_class_functions[] = {
PHP_FALIAS(domelement, domxml_element, NULL)
PHP_FALIAS(name, domxml_elem_tagname, NULL)
PHP_FALIAS(tagname, domxml_elem_tagname, NULL)
PHP_FALIAS(get_attribute, domxml_elem_get_attribute, NULL)
PHP_FALIAS(set_attribute, domxml_elem_set_attribute, NULL)
PHP_FALIAS(remove_attribute, domxml_elem_remove_attribute, NULL)
PHP_FALIAS(get_attributenode, domxml_elem_get_attribute_node, NULL)
PHP_FALIAS(set_attributenode, domxml_elem_set_attribute_node, NULL)
PHP_FALIAS(get_element_by_tagname, domxml_elem_get_element_by_tagname, NULL)
{NULL, NULL, NULL}
};
static zend_function_entry php_domxmlcdata_class_functions[] = {
PHP_FALIAS(length, domxml_cdata_length, NULL)
{NULL, NULL, NULL}
};
static zend_function_entry php_domxmltext_class_functions[] = {
{NULL, NULL, NULL}
};
static zend_function_entry php_domxmlcomment_class_functions[] = {
{NULL, NULL, NULL}
};
static zend_function_entry php_domxmlnotation_class_functions[] = {
PHP_FALIAS(public_id, domxml_notation_public_id, NULL)
PHP_FALIAS(system_id, domxml_notation_system_id, NULL)
{NULL, NULL, NULL}
};
static zend_function_entry php_domxmlentityref_class_functions[] = {
{NULL, NULL, NULL}
};
static zend_function_entry php_domxmlentity_class_functions[] = {
/*
PHP_FALIAS(public_id, domxml_entity_public_id, NULL)
PHP_FALIAS(system_id, domxml_entity_system_id, NULL)
PHP_FALIAS(notation_name, domxml_entity_notation_name, NULL)
*/
{NULL, NULL, NULL}
};
static zend_function_entry php_domxmlpi_class_functions[] = {
PHP_FALIAS(target, domxml_pi_target, NULL)
PHP_FALIAS(data, domxml_pi_data, NULL)
{NULL, NULL, NULL}
};
#if defined(LIBXML_XPATH_ENABLED)
static zend_function_entry php_xpathctx_class_functions[] = {
PHP_FALIAS(xpath_eval, xpath_eval, NULL)
PHP_FALIAS(xpath_eval_expression, xpath_eval_expression, NULL)
PHP_FALIAS(xpath_register_ns, xpath_register_ns, NULL)
{NULL, NULL, NULL}
};
static zend_function_entry php_xpathobject_class_functions[] = {
{NULL, NULL, NULL}
};
#endif
static zend_function_entry php_domxmlattr_class_functions[] = {
PHP_FALIAS(name, domxml_attr_name, NULL)
PHP_FALIAS(value, domxml_attr_value, NULL)
PHP_FALIAS(specified, domxml_attr_specified, NULL)
/*
PHP_FALIAS(owner_element, domxml_attr_owner_element, NULL)
*/
{NULL, NULL, NULL}
};
static zend_function_entry php_domxmlns_class_functions[] = {
{NULL, NULL, NULL}
};
#if HAVE_DOMXSLT
static zend_function_entry php_domxsltstylesheet_class_functions[] = {
/* TODO: maybe some more methods? */
PHP_FALIAS(process, domxml_xslt_process, NULL)
{NULL, NULL, NULL}
};
#endif
zend_module_entry domxml_module_entry = {
STANDARD_MODULE_HEADER,
"domxml",
domxml_functions,
PHP_MINIT(domxml),
NULL,
PHP_RINIT(domxml),
NULL,
PHP_MINFO(domxml),
NO_VERSION_YET,
STANDARD_MODULE_PROPERTIES
};
#ifdef COMPILE_DL_DOMXML
ZEND_GET_MODULE(domxml)
#endif
static void dom_object_set_data(void *obj, zval *wrapper)
{
/*
char tmp[20];
sprintf(tmp, "%08X", obj);
fprintf(stderr, "Adding %s to hash\n", tmp);
*/
((xmlNodePtr) obj)->_private = wrapper;
}
static zval *dom_object_get_data(void *obj)
{
/*
char tmp[20];
sprintf(tmp, "%08X", obj);
fprintf(stderr, "Trying getting %s from object ...", tmp);
if(((xmlNodePtr) obj)->_private)
fprintf(stderr, " found\n");
else
fprintf(stderr, " not found\n");
*/
return ((zval *) (((xmlNodePtr) obj)->_private));
}
static inline void node_wrapper_dtor(xmlNodePtr node)
{
zval *wrapper;
// FIXME: type check probably unnecessary here?
if (!node || Z_TYPE_P(node) == XML_DTD_NODE)
return;
wrapper = dom_object_get_data(node);
if (wrapper)
zval_ptr_dtor(&wrapper);
}
static inline void attr_list_wrapper_dtor(xmlAttrPtr attr)
{
while (attr != NULL) {
node_wrapper_dtor((xmlNodePtr) attr);
attr = attr->next;
}
}
static inline void node_list_wrapper_dtor(xmlNodePtr node)
{
while (node != NULL) {
node_list_wrapper_dtor(node->children);
switch (node->type) {
/* Skip property freeing for the following types */
case XML_ATTRIBUTE_DECL:
case XML_DTD_NODE:
case XML_ENTITY_DECL:
break;
default:
attr_list_wrapper_dtor(node->properties);
}
node_wrapper_dtor(node);
node = node->next;
}
}
static void php_free_xml_doc(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
xmlDoc *doc = (xmlDoc *) rsrc->ptr;
if (doc) {
node_list_wrapper_dtor(doc->children);
node_wrapper_dtor((xmlNodePtr) doc);
xmlFreeDoc(doc);
}
}
static void php_free_xml_node(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
xmlNodePtr node = (xmlNodePtr) rsrc->ptr;
if (node) {
zval *wrapper = dom_object_get_data(node);
if (wrapper)
zval_ptr_dtor(&wrapper);
}
}
#if defined(LIBXML_XPATH_ENABLED)
static void php_free_xpath_context(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
xmlXPathContextPtr ctx = (xmlXPathContextPtr) rsrc->ptr;
if (ctx) {
if (ctx->user) {
zval *wrapper = ctx->user;
zval_ptr_dtor(&wrapper);
}
xmlXPathFreeContext(ctx);
}
}
static void php_free_xpath_object(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
xmlXPathObjectPtr obj = (xmlXPathObjectPtr) rsrc->ptr;
if (obj) {
if (obj->user) {
zval *wrapper = obj->user;
zval_ptr_dtor(&wrapper);
}
xmlXPathFreeObject(obj);
}
}
#endif
#if HAVE_DOMXSLT
static void php_free_xslt_stylesheet(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
xsltStylesheetPtr sheet = (xsltStylesheetPtr) rsrc->ptr;
if (sheet) {
node_wrapper_dtor((xmlNodePtr) sheet);
xsltFreeStylesheet(sheet);
}
}
static void xsltstylesheet_set_data(void *obj, zval *wrapper)
{
/*
char tmp[20];
sprintf(tmp, "%08X", obj);
fprintf(stderr, "Adding %s to hash\n", tmp);
*/
((xsltStylesheetPtr) obj)->_private = wrapper;
}
static zval *xsltstylesheet_get_data(void *obj)
{
/*
char tmp[20];
sprintf(tmp, "%08X", obj);
fprintf(stderr, "Trying getting %s from object ...", tmp);
if(((xmlNodePtr) obj)->_private)
fprintf(stderr, " found\n");
else
fprintf(stderr, " not found\n");
*/
return ((zval *) (((xsltStylesheetPtr) obj)->_private));
}
void *php_xsltstylesheet_get_object(zval *wrapper, int rsrc_type1, int rsrc_type2 TSRMLS_DC)
{
void *obj;
zval **handle;
int type;
if (NULL == wrapper) {
php_error(E_WARNING, "xsltstylesheet_get_object() invalid wrapper object passed");
return NULL;
}
if (Z_TYPE_P(wrapper) != IS_OBJECT) {
php_error(E_WARNING, "%s(): wrapper is not an object", get_active_function_name(TSRMLS_C));
return NULL;
}
if (zend_hash_index_find(Z_OBJPROP_P(wrapper), 0, (void **) &handle) == FAILURE) {
php_error(E_WARNING, "%s(): underlying object missing", get_active_function_name(TSRMLS_C));
return NULL;
}
obj = zend_list_find(Z_LVAL_PP(handle), &type);
if (!obj || ((type != rsrc_type1) && (type != rsrc_type2))) {
php_error(E_WARNING, "%s(): underlying object missing or of invalid type", get_active_function_name(TSRMLS_C));
return NULL;
}
return obj;
}
static void php_xsltstylesheet_set_object(zval *wrapper, void *obj, int rsrc_type)
{
zval *handle, *addr;
MAKE_STD_ZVAL(handle);
Z_TYPE_P(handle) = IS_LONG;
Z_LVAL_P(handle) = zend_list_insert(obj, rsrc_type);
MAKE_STD_ZVAL(addr);
Z_TYPE_P(addr) = IS_LONG;
Z_LVAL_P(addr) = (int) obj;
zend_hash_index_update(Z_OBJPROP_P(wrapper), 0, &handle, sizeof(zval *), NULL);
zend_hash_index_update(Z_OBJPROP_P(wrapper), 1, &addr, sizeof(zval *), NULL);
zval_add_ref(&wrapper);
xsltstylesheet_set_data(obj, wrapper);
}
#endif /* HAVE_DOMXSLT */
void *php_xpath_get_object(zval *wrapper, int rsrc_type1, int rsrc_type2 TSRMLS_DC)
{
void *obj;
zval **handle;
int type;
if (NULL == wrapper) {
php_error(E_WARNING, "php_xpath_get_object() invalid wrapper object passed");
return NULL;
}
if (Z_TYPE_P(wrapper) != IS_OBJECT) {
php_error(E_WARNING, "%s(): wrapper is not an object", get_active_function_name(TSRMLS_C));
return NULL;
}
if (zend_hash_index_find(Z_OBJPROP_P(wrapper), 0, (void **) &handle) == FAILURE) {
php_error(E_WARNING, "%s(): underlying object missing", get_active_function_name(TSRMLS_C));
return NULL;
}
obj = zend_list_find(Z_LVAL_PP(handle), &type);
if (!obj || ((type != rsrc_type1) && (type != rsrc_type2))) {
php_error(E_WARNING, "%s(): underlying object missing or of invalid type", get_active_function_name(TSRMLS_C));
return NULL;
}
return obj;
}
static void xpath_object_set_data(void *obj, zval *wrapper)
{
/*
char tmp[20];
sprintf(tmp, "%08X", obj);
fprintf(stderr, "Adding %s to hash\n", tmp);
*/
((xmlXPathObjectPtr) obj)->user = wrapper;
}
static zval *xpath_object_get_data(void *obj)
{
/*
char tmp[20];
sprintf(tmp, "%08X", obj);
fprintf(stderr, "Trying getting %s from hash ...", tmp);
if(((xmlXPathObjectPtr) obj)->user)
fprintf(stderr, " found\n");
else
fprintf(stderr, " not found\n");
*/
return ((zval *) (((xmlXPathObjectPtr) obj)->user));
}
static void php_xpath_set_object(zval *wrapper, void *obj, int rsrc_type)
{
zval *handle, *addr;
MAKE_STD_ZVAL(handle);
Z_TYPE_P(handle) = IS_LONG;
Z_LVAL_P(handle) = zend_list_insert(obj, rsrc_type);
MAKE_STD_ZVAL(addr);
Z_TYPE_P(addr) = IS_LONG;
Z_LVAL_P(addr) = (int) obj;
zend_hash_index_update(Z_OBJPROP_P(wrapper), 0, &handle, sizeof(zval *), NULL);
zend_hash_index_update(Z_OBJPROP_P(wrapper), 1, &addr, sizeof(zval *), NULL);
zval_add_ref(&wrapper);
xpath_object_set_data(obj, wrapper);
}
static zval *php_xpathobject_new(xmlXPathObjectPtr obj, int *found TSRMLS_DC)
{
zval *wrapper;
if (! found) {
*found = 0;
}
if (!obj) {
MAKE_STD_ZVAL(wrapper);
ZVAL_NULL(wrapper);
return wrapper;
}
if ((wrapper = (zval *) xpath_object_get_data((void *) obj))) {
zval_add_ref(&wrapper);
*found = 1;
return wrapper;
}
MAKE_STD_ZVAL(wrapper);
object_init_ex(wrapper, xpathobject_class_entry);
/*
rsrc_type = le_xpathobjectp;
php_xpath_set_object(wrapper, (void *) obj, rsrc_type);
*/
php_xpath_set_object(wrapper, (void *) obj, le_xpathobjectp);
return (wrapper);
}
void *php_xpath_get_context(zval *wrapper, int rsrc_type1, int rsrc_type2 TSRMLS_DC)
{
void *obj;
zval **handle;
int type;
if (NULL == wrapper) {
php_error(E_WARNING, "php_xpath_get_context() invalid wrapper object passed");
return NULL;
}
if (Z_TYPE_P(wrapper) != IS_OBJECT) {
php_error(E_WARNING, "%s(): wrapper is not an object", get_active_function_name(TSRMLS_C));
return NULL;
}
if (zend_hash_index_find(Z_OBJPROP_P(wrapper), 0, (void **) &handle) ==
FAILURE) {
php_error(E_WARNING, "%s(): underlying object missing", get_active_function_name(TSRMLS_C));
return NULL;
}
obj = zend_list_find(Z_LVAL_PP(handle), &type);
if (!obj || ((type != rsrc_type1) && (type != rsrc_type2))) {
php_error(E_WARNING, "%s(): underlying object missing or of invalid type", get_active_function_name(TSRMLS_C));
return NULL;
}
return obj;
}
static void xpath_context_set_data(void *obj, zval *wrapper)
{
/*
char tmp[20];
sprintf(tmp, "%08X", obj);
fprintf(stderr, "Adding %s to hash\n", tmp);
*/
((xmlXPathContextPtr) obj)->user = (void *) wrapper;
}
static zval *xpath_context_get_data(void *obj)
{
/*
char tmp[20];
sprintf(tmp, "%08X", obj);
fprintf(stderr, "Trying getting %s from hash ...", tmp);
if(((xmlXPathContextPtr) obj)->user)
fprintf(stderr, " found\n");
else
fprintf(stderr, " not found\n");
*/
return ((zval *) (((xmlXPathContextPtr) obj)->user));
}
static void php_xpath_set_context(zval *wrapper, void *obj, int rsrc_type)
{
zval *handle, *addr;
MAKE_STD_ZVAL(handle);
Z_TYPE_P(handle) = IS_LONG;
Z_LVAL_P(handle) = zend_list_insert(obj, rsrc_type);
MAKE_STD_ZVAL(addr);
Z_TYPE_P(addr) = IS_LONG;
Z_LVAL_P(addr) = (int) obj;
zend_hash_index_update(Z_OBJPROP_P(wrapper), 0, &handle, sizeof(zval *), NULL);
zend_hash_index_update(Z_OBJPROP_P(wrapper), 1, &addr, sizeof(zval *), NULL);
zval_add_ref(&wrapper);
xpath_context_set_data(obj, wrapper);
}
static zval *php_xpathcontext_new(xmlXPathContextPtr obj, int *found TSRMLS_DC)
{
zval *wrapper;
int rsrc_type;
if (! found) {
*found = 0;
}
if (!obj) {
MAKE_STD_ZVAL(wrapper);
ZVAL_NULL(wrapper);
return wrapper;
}
if ((wrapper = (zval *) xpath_context_get_data((void *) obj))) {
zval_add_ref(&wrapper);
*found = 1;
return wrapper;
}
MAKE_STD_ZVAL(wrapper);
/*
fprintf(stderr, "Adding new XPath Context\n");
*/
object_init_ex(wrapper, xpathctx_class_entry);
rsrc_type = le_xpathctxp;
php_xpath_set_context(wrapper, (void *) obj, rsrc_type);
return (wrapper);
}
void *php_dom_get_object(zval *wrapper, int rsrc_type1, int rsrc_type2 TSRMLS_DC)
{
void *obj;
zval **handle;
int type;
if (NULL == wrapper) {
php_error(E_WARNING, "php_dom_get_object() invalid wrapper object passed");
return NULL;
}
if (Z_TYPE_P(wrapper) != IS_OBJECT) {
php_error(E_WARNING, "%s(): wrapper is not an object", get_active_function_name(TSRMLS_C));
return NULL;
}
if (zend_hash_index_find(Z_OBJPROP_P(wrapper), 0, (void **) &handle) == FAILURE) {
php_error(E_WARNING, "%s(): underlying object missing", get_active_function_name(TSRMLS_C));
return NULL;
}
obj = zend_list_find(Z_LVAL_PP(handle), &type);
/* The following test should be replaced with search in all parents */
if (!obj) { /* || ((type != rsrc_type1) && (type != rsrc_type2))) { */
php_error(E_WARNING, "%s(): underlying object missing or of invalid type", get_active_function_name(TSRMLS_C));
return NULL;
}
return obj;
}
static void php_dom_set_object(zval *wrapper, void *obj, int rsrc_type)
{
zval *handle, *addr;
MAKE_STD_ZVAL(handle);
Z_TYPE_P(handle) = IS_LONG;
Z_LVAL_P(handle) = zend_list_insert(obj, rsrc_type);
MAKE_STD_ZVAL(addr);
Z_TYPE_P(addr) = IS_LONG;
Z_LVAL_P(addr) = (int) obj;
zend_hash_index_update(Z_OBJPROP_P(wrapper), 0, &handle, sizeof(zval *), NULL);
zend_hash_index_update(Z_OBJPROP_P(wrapper), 1, &addr, sizeof(zval *), NULL);
zval_add_ref(&wrapper);
dom_object_set_data(obj, wrapper);
}
static zval *php_domobject_new(xmlNodePtr obj, int *found TSRMLS_DC)
{
zval *wrapper;
char *content;
int rsrc_type;
if (! found) {
*found = 0;
}
if (!obj) {
MAKE_STD_ZVAL(wrapper);
ZVAL_NULL(wrapper);
return wrapper;
}
if ((wrapper = (zval *) dom_object_get_data((void *) obj))) {
zval_add_ref(&wrapper);
*found = 1;
return wrapper;
}
MAKE_STD_ZVAL(wrapper);
switch (Z_TYPE_P(obj)) {
case XML_ELEMENT_NODE:
{
xmlNodePtr nodep = obj;
object_init_ex(wrapper, domxmlelement_class_entry);
rsrc_type = le_domxmlelementp;
add_property_long(wrapper, "type", Z_TYPE_P(nodep));
add_property_stringl(wrapper, "tagname", (char *) nodep->name, strlen(nodep->name), 1);
break;
}
case XML_TEXT_NODE:
{
xmlNodePtr nodep = obj;
object_init_ex(wrapper, domxmltext_class_entry);
rsrc_type = le_domxmltextp;
content = xmlNodeGetContent(nodep);
if (content) {
add_property_long(wrapper, "type", Z_TYPE_P(nodep));
add_property_stringl(wrapper, "content", (char *) content, strlen(content), 1);
}
break;
}
case XML_COMMENT_NODE:
{
xmlNodePtr nodep = obj;
object_init_ex(wrapper, domxmlcomment_class_entry);
rsrc_type = le_domxmlcommentp;
content = xmlNodeGetContent(nodep);
if (content) {
add_property_long(wrapper, "type", Z_TYPE_P(nodep));
add_property_stringl(wrapper, "content", (char *) content, strlen(content), 1);
}
break;
}
case XML_PI_NODE:
{
xmlNodePtr nodep = obj;
object_init_ex(wrapper, domxmlpi_class_entry);
rsrc_type = le_domxmlpip;
content = xmlNodeGetContent(nodep);
add_property_stringl(wrapper, "target", (char *) nodep->name, strlen(nodep->name), 1);
if (content)
add_property_stringl(wrapper, "data", (char *) content, strlen(content), 1);
break;
}
case XML_ENTITY_REF_NODE:
{
xmlNodePtr nodep = obj;
object_init_ex(wrapper, domxmlentityref_class_entry);
rsrc_type = le_domxmlentityrefp;
add_property_stringl(wrapper, "name", (char *) nodep->name, strlen(nodep->name), 1);
break;
}
case XML_ENTITY_DECL:
case XML_ELEMENT_DECL:
{
xmlNodePtr nodep = obj;
object_init_ex(wrapper, domxmlnode_class_entry);
rsrc_type = le_domxmlnodep;
add_property_long(wrapper, "type", Z_TYPE_P(nodep));
add_property_stringl(wrapper, "name", (char *) nodep->name, strlen(nodep->name), 1);
if (Z_TYPE_P(obj) == XML_ENTITY_REF_NODE) {
content = xmlNodeGetContent(nodep);
if (content)
add_property_stringl(wrapper, "content", (char *) content, strlen(content), 1);
}
break;
}
case XML_ATTRIBUTE_NODE:
{
xmlAttrPtr attrp = (xmlAttrPtr) obj;
object_init_ex(wrapper, domxmlattr_class_entry);
rsrc_type = le_domxmlattrp;
add_property_stringl(wrapper, "name", (char *) attrp->name, strlen(attrp->name), 1);
add_property_long(wrapper, "type", Z_TYPE_P(attrp));
content = xmlNodeGetContent((xmlNodePtr) attrp);
if (content)
add_property_stringl(wrapper, "value", (char *) content, strlen(content), 1);
break;
}
case XML_DOCUMENT_NODE:
case XML_HTML_DOCUMENT_NODE:
{
xmlDocPtr docp = (xmlDocPtr) obj;
object_init_ex(wrapper, domxmldoc_class_entry);
rsrc_type = le_domxmldocp;
if (docp->name)
add_property_stringl(wrapper, "name", (char *) docp->name, strlen(docp->name), 1);
else
add_property_stringl(wrapper, "name", "", 0, 1);
if (docp->URL)
add_property_stringl(wrapper, "url", (char *) docp->URL, strlen(docp->URL), 1);
else
add_property_stringl(wrapper, "url", "", 0, 1);
if (docp->version)
add_property_stringl(wrapper, "version", (char *) docp->version, strlen(docp->version), 1);
else
add_property_stringl(wrapper, "version", "", 0, 1);
if (docp->encoding)
add_property_stringl(wrapper, "encoding", (char *) docp->encoding, strlen(docp->encoding), 1);
add_property_long(wrapper, "standalone", docp->standalone);
add_property_long(wrapper, "type", Z_TYPE_P(docp));
add_property_long(wrapper, "compression", docp->compression);
add_property_long(wrapper, "charset", docp->charset);
break;
}
case XML_DTD_NODE:
{
xmlDtdPtr dtd = (xmlDtdPtr) obj;
object_init_ex(wrapper, domxmldtd_class_entry);
rsrc_type = le_domxmldtdp;
add_property_long(wrapper, "type", Z_TYPE_P(dtd));
if (dtd->ExternalID)
add_property_string(wrapper, "publicId", (char *) dtd->ExternalID, 1);
if (dtd->SystemID)
add_property_string(wrapper, "systemId", (char *) dtd->SystemID, 1);
if (dtd->name)
add_property_string(wrapper, "name", (char *) dtd->name, 1);
break;
}
case XML_CDATA_SECTION_NODE:
{
xmlNodePtr nodep = obj;
object_init_ex(wrapper, domxmlcdata_class_entry);
rsrc_type = le_domxmlcdatap;
content = xmlNodeGetContent(nodep);
add_property_long(wrapper, "type", Z_TYPE_P(nodep));
if (content)
add_property_stringl(wrapper, "content", (char *) content, strlen(content), 1);
break;
}
default:
php_error(E_WARNING, "%s(): unsupported node type: %d\n", get_active_function_name(TSRMLS_C), Z_TYPE_P(obj));
FREE_ZVAL(wrapper);
return NULL;
}
php_dom_set_object(wrapper, (void *) obj, rsrc_type);
return (wrapper);
}
static void domxml_error(void *ctx, const char *msg, ...)
{
char buf[1024];
va_list ap;
va_start(ap, msg);
vsnprintf(buf, 1024, msg, ap);
va_end(ap);
php_error(E_WARNING, buf);
}
PHP_RINIT_FUNCTION(domxml)
{
return SUCCESS;
}
PHP_MINIT_FUNCTION(domxml)
{
zend_class_entry ce;
le_domxmldocp = zend_register_list_destructors_ex(php_free_xml_doc, NULL, "domdocument", module_number);
/* Freeing the document contains freeing the complete tree.
Therefore nodes, attributes etc. may not be freed seperately.
*/
le_domxmlnodep = zend_register_list_destructors_ex(php_free_xml_node, NULL, "domnode", module_number);
le_domxmlcommentp = zend_register_list_destructors_ex(php_free_xml_node, NULL, "domnode", module_number);
le_domxmlattrp = zend_register_list_destructors_ex(php_free_xml_node, NULL, "domattribute", module_number);
le_domxmltextp = zend_register_list_destructors_ex(php_free_xml_node, NULL, "domtext", module_number);
le_domxmlelementp = zend_register_list_destructors_ex(php_free_xml_node, NULL, "domelement", module_number);
le_domxmldtdp = zend_register_list_destructors_ex(php_free_xml_node, NULL, "domdtd", module_number);
le_domxmlcdatap = zend_register_list_destructors_ex(php_free_xml_node, NULL, "domcdata", module_number);
le_domxmlentityrefp = zend_register_list_destructors_ex(php_free_xml_node, NULL, "domentityref", module_number);
le_domxmlpip = zend_register_list_destructors_ex(php_free_xml_node, NULL, "dompi", module_number);
/* Not yet initialized le_*s */
le_domxmldoctypep = -10000;
le_domxmlnotationp = -10003;
#if defined(LIBXML_XPATH_ENABLED)
le_xpathctxp = zend_register_list_destructors_ex(php_free_xpath_context, NULL, "xpathcontext", module_number);
le_xpathobjectp = zend_register_list_destructors_ex(php_free_xpath_object, NULL, "xpathobject", module_number);
#endif
/* le_domxmlnsp = register_list_destructors(NULL, NULL); */
#if HAVE_DOMXSLT
le_domxsltstylesheetp = zend_register_list_destructors_ex(php_free_xslt_stylesheet, NULL, "xsltstylesheet", module_number);
#endif
INIT_OVERLOADED_CLASS_ENTRY(ce, "DomNode", php_domxmlnode_class_functions, NULL, NULL, NULL);
domxmlnode_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
INIT_OVERLOADED_CLASS_ENTRY(ce, "DomDocument", php_domxmldoc_class_functions, NULL, NULL, NULL);
domxmldoc_class_entry = zend_register_internal_class_ex(&ce, domxmlnode_class_entry, NULL TSRMLS_CC);
INIT_OVERLOADED_CLASS_ENTRY(ce, "DomDocumentType", php_domxmldoctype_class_functions, NULL, NULL, NULL);
domxmldoctype_class_entry = zend_register_internal_class_ex(&ce, domxmlnode_class_entry, NULL TSRMLS_CC);
INIT_OVERLOADED_CLASS_ENTRY(ce, "Dtd", php_domxmldtd_class_functions, NULL, NULL, NULL);
domxmldtd_class_entry = zend_register_internal_class_ex(&ce, domxmlnode_class_entry, NULL TSRMLS_CC);
INIT_OVERLOADED_CLASS_ENTRY(ce, "DomElement", php_domxmlelement_class_functions, NULL, NULL, NULL);
domxmlelement_class_entry = zend_register_internal_class_ex(&ce, domxmlnode_class_entry, NULL TSRMLS_CC);
INIT_OVERLOADED_CLASS_ENTRY(ce, "DomAttribute", php_domxmlattr_class_functions, NULL, NULL, NULL);
domxmlattr_class_entry = zend_register_internal_class_ex(&ce, domxmlnode_class_entry, NULL TSRMLS_CC);
INIT_OVERLOADED_CLASS_ENTRY(ce, "DomCData", php_domxmlcdata_class_functions, NULL, NULL, NULL);
domxmlcdata_class_entry = zend_register_internal_class_ex(&ce, domxmlnode_class_entry, NULL TSRMLS_CC);
INIT_OVERLOADED_CLASS_ENTRY(ce, "DomText", php_domxmltext_class_functions, NULL, NULL, NULL);
domxmltext_class_entry = zend_register_internal_class_ex(&ce, domxmlcdata_class_entry, NULL TSRMLS_CC);
INIT_OVERLOADED_CLASS_ENTRY(ce, "DomComment", php_domxmlcomment_class_functions, NULL, NULL, NULL);
domxmlcomment_class_entry = zend_register_internal_class_ex(&ce, domxmlcdata_class_entry, NULL TSRMLS_CC);
INIT_OVERLOADED_CLASS_ENTRY(ce, "DomProcessingInstruction", php_domxmlpi_class_functions, NULL, NULL, NULL);
domxmlpi_class_entry = zend_register_internal_class_ex(&ce, domxmlnode_class_entry, NULL TSRMLS_CC);
INIT_OVERLOADED_CLASS_ENTRY(ce, "DomNotation", php_domxmlnotation_class_functions, NULL, NULL, NULL);
domxmlnotation_class_entry = zend_register_internal_class_ex(&ce, domxmlnode_class_entry, NULL TSRMLS_CC);
INIT_OVERLOADED_CLASS_ENTRY(ce, "DomEntity", php_domxmlentity_class_functions, NULL, NULL, NULL);
domxmlentity_class_entry = zend_register_internal_class_ex(&ce, domxmlnode_class_entry, NULL TSRMLS_CC);
INIT_OVERLOADED_CLASS_ENTRY(ce, "DomEntityReference", php_domxmlentityref_class_functions, NULL, NULL, NULL);
domxmlentityref_class_entry = zend_register_internal_class_ex(&ce, domxmlnode_class_entry, NULL TSRMLS_CC);
INIT_OVERLOADED_CLASS_ENTRY(ce, "DomNamespace", php_domxmlns_class_functions, NULL, NULL, NULL);
domxmlns_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
#if defined(LIBXML_XPATH_ENABLED)
INIT_OVERLOADED_CLASS_ENTRY(ce, "XPathContext", php_xpathctx_class_functions, NULL, NULL, NULL);
xpathctx_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
INIT_OVERLOADED_CLASS_ENTRY(ce, "XPathObject", php_xpathobject_class_functions, NULL, NULL, NULL);
xpathobject_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
#endif
#if HAVE_DOMXSLT
INIT_OVERLOADED_CLASS_ENTRY(ce, "XsltStylesheet", php_domxsltstylesheet_class_functions, NULL, NULL, NULL);
domxsltstylesheet_class_entry = zend_register_internal_class_ex(&ce, NULL, NULL TSRMLS_CC);
#endif
REGISTER_LONG_CONSTANT("XML_ELEMENT_NODE", XML_ELEMENT_NODE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_NODE", XML_ATTRIBUTE_NODE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_TEXT_NODE", XML_TEXT_NODE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_CDATA_SECTION_NODE", XML_CDATA_SECTION_NODE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_ENTITY_REF_NODE", XML_ENTITY_REF_NODE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_ENTITY_NODE", XML_ENTITY_NODE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_PI_NODE", XML_PI_NODE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_COMMENT_NODE", XML_COMMENT_NODE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_DOCUMENT_NODE", XML_DOCUMENT_NODE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_DOCUMENT_TYPE_NODE", XML_DOCUMENT_TYPE_NODE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_DOCUMENT_FRAG_NODE", XML_DOCUMENT_FRAG_NODE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_NOTATION_NODE", XML_NOTATION_NODE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_HTML_DOCUMENT_NODE", XML_HTML_DOCUMENT_NODE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_DTD_NODE", XML_DTD_NODE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_ELEMENT_DECL_NODE", XML_ELEMENT_DECL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_DECL_NODE", XML_ATTRIBUTE_DECL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_ENTITY_DECL_NODE", XML_ENTITY_DECL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_NAMESPACE_DECL_NODE", XML_NAMESPACE_DECL, CONST_CS | CONST_PERSISTENT);
#ifdef XML_GLOBAL_NAMESPACE
REGISTER_LONG_CONSTANT("XML_GLOBAL_NAMESPACE", XML_GLOBAL_NAMESPACE, CONST_CS | CONST_PERSISTENT);
#endif
REGISTER_LONG_CONSTANT("XML_LOCAL_NAMESPACE", XML_LOCAL_NAMESPACE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_CDATA", XML_ATTRIBUTE_CDATA, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_ID", XML_ATTRIBUTE_ID, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_IDREF", XML_ATTRIBUTE_IDREF, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_IDREFS", XML_ATTRIBUTE_IDREFS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_ENTITY", XML_ATTRIBUTE_ENTITIES, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_NMTOKEN", XML_ATTRIBUTE_NMTOKEN, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_NMTOKENS", XML_ATTRIBUTE_NMTOKENS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_ENUMERATION", XML_ATTRIBUTE_ENUMERATION, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XML_ATTRIBUTE_NOTATION", XML_ATTRIBUTE_NOTATION, CONST_CS | CONST_PERSISTENT);
#if defined(LIBXML_XPATH_ENABLED)
REGISTER_LONG_CONSTANT("XPATH_UNDEFINED", XPATH_UNDEFINED, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XPATH_NODESET", XPATH_NODESET, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XPATH_BOOLEAN", XPATH_BOOLEAN, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XPATH_NUMBER", XPATH_NUMBER, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XPATH_STRING", XPATH_STRING, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XPATH_POINT", XPATH_POINT, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XPATH_RANGE", XPATH_RANGE, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XPATH_LOCATIONSET", XPATH_LOCATIONSET, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("XPATH_USERS", XPATH_USERS, CONST_CS | CONST_PERSISTENT);
#endif
xmlSetGenericErrorFunc(xmlGenericErrorContext, (xmlGenericErrorFunc)domxml_error);
#if HAVE_DOMXSLT
xsltSetGenericErrorFunc(xsltGenericErrorContext, (xmlGenericErrorFunc)domxml_error);
#if HAVE_DOMEXSLT
exsltRegisterAll();
#endif
#endif
return SUCCESS;
}
/* {{{ proto int domxml_test(int id)
Unity function for testing */
PHP_FUNCTION(domxml_test)
{
zval *id;
if ((ZEND_NUM_ARGS() != 1) || getParameters(ht, 1, &id) == FAILURE)
WRONG_PARAM_COUNT;
convert_to_long(id);
RETURN_LONG(Z_LVAL_P(id));
}
/* }}} */
PHP_MINFO_FUNCTION(domxml)
{
/* don't know why that line was commented out in the previous version, so i left it (cmv) */
php_info_print_table_start();
php_info_print_table_row(2, "DOM/XML", "enabled");
php_info_print_table_row(2, "libxml Version", LIBXML_DOTTED_VERSION);
#if defined(LIBXML_HTML_ENABLED)
php_info_print_table_row(2, "HTML Support", "enabled");
#endif
#if defined(LIBXML_XPATH_ENABLED)
php_info_print_table_row(2, "XPath Support", "enabled");
#endif
#if defined(LIBXML_XPTR_ENABLED)
php_info_print_table_row(2, "XPointer Support", "enabled");
#endif
#if HAVE_DOMXSLT
php_info_print_table_row(2, "DOM/XSLT", "enabled");
php_info_print_table_row(2, "libxslt Version", LIBXSLT_DOTTED_VERSION);
#if HAVE_DOMEXSLT
php_info_print_table_row(2, "DOM/EXSLT", "enabled");
php_info_print_table_row(2, "libexslt Version", LIBEXSLT_DOTTED_VERSION);
#endif
#endif
php_info_print_table_end();
}
/* {{{ Methods of Class DomAttribute */
/* {{{ proto array domxml_attr_name(void)
Returns list of attribute names */
PHP_FUNCTION(domxml_attr_name)
{
zval *id;
xmlAttrPtr attrp;
DOMXML_GET_THIS_OBJ(attrp, id,le_domxmlattrp);
DOMXML_NO_ARGS();
RETURN_STRING((char *) (attrp->name), 1);
}
/* }}} */
/* {{{ proto array domxml_attr_value(void)
Returns list of attribute names */
PHP_FUNCTION(domxml_attr_value)
{
zval *id;
xmlAttrPtr attrp;
DOMXML_GET_THIS_OBJ(attrp, id, le_domxmlattrp);
DOMXML_NO_ARGS();
RETURN_STRING((char *) xmlNodeGetContent((xmlNodePtr) attrp), 1);
}
/* }}} */
/* {{{ proto array domxml_attr_specified(void)
Returns list of attribute names */
PHP_FUNCTION(domxml_attr_specified)
{
zval *id;
xmlAttrPtr attrp;
DOMXML_NOT_IMPLEMENTED();
id = getThis();
attrp = php_dom_get_object(id, le_domxmlattrp, 0 TSRMLS_CC);
RETURN_TRUE;
}
/* }}} */
/* End of Methods DomAttr }}} */
/* {{{ Methods of Class DomProcessingInstruction */
/* {{{ proto array domxml_pi_target(void)
Returns target of pi */
PHP_FUNCTION(domxml_pi_target)
{
zval *id;
xmlNodePtr nodep;
DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlpip);
DOMXML_NO_ARGS();
RETURN_STRING((char *) nodep->name, 1);
}
/* }}} */
/* {{{ proto array domxml_pi_data(void)
Returns data of pi */
PHP_FUNCTION(domxml_pi_data)
{
zval *id;
xmlNodePtr nodep;
DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlpip);
DOMXML_NO_ARGS();
RETURN_STRING(xmlNodeGetContent(nodep), 1);
}
/* }}} */
/* End of Methods of DomProcessingInstruction }}} */
/* {{{ Methods of Class DomCData */
/* {{{ proto array domxml_cdata_length(void)
Returns list of attribute names */
PHP_FUNCTION(domxml_cdata_length)
{
zval *id;
xmlNodePtr nodep;
DOMXML_NOT_IMPLEMENTED();
id = getThis();
nodep = php_dom_get_object(id, le_domxmlcdatap, 0 TSRMLS_CC);
RETURN_LONG(1);
}
/* }}} */
/* End of Methods DomCDdata }}} */
/* {{{ Methods of Class DomNode */
/* {{{ proto object domxml_node(string name)
Creates node */
PHP_FUNCTION(domxml_node)
{
zval *rv;
xmlNode *node;
int ret, name_len;
char *name;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
return;
}
node = xmlNewNode(NULL, name);
if (!node) {
RETURN_FALSE;
}
DOMXML_RET_OBJ(rv, node, &ret);
}
/* }}} */
/* {{{ proto object domxml_node_name(void)
Returns name of node */
PHP_FUNCTION(domxml_node_name)
{
zval *id;
xmlNode *n;
const char *str = NULL;
DOMXML_GET_THIS_OBJ(n, id, le_domxmlnodep);
DOMXML_NO_ARGS();
switch (Z_TYPE_P(n)) {
case XML_ELEMENT_NODE:
str = n->name;
break;
case XML_TEXT_NODE:
str = "#text";
break;
case XML_CDATA_SECTION_NODE:
str = "#cdata-section";
break;
case XML_ENTITY_REF_NODE:
str = n->name;
break;
case XML_ENTITY_NODE:
str = NULL;
break;
case XML_PI_NODE:
str = n->name;
break;
case XML_COMMENT_NODE:
str = "#comment";
break;
case XML_DOCUMENT_FRAG_NODE:
str = "#document-fragment";
break;
default:
str = NULL;
break;
}
if(str != NULL) {
RETURN_STRING((char *) str, 1);
} else {
RETURN_EMPTY_STRING();
}
}
/* }}} */
/* {{{ proto object domxml_node_value(void)
Returns name of value */
PHP_FUNCTION(domxml_node_value)
{
zval *id;
xmlNode *n;
char *str = NULL;
DOMXML_GET_THIS_OBJ(n, id, le_domxmlnodep);
DOMXML_NO_ARGS();
switch (Z_TYPE_P(n)) {
case XML_TEXT_NODE:
case XML_COMMENT_NODE:
case XML_CDATA_SECTION_NODE:
case XML_PI_NODE:
str = n->content;
break;
default:
str = NULL;
break;
}
if(str != NULL) {
RETURN_STRING((char *) str, 1);
} else {
RETURN_EMPTY_STRING();
}
}
/* }}} */
/* {{{ proto bool domxml_is_blank_node(void)
Returns true if node is blank */
PHP_FUNCTION(domxml_is_blank_node)
{
zval *id;
xmlNode *n;
DOMXML_GET_THIS_OBJ(n, id, le_domxmlnodep);
DOMXML_NO_ARGS();
if(xmlIsBlankNode(n)) {
RETURN_TRUE;
} else {
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto int domxml_node_type(void)
Returns the type of the node */
PHP_FUNCTION(domxml_node_type)
{
zval *id;
xmlNode *node;
DOMXML_GET_THIS_OBJ(node, id, le_domxmlnodep);
DOMXML_NO_ARGS();
RETURN_LONG(node->type);
}
/* }}} */
/* {{{ proto bool domxml_clone_node(void)
Clones a node */
PHP_FUNCTION(domxml_clone_node)
{
zval *rv;
zval *id;
xmlNode *n, *node;
int ret, recursive = 0;;
DOMXML_GET_THIS_OBJ(n, id, le_domxmlnodep);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &recursive) == FAILURE) {
return;
}
node = xmlCopyNode(n, recursive);
if (!node) {
RETURN_FALSE;
}
DOMXML_RET_OBJ(rv, node, &ret);
}
/* }}} */
/* {{{ proto object domxml_node_first_child(void)
Returns first child from list of children */
PHP_FUNCTION(domxml_node_first_child)
{
zval *id, *rv;
xmlNode *nodep, *first;
int ret;
DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep);
DOMXML_NO_ARGS();
first = nodep->children;
if (!first) {
RETURN_FALSE;
}
DOMXML_RET_OBJ(rv, first, &ret);
}
/* }}} */
/* {{{ proto object domxml_node_last_child(void)
Returns last child from list of children */
PHP_FUNCTION(domxml_node_last_child)
{
zval *id, *rv;
xmlNode *nodep, *last;
int ret;
DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep);
DOMXML_NO_ARGS();
last = nodep->last;
if (!last) {
RETURN_FALSE;
}
DOMXML_RET_OBJ(rv, last, &ret);
}
/* }}} */
/* {{{ proto object domxml_node_next_sibling(void)
Returns next child from list of children */
PHP_FUNCTION(domxml_node_next_sibling)
{
zval *id, *rv;
xmlNode *nodep, *first;
int ret;
DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep);
DOMXML_NO_ARGS();
first = nodep->next;
if (!first) {
RETURN_FALSE;
}
DOMXML_RET_OBJ(rv, first, &ret);
}
/* }}} */
/* {{{ proto object domxml_node_previous_sibling(void)
Returns previous child from list of children */
PHP_FUNCTION(domxml_node_previous_sibling)
{
zval *id, *rv;
xmlNode *nodep, *first;
int ret;
DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep);
DOMXML_NO_ARGS();
first = nodep->prev;
if (!first) {
RETURN_FALSE;
}
DOMXML_RET_OBJ(rv, first, &ret);
}
/* }}} */
/* {{{ proto object domxml_node_owner_document(void)
Returns document this node belongs to */
PHP_FUNCTION(domxml_node_owner_document)
{
zval *id, *rv;
xmlNode *nodep;
xmlDocPtr docp;
int ret;
DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep);
DOMXML_NO_ARGS();
docp = nodep->doc;
if (!docp) {
RETURN_FALSE;
}
DOMXML_RET_OBJ(rv, (xmlNodePtr) docp, &ret);
}
/* }}} */
/* {{{ proto object domxml_node_has_child_nodes(void)
Returns true if node has children */
PHP_FUNCTION(domxml_node_has_child_nodes)
{
zval *id;
xmlNode *nodep;
DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep);
DOMXML_NO_ARGS();
if (nodep->children) {
RETURN_TRUE;
} else {
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto object domxml_node_has_attributes(void)
Returns true if node has attributes */
PHP_FUNCTION(domxml_node_has_attributes)
{
zval *id;
xmlNode *nodep;
DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep);
DOMXML_NO_ARGS();
if (Z_TYPE_P(nodep) != XML_ELEMENT_NODE)
RETURN_FALSE;
if (nodep->properties) {
RETURN_TRUE;
} else {
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto object domxml_node_prefix(void)
Returns namespace prefix of node */
PHP_FUNCTION(domxml_node_prefix)
{
zval *id;
xmlNode *nodep;
xmlNsPtr ns;
DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep);
DOMXML_NO_ARGS();
ns = nodep->ns;
if (!ns) {
RETURN_EMPTY_STRING();
}
if (ns->prefix) {
RETURN_STRING((char *) (ns->prefix), 1);
} else {
RETURN_EMPTY_STRING();
}
}
/* }}} */
/* {{{ proto object domxml_node_parent(void)
Returns parent of node */
PHP_FUNCTION(domxml_node_parent)
{
zval *id, *rv;
xmlNode *nodep, *last;
int ret;
DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep);
DOMXML_NO_ARGS();
last = nodep->parent;
if (!last) {
RETURN_FALSE;
}
DOMXML_RET_OBJ(rv, last, &ret);
}
/* }}} */
/* {{{ proto array domxml_node_children(void)
Returns list of children nodes */
PHP_FUNCTION(domxml_node_children)
{
zval *id;
xmlNode *nodep, *last;
int ret;
DOMXML_PARAM_NONE(nodep, id, le_domxmlnodep);
/* Even if the nodep is a XML_DOCUMENT_NODE the type is at the
same position.
*/
if ((Z_TYPE_P(nodep) == XML_DOCUMENT_NODE) || (Z_TYPE_P(nodep) == XML_HTML_DOCUMENT_NODE))
last = ((xmlDoc *) nodep)->children;
else
last = nodep->children;
if (!last) {
RETURN_FALSE;
}
if (array_init(return_value) == FAILURE) {
RETURN_FALSE;
}
while (last) {
zval *child;
child = php_domobject_new(last, &ret TSRMLS_CC);
add_next_index_zval(return_value, child);
last = last->next;
}
}
/* }}} */
/* {{{ proto void domxml_node_unlink_node([object node])
Deletes the node */
PHP_FUNCTION(domxml_node_unlink_node)
{
zval *id;
xmlNode *nodep;
DOMXML_PARAM_NONE(nodep, id, le_domxmlnodep);
xmlUnlinkNode(nodep);
/* This causes a Segmentation Fault for some reason. Removing
it allows the user to re-add the node at some other time, in
addition to fixing the segfault. Node will be freed at
shutdown. */
/*xmlFreeNode(nodep);
zval_dtor(id);*/ /* This is not enough because the children won't be deleted */
}
/* }}} */
/* {{{ proto object domxml_node_add_child(object domnode)
Adds existing node to parent node */
PHP_FUNCTION(domxml_node_add_child)
{
zval *id, *rv, *node;
xmlNodePtr child, nodep, new_child;
int ret;
DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &node) == FAILURE) {
return;
}
DOMXML_GET_OBJ(child, node, le_domxmlnodep);
if (child->type == XML_ATTRIBUTE_NODE) {
php_error(E_WARNING, "%s(): can't add attribute node", get_active_function_name(TSRMLS_C));
RETURN_FALSE;
}
if (NULL == (new_child = xmlCopyNode(child, 1))) {
php_error(E_WARNING, "%s(): unable to clone node", get_active_function_name(TSRMLS_C));
RETURN_FALSE;
}
child = xmlAddChild(nodep, new_child);
if (NULL == child) {
php_error(E_WARNING, "%s(): couldn't add child", get_active_function_name(TSRMLS_C));
RETURN_FALSE;
}
DOMXML_RET_OBJ(rv, child, &ret);
}
/* }}} */
/* {{{ proto object domxml_node_replace_node(object domnode)
Replaces one node with another node */
PHP_FUNCTION(domxml_node_replace_node)
{
zval *id, *rv, *node;
xmlNodePtr repnode, nodep, new_repnode;
int ret;
DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &node) == FAILURE) {
return;
}
DOMXML_GET_OBJ(repnode, node, le_domxmlnodep);
if (NULL == (new_repnode = xmlCopyNode(repnode, 1))) {
php_error(E_WARNING, "%s(): unable to clone node", get_active_function_name(TSRMLS_C));
RETURN_FALSE;
}
repnode = xmlReplaceNode(nodep, new_repnode);
DOMXML_RET_OBJ(rv, repnode, &ret);
}
/* }}} */
/* {{{ proto object domxml_node_append_child(object domnode)
Adds node to list of children */
PHP_FUNCTION(domxml_node_append_child)
{
zval *id, *rv, *node;
xmlNodePtr child, nodep, new_child;
int ret;
DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &node) == FAILURE) {
return;
}
DOMXML_GET_OBJ(child, node, le_domxmlnodep);
if (child->type == XML_ATTRIBUTE_NODE) {
php_error(E_WARNING, "%s(): can't append attribute node", get_active_function_name(TSRMLS_C));
RETURN_FALSE;
}
if (NULL == (new_child = xmlCopyNode(child, 1))) {
php_error(E_WARNING, "%s(): unable to clone node", get_active_function_name(TSRMLS_C));
RETURN_FALSE;
}
// FIXME reverted xmlAddChildList; crashes
child = xmlAddSibling(nodep, new_child);
if (NULL == child) {
php_error(E_WARNING, "%s(): couldn't append node", get_active_function_name(TSRMLS_C));
RETURN_FALSE;
}
DOMXML_RET_OBJ(rv, child, &ret);
}
/* }}} */
/* {{{ proto object domxml_node_insert_before(object newnode, object refnode)
Adds node in list of nodes before given node */
PHP_FUNCTION(domxml_node_insert_before)
{
zval *id, *rv, *node, *ref;
xmlNodePtr child, nodep, refp;
int ret;
DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "oo", &node, &ref) == FAILURE) {
return;
}
DOMXML_GET_OBJ(child, node, le_domxmlnodep);
DOMXML_GET_OBJ(refp, ref, le_domxmlnodep);
child = xmlAddPrevSibling(refp, child);
if (NULL == child) {
php_error(E_WARNING, "%s(): couldn't add newnode as the previous sibling of refnode", get_active_function_name(TSRMLS_C));
RETURN_FALSE;
}
DOMXML_RET_OBJ(rv, child, &ret);
}
/* }}} */
/* {{{ proto bool domxml_node_set_name(string name)
Sets name of a node */
PHP_FUNCTION(domxml_node_set_name)
{
zval *id;
xmlNode *nodep;
int name_len;
char *name;
DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
return;
}
xmlNodeSetName(nodep, name);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto array domxml_node_attributes(void)
Returns list of attributes of node */
PHP_FUNCTION(domxml_node_attributes)
{
zval *id, *attrs;
xmlNode *nodep;
#ifdef oldstyle_for_libxml_1_8_7
xmlAttr *attr;
#endif
DOMXML_PARAM_NONE(nodep, id, le_domxmlnodep);
if (node_attributes(&attrs, nodep TSRMLS_CC) < 0)
RETURN_FALSE;
*return_value = *attrs;
FREE_ZVAL(attrs);
#ifdef oldstyle_for_libxml_1_8_7
attr = nodep->properties;
if (!attr) {
RETURN_FALSE;
}
if (array_init(return_value) == FAILURE) {
RETURN_FALSE;
}
while (attr) {
add_assoc_string(return_value, (char *) attr->name, xmlNodeGetContent(attr), 1);
attr = attr->next;
}
#endif
}
/* }}} */
/* {{{ proto object domxml_node_new_child(string name, string content)
Adds child node to parent node */
PHP_FUNCTION(domxml_node_new_child)
{
zval *id, *rv;
xmlNodePtr child, nodep;
int ret, name_len, content_len;
char *name, *content = NULL;
DOMXML_PARAM_FOUR(nodep, id, le_domxmlnodep, "s|s", &name, &name_len, &content, &content_len);
child = xmlNewChild(nodep, NULL, name, content);
if (!child) {
RETURN_FALSE;
}
DOMXML_RET_OBJ(rv, child, &ret);
}
/* }}} */
/* {{{ proto bool domxml_node_set_content(string content)
Sets content of a node */
PHP_FUNCTION(domxml_node_set_content)
{
zval *id;
xmlNode *nodep;
int content_len;
char *content;
DOMXML_PARAM_TWO(nodep, id, le_domxmlnodep, "s", &content, &content_len);
// FIXME: another gotcha. If node has children, calling
// xmlNodeSetContent will remove the children -> we loose the zval's
// To prevent crash, append content if children are set
if (nodep->children) {
xmlNodeAddContentLen(nodep, content, content_len);
} else {
xmlNodeSetContentLen(nodep, content, content_len);
}
/* FIXME: Actually the property 'content' of the node has to be updated
as well. Since 'content' should disappear sooner or later and being
replaces by a function 'content()' I skip this for now
*/
RETURN_TRUE;
}
/* }}} */
/* {{{ proto string domxml_node_get_content()
Gets content of a node.
"Read the value of a node, this can be either the text carried directly by
this node if it's a TEXT node or the aggregate string of the values carried by
this node child's (TEXT and ENTITY_REF). Entity references are substituted."
*/
PHP_FUNCTION(domxml_node_get_content)
{
zval *id;
xmlNode *nodep;
xmlChar *mem;
DOMXML_PARAM_NONE(nodep, id, le_domxmlnodep);
mem = xmlNodeGetContent(nodep);
if (!mem) {
RETURN_FALSE;
}
RETURN_STRING(mem,1);
}
/* }}} */
/* End of Methods DomNode }}} */
/* {{{ Methods of Class DomNotation */
/* {{{ proto string domxml_notation_public_id(void)
Returns public id of notation node */
PHP_FUNCTION(domxml_notation_public_id)
{
zval *id;
xmlNotationPtr nodep;
DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnotationp);
DOMXML_NO_ARGS();
RETURN_STRING((char *) (nodep->PublicID), 1);
}
/* }}} */
/* {{{ proto string domxml_notation_system_id(void)
Returns system ID of notation node */
PHP_FUNCTION(domxml_notation_system_id)
{
zval *id;
xmlNotationPtr nodep;
DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnotationp);
DOMXML_NO_ARGS();
RETURN_STRING((char *) (nodep->SystemID), 1);
}
/* }}} */
/* End of Methods DomNotation }}} */
/* {{{ Methods of Class DomElement */
/* {{{ proto object domxml_element(string name)
Constructor of DomElement */
PHP_FUNCTION(domxml_element)
{
zval *rv;
xmlNode *node;
int ret, name_len;
char *name;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
return;
}
node = xmlNewNode(NULL, name);
if (!node) {
RETURN_FALSE;
}
DOMXML_RET_OBJ(rv, node, &ret);
}
/* }}} */
/* {{{ proto string domxml_elem_tagname(void)
Returns tag name of element node */
PHP_FUNCTION(domxml_elem_tagname)
{
zval *id;
xmlNode *nodep;
DOMXML_NO_ARGS();
DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlelementp);
DOMXML_NO_ARGS();
RETURN_STRING((char *) (nodep->name), 1);
}
/* }}} */
/* {{{ proto string domxml_elem_get_attribute(string attrname)
Returns value of given attribute */
PHP_FUNCTION(domxml_elem_get_attribute)
{
zval *id;
xmlNode *nodep;
char *name, *value;
int name_len;
DOMXML_PARAM_TWO(nodep, id, le_domxmlelementp, "s", &name, &name_len);
value = xmlGetProp(nodep, name);
if (!value) {
RETURN_EMPTY_STRING();
} else {
RETURN_STRING(value, 1);
}
}
/* }}} */
/* {{{ proto bool domxml_elem_set_attribute(string attrname, string value)
Sets value of given attribute */
PHP_FUNCTION(domxml_elem_set_attribute)
{
zval *id, *rv;
xmlNode *nodep;
xmlAttr *attr;
int ret, name_len, value_len;
char *name, *value;
DOMXML_PARAM_FOUR(nodep, id, le_domxmlelementp, "ss", &name, &name_len, &value, &value_len);
attr = xmlSetProp(nodep, name, value);
if (!attr) {
php_error(E_WARNING, "%s(): no such attribute '%s'", get_active_function_name(TSRMLS_C), name);
RETURN_FALSE;
}
DOMXML_RET_OBJ(rv, (xmlNodePtr) attr, &ret);
}
/* }}} */
/* {{{ proto string domxml_elem_remove_attribute(string attrname)
Removes given attribute */
PHP_FUNCTION(domxml_elem_remove_attribute)
{
zval *id, *arg1;
xmlNode *nodep;
DOMXML_NOT_IMPLEMENTED();
if ((ZEND_NUM_ARGS() == 1) && getParameters(ht, 1, &arg1) == SUCCESS) {
id = getThis();
nodep = php_dom_get_object(id, le_domxmlelementp, 0 TSRMLS_CC);
} else {
WRONG_PARAM_COUNT;
}
convert_to_string(arg1);
/* FIXME: not implemented */
RETURN_TRUE;
}
/* }}} */
/* {{{ proto string domxml_elem_get_attribute_node(string attrname)
Returns value of given attribute */
PHP_FUNCTION(domxml_elem_get_attribute_node)
{
zval *id, *arg1;
xmlNode *nodep;
DOMXML_NOT_IMPLEMENTED();
if ((ZEND_NUM_ARGS() == 1) && getParameters(ht, 1, &arg1) == SUCCESS) {
id = getThis();
nodep = php_dom_get_object(id, le_domxmlelementp, 0 TSRMLS_CC);
} else {
WRONG_PARAM_COUNT;
}
convert_to_string(arg1);
/* FIXME: not implemented */
RETURN_TRUE;
}
/* }}} */
/* {{{ proto bool domxml_elem_set_attribute_node(int attr)
Sets value of given attribute */
PHP_FUNCTION(domxml_elem_set_attribute_node)
{
zval *id, *arg1;
xmlNode *nodep;
xmlAttr *attrp;
DOMXML_NOT_IMPLEMENTED();
if ((ZEND_NUM_ARGS() == 1) && getParameters(ht, 1, &arg1) == SUCCESS) {
id = getThis();
nodep = php_dom_get_object(id, le_domxmlelementp, 0 TSRMLS_CC);
attrp = php_dom_get_object(arg1, le_domxmlattrp, 0 TSRMLS_CC);
} else {
WRONG_PARAM_COUNT;
}
/* FIXME: not implemented */
RETURN_TRUE;
}
/* }}} */
/* {{{ proto string domxml_elem_get_element_by_tagname(string tagname)
Returns element for given attribute */
PHP_FUNCTION(domxml_elem_get_element_by_tagname)
{
zval *id, *arg1;
xmlNode *nodep;
DOMXML_NOT_IMPLEMENTED();
if ((ZEND_NUM_ARGS() == 1) && getParameters(ht, 1, &arg1) == SUCCESS) {
id = getThis();
nodep = php_dom_get_object(id, le_domxmlelementp, 0 TSRMLS_CC);
} else {
WRONG_PARAM_COUNT;
}
convert_to_string(arg1);
/* FIXME: not implemented */
}
/* }}} */
/* End of Methods DomElement }}} */
/* {{{ Methods of Class DomDocumentType */
/* {{{ proto array domxml_doctype_name(void)
Returns name of DocumentType */
PHP_FUNCTION(domxml_doctype_name)
{
zval *id;
xmlNodePtr attrp;
DOMXML_NO_ARGS();
DOMXML_GET_THIS_OBJ(attrp, id, le_domxmldoctypep);
RETURN_STRING((char *) (attrp->name), 1);
}
/* }}} */
/* End of Methods DomElementType }}} */
/* {{{ Methods of Class DomDocument */
/* {{{ proto object domxml_doc_doctype(void)
Returns DomDocumentType */
PHP_FUNCTION(domxml_doc_doctype)
{
zval *id, *rv;
xmlDtdPtr dtd;
xmlDocPtr docp;
int ret;
DOMXML_GET_THIS_OBJ(docp, id, le_domxmldocp);
DOMXML_NO_ARGS();
dtd = xmlGetIntSubset(docp);
DOMXML_RET_OBJ(rv, (xmlNodePtr) dtd, &ret);
}
/* }}} */
/* {{{ proto object domxml_doc_implementation(void)
Returns DomeDOMImplementation */
PHP_FUNCTION(domxml_doc_implementation)
{
/* zval *id;
xmlDocPtr docp;*/
DOMXML_NOT_IMPLEMENTED();
/*
DOMXML_GET_THIS_OBJ(docp, id, le_domxmldocp);
rv = php_domobject_new(node, &ret TSRMLS_CC);
SEPARATE_ZVAL(&rv);
*return_value = *rv;
*/
}
/* }}} */
/* {{{ proto array domxml_doc_document_element(void)
Returns root node of document */
PHP_FUNCTION(domxml_doc_document_element)
{
zval *id;
xmlDoc *docp;
xmlNode *node;
int ret;
id = getThis();
if (!id) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &id) == FAILURE) {
return;
}
}
DOMXML_GET_OBJ(docp, id, le_domxmldocp);
node = docp->children;
if (!node) {
RETURN_FALSE;
}
while (node) {
if (Z_TYPE_P(node) == XML_ELEMENT_NODE) {
zval *rv;
DOMXML_RET_OBJ(rv, node, &ret);
return;
}
node = node->next;
}
}
/* }}} */
/* {{{ proto object domxml_doc_create_element(string name)
Creates new element node */
PHP_FUNCTION(domxml_doc_create_element)
{
zval *id, *rv;
xmlNode *node;
xmlDocPtr docp;
int ret, name_len;
char *name;
DOMXML_GET_THIS_OBJ(docp, id, le_domxmldocp);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
return;
}
node = xmlNewNode(NULL, name);
if (!node) {
RETURN_FALSE;
}
node->doc = docp;
DOMXML_RET_OBJ(rv, node, &ret);
}
/* }}} */
/* {{{ proto object domxml_doc_create_text_node(string name)
Creates new text node */
PHP_FUNCTION(domxml_doc_create_text_node)
{
zval *id, *rv;
xmlNode *node;
xmlDocPtr docp;
int ret, content_len;
char *content;
DOMXML_GET_THIS_OBJ(docp, id, le_domxmldocp);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &content, &content_len) == FAILURE) {
return;
}
node = xmlNewTextLen(content, content_len);
if (!node) {
RETURN_FALSE;
}
node->doc = docp;
DOMXML_RET_OBJ(rv, node, &ret);
}
/* }}} */
/* {{{ proto object domxml_doc_create_comment(string name)
Creates new comment node */
PHP_FUNCTION(domxml_doc_create_comment)
{
zval *id, *rv;
xmlNode *node;
xmlDocPtr docp;
int ret, content_len;
char *content;
DOMXML_GET_THIS_OBJ(docp, id, le_domxmldocp);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &content, &content_len) == FAILURE) {
return;
}
node = xmlNewComment(content);
if (!node) {
RETURN_FALSE;
}
node->doc = docp;
DOMXML_RET_OBJ(rv, node, &ret);
}
/* }}} */
/* {{{ proto object domxml_doc_create_attribute(string name)
Creates new attribute node */
PHP_FUNCTION(domxml_doc_create_attribute)
{
zval *id, *rv;
xmlAttrPtr node;
xmlDocPtr docp;
int ret, name_len, value_len;
char *name, *value;
DOMXML_GET_THIS_OBJ(docp, id, le_domxmldocp);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &value, &value_len) == FAILURE) {
return;
}
node = xmlNewProp(NULL, name, value);
if (!node) {
RETURN_FALSE;
}
node->doc = docp;
DOMXML_RET_OBJ(rv, (xmlNodePtr) node, &ret);
}
/* }}} */
/* {{{ proto object domxml_doc_create_cdata_section(string name)
Creates new cdata node */
PHP_FUNCTION(domxml_doc_create_cdata_section)
{
zval *id, *rv;
xmlNode *node;
xmlDocPtr docp;
int ret, content_len;
char *content;
DOMXML_GET_THIS_OBJ(docp, id, le_domxmldocp);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &content, &content_len) == FAILURE) {
return;
}
node = xmlNewCDataBlock(docp, content, content_len);
if (!node) {
RETURN_FALSE;
}
node->doc = docp;
DOMXML_RET_OBJ(rv, node, &ret);
}
/* }}} */
/* {{{ proto object domxml_doc_create_entity_reference(string name)
Creates new cdata node */
PHP_FUNCTION(domxml_doc_create_entity_reference)
{
zval *id, *rv;
xmlNode *node;
xmlDocPtr docp;
int ret, name_len;
char *name;
DOMXML_GET_THIS_OBJ(docp, id, le_domxmldocp);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
return;
}
node = xmlNewReference(docp, name);
if (!node) {
RETURN_FALSE;
}
node->doc = docp;
DOMXML_RET_OBJ(rv, node, &ret);
}
/* }}} */
/* {{{ proto object domxml_doc_create_processing_instruction(string name)
Creates new processing_instruction node */
PHP_FUNCTION(domxml_doc_create_processing_instruction)
{
zval *id, *rv;
xmlNode *node;
xmlDocPtr docp;
int ret, name_len, content_len;
char *name, *content;
DOMXML_GET_THIS_OBJ(docp, id, le_domxmldocp);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &content, &content_len) == FAILURE) {
return;
}
node = xmlNewPI(name, content);
if (!node) {
RETURN_FALSE;
}
node->doc = docp;
DOMXML_RET_OBJ(rv, node, &ret);
}
/* }}} */
/* {{{ proto object domxml_doc_imported_node(object node, bool recursive)
Creates new element node */
PHP_FUNCTION(domxml_doc_imported_node)
{
zval *arg1, *id, *rv;
xmlNodePtr node, srcnode;
xmlDocPtr docp;
int ret, recursive = 0;
DOMXML_GET_THIS_OBJ(docp, id, le_domxmldocp);
// FIXME: which object type to expect?
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|l", &arg1, &recursive) == FAILURE) {
return;
}
DOMXML_GET_OBJ(srcnode, arg1, le_domxmlnodep);
node = xmlCopyNode(srcnode, recursive);
if (!node) {
RETURN_FALSE;
}
node->doc = docp; /* Not enough because other nodes in the tree are not set */
DOMXML_RET_OBJ(rv, node, &ret);
}
/* }}} */
/* {{{ proto object domxml_dtd(void)
Returns DTD of document */
PHP_FUNCTION(domxml_intdtd)
{
zval *id, *rv;
xmlDoc *docp;
xmlDtd *dtd;
int ret;
DOMXML_GET_THIS_OBJ(docp, id, le_domxmldocp);
dtd = xmlGetIntSubset(docp);
if (!dtd) {
RETURN_FALSE;
}
DOMXML_RET_OBJ(rv, (xmlNodePtr) dtd, &ret);
}
/* }}} */
/* {{{ proto string domxml_dump_mem([object doc_handle])
Dumps document into string */
PHP_FUNCTION(domxml_dump_mem)
{
zval *id;
xmlDoc *docp;
xmlChar *mem;
int size;
DOMXML_PARAM_NONE(docp, id, le_domxmldocp);
xmlDocDumpMemory(docp, &mem, &size);
if (!size) {
RETURN_FALSE;
}
RETURN_STRINGL(mem, size, 1);
}
/* }}} */
/* {{{ proto int domxml_dump_mem_file([object doc_handle],filename,compressmode)
Dumps document into file and uses compression if specified
Returns false on error, otherwise the length of the xml-document (uncompressed)
*/
PHP_FUNCTION(domxml_dump_mem_file)
{
zval *id;
xmlDoc *docp;
int file_len, bytes;
int compressmode = 0;
char *file;
DOMXML_PARAM_THREE(docp, id, le_domxmldocp, "s|l", &file, &file_len, &compressmode);
xmlSetCompressMode (compressmode);
bytes = xmlSaveFile(file,docp);
if (bytes == -1)
{
RETURN_FALSE;
}
RETURN_LONG(bytes);
}
/* }}} */
/* {{{ proto string domxml_dump_node([object doc_handle],object node_handle[,int format[,int level]])
Dumps node into string */
PHP_FUNCTION(domxml_dump_node)
{
zval *id, *nodep;
xmlDocPtr docp;
xmlNodePtr elementp;
xmlChar *mem ;
xmlBufferPtr buf;
int level = 0;
int format = 0;
DOMXML_PARAM_THREE(docp, id, le_domxmldocp,"o|ll",&nodep,&format,&level);
DOMXML_GET_OBJ(elementp, nodep, le_domxmlnodep);
if (Z_TYPE_P(elementp) == XML_DOCUMENT_NODE || Z_TYPE_P(elementp) == XML_HTML_DOCUMENT_NODE ) {
php_error(E_WARNING, "%s(): cannot dump element with a document node", get_active_function_name(TSRMLS_C));
RETURN_FALSE;
}
buf = xmlBufferCreate();
if (!buf)
{
php_error(E_WARNING, "%s(): could fetch buffer", get_active_function_name(TSRMLS_C));
RETURN_FALSE;
}
xmlNodeDump(buf, docp, elementp,level,format);
mem = (xmlChar*) xmlBufferContent(buf);
if (!mem) {
xmlBufferFree(buf);
RETURN_FALSE;
}
RETVAL_STRING(mem, 1);
xmlBufferFree(buf);
}
/* }}} */
/* {{{ proto object xmldoc(string xmldoc [, bool from_file])
Creates DOM object of XML document */
PHP_FUNCTION(xmldoc)
{
zval *rv;
xmlDoc *docp;
int ret;
char *buffer;
int buffer_len;
zend_bool from_file = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &buffer, &buffer_len, &from_file) == FAILURE) {
return;
}
if (from_file) {
docp = xmlParseFile(buffer);
} else {
docp = xmlParseDoc(buffer);
}
if (!docp)
RETURN_FALSE;
DOMXML_RET_OBJ(rv, (xmlNodePtr) docp, &ret);
}
/* }}} */
/* {{{ proto object xmldocfile(string filename)
Creates DOM object of XML document in file */
PHP_FUNCTION(xmldocfile)
{
zval *rv;
xmlDoc *docp;
int ret, file_len;
char *file;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &file_len) == FAILURE) {
return;
}
docp = xmlParseFile(file);
if (!docp) {
RETURN_FALSE;
}
DOMXML_RET_OBJ(rv, (xmlNodePtr) docp, &ret);
add_property_resource(return_value, "doc", ret);
if (docp->name)
add_property_stringl(return_value, "name", (char *) docp->name, strlen(docp->name), 1);
if (docp->URL)
add_property_stringl(return_value, "url", (char *) docp->URL, strlen(docp->URL), 1);
add_property_stringl(return_value, "version", (char *) docp->version, strlen(docp->version), 1);
if (docp->encoding)
add_property_stringl(return_value, "encoding", (char *) docp->encoding, strlen(docp->encoding), 1);
add_property_long(return_value, "standalone", docp->standalone);
add_property_long(return_value, "type", Z_TYPE_P(docp));
add_property_long(return_value, "compression", docp->compression);
add_property_long(return_value, "charset", docp->charset);
zend_list_addref(ret);
}
/* }}} */
#if defined(LIBXML_HTML_ENABLED)
/* {{{ proto string domxml_html_dump_mem([int doc_handle])
Dumps document into string as HTML */
PHP_FUNCTION(domxml_html_dump_mem)
{
zval *id;
xmlDoc *docp;
xmlChar *mem;
int size;
DOMXML_PARAM_NONE(docp, id, le_domxmldocp);
htmlDocDumpMemory(docp, &mem, &size);
if (!size) {
RETURN_FALSE;
}
RETURN_STRINGL(mem, size, 1);
}
/* }}} */
/* {{{ proto object html_doc(string html_doc [, bool from_file])
Creates DOM object of HTML document */
PHP_FUNCTION(html_doc)
{
zval *rv;
xmlDoc *docp;
int ret;
char *buffer;
int buffer_len;
zend_bool from_file = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &buffer, &buffer_len, &from_file) == FAILURE) {
return;
}
if (from_file) {
docp = htmlParseFile(buffer, NULL);
} else {
docp = htmlParseDoc(buffer, NULL);
}
if (!docp)
RETURN_FALSE;
DOMXML_RET_OBJ(rv, (xmlNodePtr) docp, &ret);
}
/* }}} */
/* {{{ proto object html_doc_file(string filename)
Creates DOM object of HTML document in file */
PHP_FUNCTION(html_doc_file)
{
zval *rv;
xmlDoc *docp;
int ret, file_len;
char *file;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &file_len) == FAILURE) {
return;
}
docp = htmlParseFile(file, NULL);
if (!docp) {
RETURN_FALSE;
}
DOMXML_RET_OBJ(rv, (xmlNodePtr) docp, &ret);
add_property_resource(return_value, "doc", ret);
if (docp->name)
add_property_stringl(return_value, "name", (char *) docp->name, strlen(docp->name), 1);
if (docp->URL)
add_property_stringl(return_value, "url", (char *) docp->URL, strlen(docp->URL), 1);
if (docp->version)
add_property_stringl(return_value, "version", (char *) docp->version, strlen(docp->version), 1);
/* add_property_stringl(return_value, "version", (char *) docp->version, strlen(docp->version), 1);*/
if (docp->encoding)
add_property_stringl(return_value, "encoding", (char *) docp->encoding, strlen(docp->encoding), 1);
add_property_long(return_value, "standalone", docp->standalone);
add_property_long(return_value, "type", Z_TYPE_P(docp));
add_property_long(return_value, "compression", docp->compression);
add_property_long(return_value, "charset", docp->charset);
zend_list_addref(ret);
}
/* }}} */
#endif /* defined(LIBXML_HTML_ENABLED) */
/* {{{ proto bool domxml_substitute_entities_default(bool enable)
Set and return the previous value for default entity support */
PHP_FUNCTION(domxml_substitute_entities_default)
{
zend_bool enable;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &enable) == FAILURE) {
return;
}
RETURN_BOOL(xmlSubstituteEntitiesDefault(enable));
}
/* }}} */
/* {{{ proto bool domxml_node_text_concat(string content)
Add string tocontent of a node */
PHP_FUNCTION(domxml_node_text_concat)
{
zval *id;
xmlNode *nodep;
char *content;
int content_len;
DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &content, &content_len) == FAILURE) {
return;
}
if (content_len)
xmlTextConcat(nodep, content, content_len);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto object domxml_add_root(string name)
Adds root node to document */
PHP_FUNCTION(domxml_add_root)
{
zval *id, *rv;
xmlDoc *docp;
xmlNode *nodep;
int ret, name_len;
char *name;
DOMXML_PARAM_TWO(docp, id, le_domxmldocp, "s", &name, &name_len);
nodep = xmlNewDocNode(docp, NULL, name, NULL);
if (!nodep) {
RETURN_FALSE;
}
xmlDocSetRootElement(docp, nodep);
DOMXML_RET_OBJ(rv, nodep, &ret);
}
/* }}} */
/* {{{ proto object domxml_new_xmldoc(string version)
Creates new xmldoc */
PHP_FUNCTION(domxml_new_xmldoc)
{
zval *rv;
xmlDoc *docp;
int ret, buf_len;
char *buf;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
return;
}
docp = xmlNewDoc(buf);
if (!docp) {
RETURN_FALSE;
}
DOMXML_RET_OBJ(rv, (xmlNodePtr) docp, &ret);
}
/* }}} */
#ifdef newcode
/* {{{ proto int node_namespace([int node])
Returns list of namespaces */
static int node_namespace(zval **attributes, xmlNode *nodep TSRMLS_DC)
{
xmlNs *ns;
/* Get the children of the current node */
ns = nodep->ns;
if (!ns) {
return -1;
}
/* create an php array for the children */
MAKE_STD_ZVAL(*attributes);
if (array_init(*attributes) == FAILURE) {
return -1;
}
while (ns) {
zval *pattr;
int ret;
pattr = php_domobject_new((xmlNodePtr) ns, &ret TSRMLS_CC);
SEPARATE_ZVAL(&pattr);
/* if(!ret) { */
if (ns->href)
add_property_stringl(pattr, "href", (char *) ns->href, strlen(ns->href), 1);
if (ns->prefix)
add_property_stringl(pattr, "prefix", (char *) ns->prefix, strlen(ns->prefix), 1);
add_property_long(pattr, "type", Z_TYPE_P(ns));
/* } */
zend_hash_next_index_insert(Z_ARRVAL_PP(attributes), &pattr, sizeof(zval *), NULL);
ns = ns->next;
}
return 0;
}
/* }}} */
#endif
/* We don't have a type zval. **attributes is also very unusual. */
/* {{{ proto int node_attributes(zval **attributes, int node)
Returns list of children nodes */
static int node_attributes(zval **attributes, xmlNode *nodep TSRMLS_DC)
{
xmlAttr *attr;
int count = 0;
/* Get the children of the current node */
if (Z_TYPE_P(nodep) != XML_ELEMENT_NODE)
return -1;
attr = nodep->properties;
if (!attr)
return -1;
/* create an php array for the children */
MAKE_STD_ZVAL(*attributes);
array_init(*attributes);
while (attr) {
zval *pattr;
int ret;
pattr = php_domobject_new((xmlNodePtr) attr, &ret TSRMLS_CC);
/** XXX FIXME XXX */
/* if(0 <= (n = node_children(&children, attr->children TSRMLS_CC))) {
zend_hash_update(Z_OBJPROP_P(value), "children", sizeof("children"), (void *) &children, sizeof(zval *), NULL);
}
*/ add_property_string(pattr, "name", (char *) (attr->name), 1);
add_property_string(pattr, "value", xmlNodeGetContent((xmlNodePtr) attr), 1);
zend_hash_next_index_insert(Z_ARRVAL_PP(attributes), &pattr, sizeof(zval *), NULL);
attr = attr->next;
count++;
}
return count;
}
/* }}} */
/* {{{ proto int node_children([int node])
Returns list of children nodes */
static int node_children(zval **children, xmlNode *nodep TSRMLS_DC)
{
zval *mchildren, *attributes;
/* zval *namespace; */
xmlNode *last;
int count = 0;
/* Get the children of the current node */
last = nodep;
if (!last) {
return -1;
}
/* create an php array for the children */
MAKE_STD_ZVAL(*children);
array_init(*children);
while (last) {
zval *child;
int ret;
if (NULL != (child = php_domobject_new(last, &ret TSRMLS_CC))) {
zend_hash_next_index_insert(Z_ARRVAL_PP(children), &child, sizeof(zval *), NULL);
/* Get the namespace of the current node and add it as a property */
/* XXX FIXME XXX */
/*
if(!node_namespace(&namespace, last))
zend_hash_update(Z_OBJPROP_P(child), "namespace", sizeof("namespace"), (void *) &namespace, sizeof(zval *), NULL);
*/
/* Get the attributes of the current node and add it as a property */
if (node_attributes(&attributes, last TSRMLS_CC) >= 0)
zend_hash_update(Z_OBJPROP_P(child), "attributes", sizeof("attributes"), (void *) &attributes, sizeof(zval *), NULL);
/* Get recursively the children of the current node and add it as a property */
if (node_children(&mchildren, last->children TSRMLS_CC) >= 0)
zend_hash_update(Z_OBJPROP_P(child), "children", sizeof("children"), (void *) &mchildren, sizeof(zval *), NULL);
count++;
}
last = last->next;
}
return count;
}
/* }}} */
/* {{{ proto object xmltree(string xmltree)
Creates a tree of PHP objects from an XML document */
PHP_FUNCTION(xmltree)
{
zval *children, *rv;
xmlDoc *docp;
xmlNode *root;
int ret, buf_len;
char *buf;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
return;
}
/* Create a new xml document */
docp = xmlParseDoc(buf);
if (!docp) {
RETURN_FALSE;
}
/* get the root and add as a property to the document */
root = docp->children;
if (!root) {
xmlFreeDoc(docp);
RETURN_FALSE;
}
DOMXML_RET_OBJ(rv, (xmlNodePtr) docp, &ret);
/* The root itself maybe an array. Though you may not have two Elements
as root, you may have a comment, pi and and element as root.
Thanks to Paul DuBois for pointing me at this.
*/
if (node_children(&children, root TSRMLS_CC) >= 0) {
zend_hash_update(Z_OBJPROP_P(return_value), "children",sizeof("children"), (void *) &children, sizeof(zval *), NULL);
}
/* xmlFreeDoc(docp); */
}
/* }}} */
#if defined(LIBXML_XPATH_ENABLED)
/* {{{ proto bool xpath_init(void)
Initializing XPath environment */
PHP_FUNCTION(xpath_init)
{
if (ZEND_NUM_ARGS() != 0) {
WRONG_PARAM_COUNT;
}
xmlXPathInit();
RETURN_TRUE;
}
/* }}} */
/* {{{ php_xpathptr_new_context()
*/
static void php_xpathptr_new_context(INTERNAL_FUNCTION_PARAMETERS, int mode)
{
zval *id, *rv;
xmlXPathContextPtr ctx;
xmlDocPtr docp;
int ret;
DOMXML_PARAM_NONE(docp, id, le_domxmldocp);
#if defined(LIBXML_XPTR_ENABLED)
if (mode == PHP_XPTR)
ctx = xmlXPtrNewContext(docp, NULL, NULL);
else
#endif
ctx = xmlXPathNewContext(docp);
if (!ctx) {
RETURN_FALSE;
}
rv = php_xpathcontext_new(ctx, &ret TSRMLS_CC);
DOMXML_RET_ZVAL(rv);
}
/* }}} */
/* {{{ proto object xpath_new_context([int doc_handle])
Creates new XPath context */
PHP_FUNCTION(xpath_new_context)
{
php_xpathptr_new_context(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_XPATH);
}
/* }}} */
/* {{{ proto object xptr_new_context([int doc_handle])
Creates new XPath context */
PHP_FUNCTION(xptr_new_context)
{
php_xpathptr_new_context(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_XPTR);
}
/* }}} */
/* {{{ php_xpathptr_eval()
*/
static void php_xpathptr_eval(INTERNAL_FUNCTION_PARAMETERS, int mode, int expr)
{
zval *id, *rv, *contextnode = NULL;
xmlXPathContextPtr ctxp;
xmlXPathObjectPtr xpathobjp;
xmlNode *contextnodep;
int ret, str_len;
char *str;
contextnode = NULL;
contextnodep = NULL;
if (NULL == (id = getThis())) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "os|o", &id, &str, &str_len, &contextnode) == FAILURE) {
return;
}
} else {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|o", &str, &str_len, &contextnode) == FAILURE) {
return;
}
}
ctxp = php_xpath_get_context(id, le_xpathctxp, 0 TSRMLS_CC);
if (!ctxp) {
php_error(E_WARNING, "%s(): cannot fetch XPATH context", get_active_function_name(TSRMLS_C));
RETURN_FALSE;
}
if (contextnode) {
DOMXML_GET_OBJ(contextnodep, contextnode, le_domxmlnodep);
}
ctxp->node = contextnodep;
#if defined(LIBXML_XPTR_ENABLED)
if (mode == PHP_XPTR) {
xpathobjp = xmlXPtrEval(BAD_CAST str, ctxp);
} else {
#endif
if (expr) {
xpathobjp = xmlXPathEvalExpression(str, ctxp);
} else {
xpathobjp = xmlXPathEval(str, ctxp);
}
#if defined(LIBXML_XPTR_ENABLED)
}
#endif
ctxp->node = NULL;
if (!xpathobjp) {
RETURN_FALSE;
}
if (NULL == (rv = php_xpathobject_new(xpathobjp, &ret TSRMLS_CC))) {
php_error(E_WARNING, "%s(): cannot create required XPATH objcet", get_active_function_name(TSRMLS_C));
RETURN_FALSE;
}
SEPARATE_ZVAL(&rv);
add_property_long(rv, "type", Z_TYPE_P(xpathobjp));
switch (Z_TYPE_P(xpathobjp)) {
case XPATH_UNDEFINED:
break;
case XPATH_NODESET:
{
int i;
zval *arr;
xmlNodeSetPtr nodesetp;
MAKE_STD_ZVAL(arr);
if (array_init(arr) == FAILURE) {
zval_dtor(rv);
RETURN_FALSE;
}
if (NULL == (nodesetp = xpathobjp->nodesetval)) {
zval_dtor(rv);
RETURN_FALSE;
}
for (i = 0; i < nodesetp->nodeNr; i++) {
xmlNodePtr node = nodesetp->nodeTab[i];
zval *child;
int retnode;
/* construct a node object */
child = php_domobject_new(node, &retnode TSRMLS_CC);
zend_hash_next_index_insert(Z_ARRVAL_P(arr), &child, sizeof(zval *), NULL);
}
zend_hash_update(Z_OBJPROP_P(rv), "nodeset", sizeof("nodeset"), (void *) &arr, sizeof(zval *), NULL);
break;
}
case XPATH_BOOLEAN:
add_property_bool(rv, "value", xpathobjp->boolval);
break;
case XPATH_NUMBER:
add_property_double(rv, "value", xpathobjp->floatval);
break;
case XPATH_STRING:
add_property_string(rv, "value", xpathobjp->stringval, 1);
break;
case XPATH_POINT:
break;
case XPATH_RANGE:
break;
case XPATH_LOCATIONSET:
break;
case XPATH_USERS:
break;
case XPATH_XSLT_TREE:
break;
}
*return_value = *rv;
FREE_ZVAL(rv);
}
/* }}} */
/* {{{ proto object xpath_eval([object xpathctx_handle,] string str)
Evaluates the XPath Location Path in the given string */
PHP_FUNCTION(xpath_eval)
{
php_xpathptr_eval(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_XPATH, 0);
}
/* }}} */
/* {{{ proto object xpath_eval_expression([object xpathctx_handle,] string str)
Evaluates the XPath expression in the given string */
PHP_FUNCTION(xpath_eval_expression)
{
php_xpathptr_eval(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_XPATH, 1);
}
/* }}} */
/* {{{ proto bool xpath_register_ns([object xpathctx_handle,] string namespace_prefix, string namespace_uri)
Registeres the given namespace in the passed XPath context */
PHP_FUNCTION(xpath_register_ns)
{
/*
TODO:
- automagically register all namespaces when creating a new context
*/
int prefix_len, uri_len, result;
xmlXPathContextPtr ctxp;
char *prefix, *uri, *uri_static;
zval *id;
DOMXML_PARAM_FOUR(ctxp, id, le_xpathctxp, "ss", &prefix, &prefix_len, &uri, &uri_len);
/* set the context node to NULL - what is a context node anyway? */
ctxp->node = NULL;
/*
this is a hack - libxml2 doesn't copy the URI, it simply uses the string
given in the parameter - which is normally deallocated after the function
*/
uri_static = estrndup(uri, uri_len);
result = xmlXPathRegisterNs(ctxp, prefix, uri_static);
if (0 == result) {
RETURN_TRUE;
}
RETURN_FALSE;
}
/* }}} */
#endif /* defined(LIBXML_XPATH_ENABLED) */
#if defined(LIBXML_XPTR_ENABLED)
/* {{{ proto int xptr_eval([int xpathctx_handle,] string str)
Evaluates the XPtr Location Path in the given string */
PHP_FUNCTION(xptr_eval)
{
php_xpathptr_eval(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_XPTR, 0);
}
/* }}} */
#endif /* LIBXML_XPTR_ENABLED */
/* {{{ proto string domxml_version(void)
Get XML library version */
PHP_FUNCTION(domxml_version)
{
RETURN_STRING(LIBXML_DOTTED_VERSION, 1);
}
/* }}} */
#if HAVE_DOMXSLT
static zval *php_xsltstylesheet_new(xsltStylesheetPtr obj, int *found TSRMLS_DC)
{
zval *wrapper;
int rsrc_type;
if (! found) {
*found = 0;
}
if (!obj) {
MAKE_STD_ZVAL(wrapper);
ZVAL_NULL(wrapper);
return wrapper;
}
if ((wrapper = (zval *) dom_object_get_data((void *) obj))) {
zval_add_ref(&wrapper);
*found = 1;
return wrapper;
}
MAKE_STD_ZVAL(wrapper);
object_init_ex(wrapper, domxsltstylesheet_class_entry);
rsrc_type = le_domxsltstylesheetp;
php_xsltstylesheet_set_object(wrapper, (void *) obj, rsrc_type);
return (wrapper);
}
/* {{{ proto object domxml_xslt_stylesheet(string xsltstylesheet)
Creates XSLT Stylesheet object from string */
PHP_FUNCTION(domxml_xslt_stylesheet)
{
zval *rv;
xmlDocPtr docp;
xsltStylesheetPtr sheetp;
int ret;
char *buffer;
int buffer_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buffer, &buffer_len) == FAILURE) {
RETURN_FALSE;
}
docp = xmlParseDoc(buffer);
if (!docp)
RETURN_FALSE;
sheetp = xsltParseStylesheetDoc(docp);
if (!sheetp)
RETURN_FALSE;
rv = php_xsltstylesheet_new(sheetp, &ret TSRMLS_CC);
DOMXML_RET_ZVAL(rv);
}
/* }}} */
/* {{{ proto object domxml_xslt_stylesheet_doc(object xmldoc)
Creates XSLT Stylesheet object from DOM Document object */
PHP_FUNCTION(domxml_xslt_stylesheet_doc)
{
zval *rv, *idxml;
xmlDocPtr docp;
xmlDocPtr newdocp;
xsltStylesheetPtr sheetp;
int ret;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &idxml) == FAILURE) {
RETURN_FALSE;
}
DOMXML_GET_OBJ(docp, idxml, le_domxmldocp);
newdocp = xmlCopyDoc(docp, 1);
if (!newdocp)
RETURN_FALSE;
sheetp = xsltParseStylesheetDoc(newdocp);
if (!sheetp)
RETURN_FALSE;
rv = php_xsltstylesheet_new(sheetp, &ret TSRMLS_CC);
DOMXML_RET_ZVAL(rv);
}
/* }}} */
/* {{{ proto object domxml_xslt_stylesheet_file(string filename)
Creates XSLT Stylesheet object from file */
PHP_FUNCTION(domxml_xslt_stylesheet_file)
{
zval *rv;
xsltStylesheetPtr sheetp;
int ret, file_len;
char *file;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &file_len) == FAILURE) {
RETURN_FALSE;
}
sheetp = xsltParseStylesheetFile(file);
if (!sheetp)
RETURN_FALSE;
rv = php_xsltstylesheet_new(sheetp, &ret TSRMLS_CC);
DOMXML_RET_ZVAL(rv);
}
/* }}} */
/* {{{ php_domxslt_string_to_xpathexpr()
Translates a string to a XPath Expression */
static char *php_domxslt_string_to_xpathexpr(const char *str)
{
const xmlChar *string = (const xmlChar *)str;
xmlChar *value;
TSRMLS_FETCH();
if (xmlStrchr(string, '"')) {
if (xmlStrchr(string, '\'')) {
php_error(E_WARNING, "Cannot create XPath expression (string contains both quote and double-quotes) in %s",
get_active_function_name(TSRMLS_C));
return NULL;
}
value = xmlStrdup((const xmlChar *)"'");
value = xmlStrcat(value, string);
value = xmlStrcat(value, (const xmlChar *)"'");
}
else {
value = xmlStrdup((const xmlChar *)"\"");
value = xmlStrcat(value, string);
value = xmlStrcat(value, (const xmlChar *)"\"");
}
return (char *)value;
}
/* {{{ php_domxslt_make_params()
Translates a PHP array to a libxslt parameters array */
static char **php_domxslt_make_params(zval *idvars, int xpath_params)
{
HashTable *parht;
int parsize;
zval **value;
char *xpath_expr, *string_key = NULL;
ulong num_key;
char **params = NULL;
int i = 0;
TSRMLS_FETCH();
parht = HASH_OF(idvars);
parsize = (2 * zend_hash_num_elements(parht) + 1) * sizeof(char *);
params = (char **)emalloc(parsize);
memset((char *)params, 0, parsize);
for (zend_hash_internal_pointer_reset(parht);
zend_hash_get_current_data(parht, (void **)&value) == SUCCESS;
zend_hash_move_forward(parht)) {
if (zend_hash_get_current_key(parht, &string_key, &num_key, 1) != HASH_KEY_IS_STRING) {
php_error(E_WARNING, "Invalid argument or parameter array to %s",
get_active_function_name(TSRMLS_C));
return NULL;
}
else {
SEPARATE_ZVAL(value);
convert_to_string_ex(value);
if (!xpath_params) {
xpath_expr = php_domxslt_string_to_xpathexpr(Z_STRVAL_PP(value));
}
else {
xpath_expr = Z_STRVAL_PP(value);
}
if (xpath_expr) {
params[i++] = string_key;
params[i++] = xpath_expr;
}
}
}
params[i++] = NULL;
return params;
}
/* {{{ proto object domxml_xslt_process(object xslstylesheet, object xmldoc [, array xslt_parameters [, bool xpath_parameters]])
Perform an XSLT transformation */
PHP_FUNCTION(domxml_xslt_process)
{
/* TODO:
- test memory deallocation
- test other stuff
- check xsltsp->errors ???
*/
zval *rv, *idxsl, *idxml, *idparams = NULL;
zend_bool xpath_params = 0;
xsltStylesheetPtr xsltstp;
xmlDocPtr xmldocp;
xmlDocPtr docp;
char **params = NULL;
int ret;
DOMXML_GET_THIS(idxsl);
xsltstp = php_xsltstylesheet_get_object(idxsl, le_domxsltstylesheetp, 0 TSRMLS_CC);
if (!xsltstp) {
php_error(E_WARNING, "%s(): underlying object missing",
get_active_function_name(TSRMLS_C));
RETURN_FALSE;
}
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|ab", &idxml, &idparams, &xpath_params) == FAILURE) {
RETURN_FALSE;
}
DOMXML_GET_OBJ(xmldocp, idxml, le_domxmldocp);
if (idparams) {
params = php_domxslt_make_params(idparams, xpath_params);
}
docp = xsltApplyStylesheet(xsltstp, xmldocp, (const char**)params);
if (params) {
efree(params);
}
if (!docp) {
RETURN_FALSE;
}
DOMXML_RET_OBJ(rv, (xmlNodePtr) docp, &ret);
}
/* }}} */
/* {{{ proto string domxml_xslt_version(void)
Get XSLT library version */
PHP_FUNCTION(domxml_xslt_version)
{
RETURN_STRING(LIBXSLT_DOTTED_VERSION, 1);
}
/* }}} */
#endif /* HAVE_DOMXSLT */
#endif /* HAVE_DOMXML */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/