php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
private_data.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Niels Dossche <nielsdos@php.net> |
14 +----------------------------------------------------------------------+
15*/
16
17#ifdef HAVE_CONFIG_H
18#include <config.h>
19#endif
20
21#include "php.h"
22#if defined(HAVE_LIBXML) && defined(HAVE_DOM)
23#include "php_dom.h"
24#include "private_data.h"
25#include "internal_helpers.h"
26
27static void php_dom_libxml_private_data_destroy(php_libxml_private_data_header *header)
28{
30}
31
32static void php_dom_libxml_private_data_ns_hook(php_libxml_private_data_header *header, xmlNodePtr node)
33{
35}
36
38{
39 return private_data == NULL ? NULL : &private_data->header;
40}
41
43{
44 return private_data == NULL ? NULL : &private_data->ns_mapper;
45}
46
48{
49 php_dom_private_data *private_data = emalloc(sizeof(*private_data));
50 private_data->header.dtor = php_dom_libxml_private_data_destroy;
51 private_data->header.ns_hook = php_dom_libxml_private_data_ns_hook;
52 private_data->ns_mapper.html_ns = NULL;
53 private_data->ns_mapper.prefixless_xmlns_ns = NULL;
55 private_data->template_fragments = NULL;
56 return private_data;
57}
58
60{
61 zend_hash_destroy(&data->ns_mapper.uri_to_prefix_map);
62 if (data->template_fragments != NULL) {
63 xmlNodePtr node;
64 ZEND_HASH_MAP_FOREACH_PTR(data->template_fragments, node) {
65 xmlFreeNode(node);
67 zend_hash_destroy(data->template_fragments);
68 FREE_HASHTABLE(data->template_fragments);
69 }
70 efree(data);
71}
72
73static void php_dom_free_templated_content(php_dom_private_data *private_data, xmlNodePtr base)
74{
75 /* Note: it's not possible to obtain a userland reference to these yet, so we can just free them without worrying
76 * about their proxies.
77 * Note 2: it's possible to have nested template content. */
78
79 if (zend_hash_num_elements(private_data->template_fragments) > 0) {
80 /* There's more templated content, try to free it. */
81 xmlNodePtr current = base->children;
82 while (current != NULL) {
83 if (current->type == XML_ELEMENT_NODE) {
85 }
86
87 current = php_dom_next_in_tree_order(current, base);
88 }
89 }
90
91 xmlFreeNode(base);
92}
93
94void php_dom_add_templated_content(php_dom_private_data *private_data, const xmlNode *template_node, xmlNodePtr fragment)
95{
96 if (private_data->template_fragments == NULL) {
98 zend_hash_init(private_data->template_fragments, 0, NULL, NULL, false);
100 }
101
102 zend_hash_index_add_new_ptr(private_data->template_fragments, dom_mangle_pointer_for_key(template_node), fragment);
103}
104
105xmlNodePtr php_dom_retrieve_templated_content(php_dom_private_data *private_data, const xmlNode *template_node)
106{
107 if (private_data->template_fragments == NULL) {
108 return NULL;
109 }
110
111 return zend_hash_index_find_ptr(private_data->template_fragments, dom_mangle_pointer_for_key(template_node));
112}
113
114xmlNodePtr php_dom_ensure_templated_content(php_dom_private_data *private_data, xmlNodePtr template_node)
115{
116 xmlNodePtr result = php_dom_retrieve_templated_content(private_data, template_node);
117 if (result == NULL) {
118 result = xmlNewDocFragment(template_node->doc);
119 if (EXPECTED(result != NULL)) {
120 result->parent = template_node;
121 dom_add_element_ns_hook(private_data, template_node);
122 php_dom_add_templated_content(private_data, template_node, result);
123 }
124 }
125 return result;
126}
127
128void php_dom_remove_templated_content(php_dom_private_data *private_data, const xmlNode *template_node)
129{
130 if (private_data->template_fragments != NULL) {
131 /* Deletion needs to be done not via a destructor because we can't access private_data from there. */
132 zval *zv = zend_hash_index_find(private_data->template_fragments, dom_mangle_pointer_for_key(template_node));
133 if (zv != NULL) {
134 xmlNodePtr node = Z_PTR_P(zv);
135 ZEND_ASSERT(offsetof(Bucket, val) == 0 && "Type cast only works if this is true");
136 Bucket* bucket = (Bucket*) zv;
137 /* First remove it from the bucket before freeing the content, otherwise recursion could make the bucket
138 * pointer invalid due to hash table structure changes. */
139 zend_hash_del_bucket(private_data->template_fragments, bucket);
140 php_dom_free_templated_content(private_data, node);
141 }
142 }
143}
144
145uint32_t php_dom_get_template_count(const php_dom_private_data *private_data)
146{
147 if (private_data->template_fragments != NULL) {
148 return zend_hash_num_elements(private_data->template_fragments);
149 } else {
150 return 0;
151 }
152}
153
154void dom_add_element_ns_hook(php_dom_private_data *private_data, xmlNodePtr element)
155{
156 xmlNsPtr ns = pemalloc(sizeof(*ns), true);
157
158 /* The private data is a tagged data structure where only tag 1 is defined by ext/libxml to register a hook. */
159 memset(ns, 0, sizeof(*ns));
160 ns->prefix = xmlStrdup(element->ns->prefix);
161 ns->href = xmlStrdup(element->ns->href);
162 ns->type = XML_LOCAL_NAMESPACE;
163 ns->_private = (void *) ((uintptr_t) private_data | LIBXML_NS_TAG_HOOK);
164 element->ns = ns;
165
166 php_libxml_set_old_ns(element->doc, ns);
167}
168
169#endif /* HAVE_LIBXML && HAVE_DOM */
header(string $header, bool $replace=true, int $response_code=0)
zval * zv
Definition ffi.c:3975
memset(ptr, 0, type->size)
zval * val
Definition ffi.c:4262
#define NULL
Definition gdcache.h:45
const XML_ELEMENT_NODE
const XML_LOCAL_NAMESPACE
#define offsetof(STRUCTURE, FIELD)
zend_constant * data
void php_dom_private_data_destroy(php_dom_private_data *data)
void php_dom_add_templated_content(php_dom_private_data *private_data, const xmlNode *template_node, xmlNodePtr fragment)
php_dom_private_data * php_dom_private_data_create(void)
xmlNodePtr php_dom_ensure_templated_content(php_dom_private_data *private_data, xmlNodePtr template_node)
struct php_libxml_private_data_header php_libxml_private_data_header
uint32_t php_dom_get_template_count(const php_dom_private_data *private_data)
php_dom_libxml_ns_mapper * php_dom_ns_mapper_from_private(php_dom_private_data *private_data)
void dom_add_element_ns_hook(php_dom_private_data *private_data, xmlNodePtr element)
php_libxml_private_data_header * php_dom_libxml_private_data_header(php_dom_private_data *private_data)
void php_dom_remove_templated_content(php_dom_private_data *private_data, const xmlNode *template_node)
xmlNodePtr php_dom_retrieve_templated_content(php_dom_private_data *private_data, const xmlNode *template_node)
zval * current
Definition session.c:1024
struct php_dom_libxml_ns_mapper ns_mapper
HashTable * template_fragments
php_libxml_private_data_header header
#define efree(ptr)
Definition zend_alloc.h:155
#define pemalloc(size, persistent)
Definition zend_alloc.h:189
#define FREE_HASHTABLE(ht)
Definition zend_alloc.h:234
#define ALLOC_HASHTABLE(ht)
Definition zend_alloc.h:231
#define emalloc(size)
Definition zend_alloc.h:151
struct _zval_struct zval
ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
Definition zend_hash.c:1727
ZEND_API void ZEND_FASTCALL zend_hash_del_bucket(HashTable *ht, Bucket *p)
Definition zend_hash.c:1526
ZEND_API void ZEND_FASTCALL zend_hash_real_init_mixed(HashTable *ht)
Definition zend_hash.c:338
ZEND_API zval *ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h)
Definition zend_hash.c:2701
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent)
Definition zend_hash.h:108
#define ZEND_HASH_MAP_FOREACH_PTR(ht, _ptr)
Definition zend_hash.h:1326
#define ZEND_HASH_FOREACH_END()
Definition zend_hash.h:1086
#define EXPECTED(condition)
#define ZEND_ASSERT(c)
#define Z_PTR_P(zval_p)
struct _Bucket Bucket
#define ZVAL_PTR_DTOR
bool result