forked from php/php-src
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathphp_dom.h
324 lines (287 loc) · 14.2 KB
/
php_dom.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
/*
+----------------------------------------------------------------------+
| Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| https://www.php.net/license/3_01.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. |
+----------------------------------------------------------------------+
| Authors: Christian Stocker <chregu@php.net> |
| Rob Richards <rrichards@php.net> |
| Marcus Borger <helly@php.net> |
+----------------------------------------------------------------------+
*/
#ifndef PHP_DOM_H
#define PHP_DOM_H
extern zend_module_entry dom_module_entry;
#define phpext_dom_ptr &dom_module_entry
#ifdef ZTS
#include "TSRM.h"
#endif
#include <libxml/parser.h>
#include <libxml/parserInternals.h>
#include <libxml/tree.h>
#include <libxml/uri.h>
#include <libxml/xmlerror.h>
#include <libxml/xinclude.h>
#include <libxml/hash.h>
#include <libxml/c14n.h>
#ifdef LIBXML_HTML_ENABLED
#include <libxml/HTMLparser.h>
#include <libxml/HTMLtree.h>
#endif
#ifdef LIBXML_XPATH_ENABLED
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#endif
#ifdef LIBXML_XPTR_ENABLED
#include <libxml/xpointer.h>
#endif
#ifdef PHP_WIN32
#ifndef DOM_EXPORTS
#define DOM_EXPORTS
#endif
#endif
#include "xml_common.h"
#include "ext/libxml/php_libxml.h"
#include "xpath_callbacks.h"
#include "zend_exceptions.h"
#include "dom_ce.h"
/* DOM API_VERSION, please bump it up, if you change anything in the API
therefore it's easier for the script-programmers to check, what's working how
Can be checked with phpversion("dom");
*/
#define DOM_API_VERSION "20031129"
/* Define a custom type for iterating using an unused nodetype */
#define DOM_NODESET XML_XINCLUDE_START
typedef struct dom_xpath_object {
php_dom_xpath_callbacks xpath_callbacks;
bool register_node_ns;
dom_object dom;
} dom_xpath_object;
static inline dom_xpath_object *php_xpath_obj_from_obj(zend_object *obj) {
return (dom_xpath_object*)((char*)(obj)
- XtOffsetOf(dom_xpath_object, dom) - XtOffsetOf(dom_object, std));
}
#define Z_XPATHOBJ_P(zv) php_xpath_obj_from_obj(Z_OBJ_P((zv)))
typedef struct dom_nnodemap_object {
dom_object *baseobj;
zval baseobj_zv;
int nodetype;
int cached_length;
xmlHashTable *ht;
xmlChar *local;
zend_string *local_lower;
xmlChar *ns;
php_libxml_cache_tag cache_tag;
dom_object *cached_obj;
zend_long cached_obj_index;
xmlDictPtr dict;
bool release_local : 1;
bool release_ns : 1;
} dom_nnodemap_object;
typedef struct {
zend_object_iterator intern;
zval curobj;
HashPosition pos;
/* intern->index is only updated for FE_* opcodes, not for e.g. unpacking,
* yet we need to track the position of the node relative to the start. */
zend_ulong index;
php_libxml_cache_tag cache_tag;
} php_dom_iterator;
typedef struct {
/* This may be a fake object that isn't actually in the children list of the parent.
* This is because some namespace declaration nodes aren't stored on the parent in libxml2, so we have to fake it.
* We could use a zval for this, but since this is always going to be an object let's save space... */
dom_object *parent_intern;
dom_object dom;
} dom_object_namespace_node;
struct php_dom_libxml_ns_mapper;
typedef struct php_dom_libxml_ns_mapper php_dom_libxml_ns_mapper;
static inline dom_object_namespace_node *php_dom_namespace_node_obj_from_obj(zend_object *obj) {
return (dom_object_namespace_node*)((char*)(obj) - XtOffsetOf(dom_object_namespace_node, dom.std));
}
#include "domexception.h"
#define DOM_HTML_NO_DEFAULT_NS (1U << 31)
void dom_objects_free_storage(zend_object *object);
dom_doc_propsptr dom_get_doc_props(php_libxml_ref_obj *document);
libxml_doc_props const* dom_get_doc_props_read_only(const php_libxml_ref_obj *document);
zend_object *dom_objects_new(zend_class_entry *class_type);
zend_object *dom_nnodemap_objects_new(zend_class_entry *class_type);
#ifdef LIBXML_XPATH_ENABLED
zend_object *dom_xpath_objects_new(zend_class_entry *class_type);
#endif
bool dom_get_strict_error(php_libxml_ref_obj *document);
void node_list_unlink(xmlNodePtr node);
int dom_check_qname(char *qname, char **localname, char **prefix, int uri_len, int name_len);
xmlNsPtr dom_get_ns(xmlNodePtr node, char *uri, int *errorcode, char *prefix);
xmlNsPtr dom_get_ns_unchecked(xmlNodePtr nodep, char *uri, char *prefix);
void dom_reconcile_ns(xmlDocPtr doc, xmlNodePtr nodep);
void dom_reconcile_ns_list(xmlDocPtr doc, xmlNodePtr nodep, xmlNodePtr last);
xmlNsPtr dom_get_nsdecl(xmlNode *node, xmlChar *localName);
void php_dom_normalize_legacy(xmlNodePtr nodep);
void php_dom_normalize_modern(xmlNodePtr nodep);
xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr basep, xmlNodePtr nodep, const xmlChar *ns, const xmlChar *local, const zend_string *local_lower, zend_long *cur, zend_long index);
void php_dom_create_implementation(zval *retval, bool modern);
int dom_hierarchy(xmlNodePtr parent, xmlNodePtr child);
bool dom_has_feature(zend_string *feature, zend_string *version);
bool dom_node_is_read_only(const xmlNode *node);
bool dom_node_children_valid(const xmlNode *node);
void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xmlHashTablePtr ht, zend_string *local, zend_string *ns);
xmlNodePtr create_notation(const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID);
xmlNode *php_dom_libxml_hash_iter(dom_nnodemap_object *objmap, int index);
zend_object_iterator *php_dom_get_iterator(zend_class_entry *ce, zval *object, int by_ref);
void dom_set_doc_classmap(php_libxml_ref_obj *document, zend_class_entry *basece, zend_class_entry *ce);
xmlNodePtr php_dom_create_fake_namespace_decl(xmlNodePtr nodep, xmlNsPtr original, zval *return_value, dom_object *parent_intern);
void php_dom_get_content_into_zval(const xmlNode *nodep, zval *target, bool default_is_null);
zend_string *dom_node_concatenated_name_helper(size_t name_len, const char *name, size_t prefix_len, const char *prefix);
zend_string *dom_node_get_node_name_attribute_or_element(const xmlNode *nodep, bool uppercase);
bool php_dom_is_node_connected(const xmlNode *node);
bool php_dom_adopt_node(xmlNodePtr nodep, dom_object *dom_object_new_document, xmlDocPtr new_document);
xmlNsPtr dom_get_ns_resolve_prefix_conflict(xmlNodePtr tree, const char *uri);
int dom_validate_and_extract(const zend_string *namespace, const zend_string *qname, xmlChar **localName, xmlChar **prefix);
bool dom_match_qualified_name_according_to_spec(const xmlChar *qname, const xmlNode *nodep);
bool php_dom_has_sibling_following_node(xmlNodePtr node, xmlElementType type);
bool php_dom_has_sibling_preceding_node(xmlNodePtr node, xmlElementType type);
bool php_dom_has_child_of_type(xmlNodePtr node, xmlElementType type);
void php_dom_update_document_after_clone(dom_object *original, xmlNodePtr original_node, dom_object *clone, xmlNodePtr cloned_node);
xmlAttrPtr php_dom_get_attribute_node(xmlNodePtr elem, const xmlChar *name, size_t name_len);
xmlChar *php_dom_libxml_fix_file_path(xmlChar *path);
void dom_document_convert_to_modern(php_libxml_ref_obj *document, xmlDocPtr lxml_doc);
dom_object *php_dom_instantiate_object_helper(zval *return_value, zend_class_entry *ce, xmlNodePtr obj, dom_object *parent);
xmlDocPtr php_dom_create_html_doc(void);
xmlEntityPtr dom_entity_reference_fetch_and_sync_declaration(xmlNodePtr reference);
void dom_set_xml_class(php_libxml_ref_obj *document);
const char *dom_locate_a_namespace(const xmlNode *node, const zend_string *prefix);
void dom_mark_namespaces_as_attributes_too(php_dom_libxml_ns_mapper *ns_mapper, xmlDocPtr doc);
bool dom_compare_value(const xmlAttr *attr, const xmlChar *value);
void dom_attr_value_will_change(dom_object *obj, xmlAttrPtr attrp);
bool php_dom_create_nullable_object(xmlNodePtr obj, zval *return_value, dom_object *domobj);
xmlNodePtr dom_clone_node(php_dom_libxml_ns_mapper *ns_mapper, xmlNodePtr node, xmlDocPtr doc, bool recursive);
void dom_set_document_ref_pointers(xmlNodePtr node, php_libxml_ref_obj *document);
void dom_set_document_ref_pointers_attr(xmlAttrPtr attr, php_libxml_ref_obj *document);
typedef enum {
DOM_LOAD_STRING = 0,
DOM_LOAD_FILE = 1,
} dom_load_mode;
#define DOM_DOCUMENT_MALFORMED ((xmlDocPtr) -1)
xmlDocPtr dom_document_parser(zval *id, dom_load_mode mode, const char *source, size_t source_len, size_t options, xmlCharEncodingHandlerPtr encoding);
/* parentnode */
void dom_parent_node_prepend(dom_object *context, zval *nodes, uint32_t nodesc);
void dom_parent_node_append(dom_object *context, zval *nodes, uint32_t nodesc);
void dom_parent_node_after(dom_object *context, zval *nodes, uint32_t nodesc);
void dom_parent_node_before(dom_object *context, zval *nodes, uint32_t nodesc);
void dom_parent_node_replace_children(dom_object *context, zval *nodes, uint32_t nodesc);
void dom_child_node_remove(dom_object *context);
void dom_child_replace_with(dom_object *context, zval *nodes, uint32_t nodesc);
void dom_remove_all_children(xmlNodePtr nodep);
bool php_dom_fragment_insertion_hierarchy_check_pre_insertion(xmlNodePtr parent, xmlNodePtr node, xmlNodePtr child);
bool php_dom_fragment_insertion_hierarchy_check_replace(xmlNodePtr parent, xmlNodePtr node, xmlNodePtr child);
void php_dom_node_append(php_libxml_ref_obj *document, xmlNodePtr node, xmlNodePtr parent);
bool php_dom_pre_insert(php_libxml_ref_obj *document, xmlNodePtr node, xmlNodePtr parent, xmlNodePtr insertion_point);
bool php_dom_pre_insert_is_parent_invalid(xmlNodePtr parent);
void dom_parent_node_query_selector(xmlNodePtr thisp, dom_object *intern, zval *return_value, const zend_string *selectors_str);
void dom_parent_node_query_selector_all(xmlNodePtr thisp, dom_object *intern, zval *return_value, const zend_string *selectors_str);
void dom_element_matches(xmlNodePtr thisp, dom_object *intern, zval *return_value, const zend_string *selectors_str);
void dom_element_closest(xmlNodePtr thisp, dom_object *intern, zval *return_value, const zend_string *selectors_str);
xmlNodePtr dom_parse_fragment(dom_object *obj, xmlNodePtr context_node, const zend_string *input);
/* nodemap and nodelist APIs */
xmlNodePtr php_dom_named_node_map_get_named_item(dom_nnodemap_object *objmap, const zend_string *named, bool may_transform);
void php_dom_named_node_map_get_named_item_into_zval(dom_nnodemap_object *objmap, const zend_string *named, zval *return_value);
xmlNodePtr php_dom_named_node_map_get_item(dom_nnodemap_object *objmap, zend_long index);
void php_dom_named_node_map_get_item_into_zval(dom_nnodemap_object *objmap, zend_long index, zval *return_value);
zend_long php_dom_get_namednodemap_length(dom_object *obj);
xmlNodePtr dom_nodelist_iter_start_first_child(xmlNodePtr nodep);
#define DOM_GET_INTERN(__id, __intern) { \
__intern = Z_DOMOBJ_P(__id); \
if (UNEXPECTED(__intern->ptr == NULL)) { \
zend_throw_error(NULL, "Couldn't fetch %s", ZSTR_VAL(__intern->std.ce->name));\
RETURN_THROWS();\
} \
}
#define DOM_GET_THIS_INTERN(__intern) DOM_GET_INTERN(ZEND_THIS, __intern)
#define DOM_GET_OBJ(__ptr, __id, __prtype, __intern) { \
DOM_GET_INTERN(__id, __intern); \
__ptr = (__prtype)((php_libxml_node_ptr *)__intern->ptr)->node; \
}
static zend_always_inline bool php_dom_is_cache_tag_stale_from_doc_ptr(const php_libxml_cache_tag *cache_tag, const php_libxml_ref_obj *doc_ptr)
{
ZEND_ASSERT(doc_ptr != NULL);
return php_libxml_is_cache_tag_stale(cache_tag, &doc_ptr->cache_tag);
}
static zend_always_inline bool php_dom_is_cache_tag_stale_from_node(const php_libxml_cache_tag *cache_tag, const xmlNode *node)
{
ZEND_ASSERT(node != NULL);
php_libxml_node_ptr *_private = node->_private;
if (!_private) {
return true;
}
php_libxml_node_object *object_private = _private->_private;
if (!object_private || !object_private->document) {
return true;
}
return php_dom_is_cache_tag_stale_from_doc_ptr(cache_tag, object_private->document);
}
static zend_always_inline void php_dom_mark_cache_tag_up_to_date_from_node(php_libxml_cache_tag *cache_tag, const xmlNode *node)
{
ZEND_ASSERT(cache_tag != NULL);
php_libxml_node_ptr *_private = node->_private;
if (_private) {
php_libxml_node_object *object_private = _private->_private;
if (object_private->document) {
cache_tag->modification_nr = object_private->document->cache_tag.modification_nr;
}
}
}
static zend_always_inline void php_dom_mark_cache_tag_up_to_date_from_doc_ref(php_libxml_cache_tag *cache_tag, const php_libxml_ref_obj *document)
{
ZEND_ASSERT(cache_tag != NULL);
ZEND_ASSERT(document != NULL);
cache_tag->modification_nr = document->cache_tag.modification_nr;
}
static zend_always_inline bool php_dom_follow_spec_node(const xmlNode *node)
{
ZEND_ASSERT(node != NULL);
php_libxml_node_ptr *_private = node->_private;
if (_private) {
php_libxml_node_object *object_private = _private->_private;
if (object_private->document) {
return php_dom_follow_spec_doc_ref(object_private->document);
}
}
return false;
}
/* Returns the first child of a container node (e.g. elements, fragments, documents, ...). */
static zend_always_inline xmlNodePtr php_dom_first_child_of_container_node(xmlNodePtr parent)
{
if (parent->type == XML_DOCUMENT_NODE || parent->type == XML_HTML_DOCUMENT_NODE) {
return xmlDocGetRootElement((xmlDoc *) parent);
} else {
return parent->children;
}
}
static zend_always_inline const xmlChar *php_dom_get_content_or_empty(const xmlNode *node)
{
return node->content ? node->content : BAD_CAST "";
}
#define PHP_DOM_DEPRECATED_PROPERTY(message) do { \
if (EXPECTED(!DOM_G(suppress_warnings))) {\
zend_error(E_DEPRECATED, message); \
if (UNEXPECTED(EG(exception))) { \
return FAILURE; \
} \
} \
} while (0)
ZEND_BEGIN_MODULE_GLOBALS(dom)
bool suppress_warnings;
ZEND_END_MODULE_GLOBALS(dom)
ZEND_EXTERN_MODULE_GLOBALS(dom)
#define DOM_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(dom, v)
PHP_MINIT_FUNCTION(dom);
PHP_MSHUTDOWN_FUNCTION(dom);
PHP_MINFO_FUNCTION(dom);
#endif /* PHP_DOM_H */