xref: /PHP-7.3/ext/dom/characterdata.c (revision 8d3f8ca1)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2018 The PHP Group                                |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Authors: Christian Stocker <chregu@php.net>                          |
16    |          Rob Richards <rrichards@php.net>                            |
17    +----------------------------------------------------------------------+
18 */
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include "php.h"
25 #if HAVE_LIBXML && HAVE_DOM
26 #include "php_dom.h"
27 
28 
29 /* {{{ arginfo */
30 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_characterdata_substring_data, 0, 0, 2)
31 	ZEND_ARG_INFO(0, offset)
32 	ZEND_ARG_INFO(0, count)
33 ZEND_END_ARG_INFO();
34 
35 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_characterdata_append_data, 0, 0, 1)
36 	ZEND_ARG_INFO(0, arg)
37 ZEND_END_ARG_INFO();
38 
39 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_characterdata_insert_data, 0, 0, 2)
40 	ZEND_ARG_INFO(0, offset)
41 	ZEND_ARG_INFO(0, arg)
42 ZEND_END_ARG_INFO();
43 
44 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_characterdata_delete_data, 0, 0, 2)
45 	ZEND_ARG_INFO(0, offset)
46 	ZEND_ARG_INFO(0, count)
47 ZEND_END_ARG_INFO();
48 
49 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_characterdata_replace_data, 0, 0, 3)
50 	ZEND_ARG_INFO(0, offset)
51 	ZEND_ARG_INFO(0, count)
52 	ZEND_ARG_INFO(0, arg)
53 ZEND_END_ARG_INFO();
54 /* }}} */
55 
56 /*
57 * class DOMCharacterData extends DOMNode
58 *
59 * URL: https://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-FF21A306
60 * Since:
61 */
62 
63 const zend_function_entry php_dom_characterdata_class_functions[] = {
64 	PHP_FALIAS(substringData, dom_characterdata_substring_data, arginfo_dom_characterdata_substring_data)
65 	PHP_FALIAS(appendData, dom_characterdata_append_data, arginfo_dom_characterdata_append_data)
66 	PHP_FALIAS(insertData, dom_characterdata_insert_data, arginfo_dom_characterdata_insert_data)
67 	PHP_FALIAS(deleteData, dom_characterdata_delete_data, arginfo_dom_characterdata_delete_data)
68 	PHP_FALIAS(replaceData, dom_characterdata_replace_data, arginfo_dom_characterdata_replace_data)
69 	PHP_FE_END
70 };
71 
72 /* {{{ data	string
73 readonly=no
74 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-72AB8359
75 Since:
76 */
dom_characterdata_data_read(dom_object * obj,zval * retval)77 int dom_characterdata_data_read(dom_object *obj, zval *retval)
78 {
79 	xmlNodePtr nodep = dom_object_get_node(obj);
80 	xmlChar *content;
81 
82 	if (nodep == NULL) {
83 		php_dom_throw_error(INVALID_STATE_ERR, 0);
84 		return FAILURE;
85 	}
86 
87 	if ((content = xmlNodeGetContent(nodep)) != NULL) {
88 		ZVAL_STRING(retval, (char *) content);
89 		xmlFree(content);
90 	} else {
91 		ZVAL_EMPTY_STRING(retval);
92 	}
93 
94 	return SUCCESS;
95 }
96 
dom_characterdata_data_write(dom_object * obj,zval * newval)97 int dom_characterdata_data_write(dom_object *obj, zval *newval)
98 {
99 	xmlNode *nodep = dom_object_get_node(obj);
100 	zend_string *str;
101 
102 	if (nodep == NULL) {
103 		php_dom_throw_error(INVALID_STATE_ERR, 0);
104 		return FAILURE;
105 	}
106 
107 	str = zval_get_string(newval);
108 
109 	xmlNodeSetContentLen(nodep, (xmlChar *) ZSTR_VAL(str), ZSTR_LEN(str) + 1);
110 
111 	zend_string_release_ex(str, 0);
112 	return SUCCESS;
113 }
114 
115 /* }}} */
116 
117 /* {{{ length	long
118 readonly=yes
119 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-7D61178C
120 Since:
121 */
dom_characterdata_length_read(dom_object * obj,zval * retval)122 int dom_characterdata_length_read(dom_object *obj, zval *retval)
123 {
124 	xmlNodePtr nodep = dom_object_get_node(obj);
125 	xmlChar *content;
126 	long length = 0;
127 
128 	if (nodep == NULL) {
129 		php_dom_throw_error(INVALID_STATE_ERR, 0);
130 		return FAILURE;
131 	}
132 
133 	content = xmlNodeGetContent(nodep);
134 
135 	if (content) {
136 		length = xmlUTF8Strlen(content);
137 		xmlFree(content);
138 	}
139 
140 	ZVAL_LONG(retval, length);
141 
142 	return SUCCESS;
143 }
144 
145 /* }}} */
146 
147 /* {{{ proto string dom_characterdata_substring_data(int offset, int count);
148 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-6531BCCF
149 Since:
150 */
PHP_FUNCTION(dom_characterdata_substring_data)151 PHP_FUNCTION(dom_characterdata_substring_data)
152 {
153 	zval       *id;
154 	xmlChar    *cur;
155 	xmlChar    *substring;
156 	xmlNodePtr  node;
157 	zend_long        offset, count;
158 	int         length;
159 	dom_object	*intern;
160 
161 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oll", &id, dom_characterdata_class_entry, &offset, &count) == FAILURE) {
162 		return;
163 	}
164 
165 	DOM_GET_OBJ(node, id, xmlNodePtr, intern);
166 
167 	cur = xmlNodeGetContent(node);
168 	if (cur == NULL) {
169 		RETURN_FALSE;
170 	}
171 
172 	length = xmlUTF8Strlen(cur);
173 
174 	if (offset < 0 || count < 0 || ZEND_LONG_INT_OVFL(offset) || ZEND_LONG_INT_OVFL(count) || offset > length) {
175 		xmlFree(cur);
176 		php_dom_throw_error(INDEX_SIZE_ERR, dom_get_strict_error(intern->document));
177 		RETURN_FALSE;
178 	}
179 
180 	if ((offset + count) > length) {
181 		count = length - offset;
182 	}
183 
184 	substring = xmlUTF8Strsub(cur, (int)offset, (int)count);
185 	xmlFree(cur);
186 
187 	if (substring) {
188 		RETVAL_STRING((char *) substring);
189 		xmlFree(substring);
190 	} else {
191 		RETVAL_EMPTY_STRING();
192 	}
193 }
194 /* }}} end dom_characterdata_substring_data */
195 
196 /* {{{ proto void dom_characterdata_append_data(string arg);
197 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-32791A2F
198 Since:
199 */
PHP_FUNCTION(dom_characterdata_append_data)200 PHP_FUNCTION(dom_characterdata_append_data)
201 {
202 	zval *id;
203 	xmlNode *nodep;
204 	dom_object *intern;
205 	char *arg;
206 	size_t arg_len;
207 
208 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &id, dom_characterdata_class_entry, &arg, &arg_len) == FAILURE) {
209 		return;
210 	}
211 
212 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
213 #if LIBXML_VERSION < 20627
214 /* Implement logic from libxml xmlTextConcat to add support for comments and PI */
215     if ((nodep->content == (xmlChar *) &(nodep->properties)) ||
216         ((nodep->doc != NULL) && (nodep->doc->dict != NULL) &&
217 		xmlDictOwns(nodep->doc->dict, nodep->content))) {
218 	nodep->content = xmlStrncatNew(nodep->content, arg, arg_len);
219     } else {
220         nodep->content = xmlStrncat(nodep->content, arg, arg_len);
221     }
222     nodep->properties = NULL;
223 #else
224 	xmlTextConcat(nodep, (xmlChar *) arg, arg_len);
225 #endif
226 	RETURN_TRUE;
227 }
228 /* }}} end dom_characterdata_append_data */
229 
230 /* {{{ proto void dom_characterdata_insert_data(int offset, string arg);
231 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-3EDB695F
232 Since:
233 */
PHP_FUNCTION(dom_characterdata_insert_data)234 PHP_FUNCTION(dom_characterdata_insert_data)
235 {
236 	zval *id;
237 	xmlChar		*cur, *first, *second;
238 	xmlNodePtr  node;
239 	char		*arg;
240 	zend_long        offset;
241 	int         length;
242 	size_t arg_len;
243 	dom_object	*intern;
244 
245 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ols", &id, dom_characterdata_class_entry, &offset, &arg, &arg_len) == FAILURE) {
246 		return;
247 	}
248 
249 	DOM_GET_OBJ(node, id, xmlNodePtr, intern);
250 
251 	cur = xmlNodeGetContent(node);
252 	if (cur == NULL) {
253 		RETURN_FALSE;
254 	}
255 
256 	length = xmlUTF8Strlen(cur);
257 
258 	if (offset < 0 || ZEND_LONG_INT_OVFL(offset) || offset > length) {
259 		xmlFree(cur);
260 		php_dom_throw_error(INDEX_SIZE_ERR, dom_get_strict_error(intern->document));
261 		RETURN_FALSE;
262 	}
263 
264 	first = xmlUTF8Strndup(cur, (int)offset);
265 	second = xmlUTF8Strsub(cur, (int)offset, length - (int)offset);
266 	xmlFree(cur);
267 
268 	xmlNodeSetContent(node, first);
269 	xmlNodeAddContent(node, (xmlChar *) arg);
270 	xmlNodeAddContent(node, second);
271 
272 	xmlFree(first);
273 	xmlFree(second);
274 
275 	RETURN_TRUE;
276 }
277 /* }}} end dom_characterdata_insert_data */
278 
279 /* {{{ proto void dom_characterdata_delete_data(int offset, int count);
280 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-7C603781
281 Since:
282 */
PHP_FUNCTION(dom_characterdata_delete_data)283 PHP_FUNCTION(dom_characterdata_delete_data)
284 {
285 	zval *id;
286 	xmlChar    *cur, *substring, *second;
287 	xmlNodePtr  node;
288 	zend_long        offset, count;
289 	int         length;
290 	dom_object	*intern;
291 
292 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oll", &id, dom_characterdata_class_entry, &offset, &count) == FAILURE) {
293 		return;
294 	}
295 
296 	DOM_GET_OBJ(node, id, xmlNodePtr, intern);
297 
298 	cur = xmlNodeGetContent(node);
299 	if (cur == NULL) {
300 		RETURN_FALSE;
301 	}
302 
303 	length = xmlUTF8Strlen(cur);
304 
305 	if (offset < 0 || count < 0 || ZEND_LONG_INT_OVFL(offset) || ZEND_LONG_INT_OVFL(count) || offset > length) {
306 		xmlFree(cur);
307 		php_dom_throw_error(INDEX_SIZE_ERR, dom_get_strict_error(intern->document));
308 		RETURN_FALSE;
309 	}
310 
311 	if (offset > 0) {
312 		substring = xmlUTF8Strsub(cur, 0, (int)offset);
313 	} else {
314 		substring = NULL;
315 	}
316 
317 	if ((offset + count) > length) {
318 		count = length - offset;
319 	}
320 
321 	second = xmlUTF8Strsub(cur, (int)offset + (int)count, length - (int)offset);
322 	substring = xmlStrcat(substring, second);
323 
324 	xmlNodeSetContent(node, substring);
325 
326 	xmlFree(cur);
327 	xmlFree(second);
328 	xmlFree(substring);
329 
330 	RETURN_TRUE;
331 }
332 /* }}} end dom_characterdata_delete_data */
333 
334 /* {{{ proto void dom_characterdata_replace_data(int offset, int count, string arg);
335 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-E5CBA7FB
336 Since:
337 */
PHP_FUNCTION(dom_characterdata_replace_data)338 PHP_FUNCTION(dom_characterdata_replace_data)
339 {
340 	zval *id;
341 	xmlChar		*cur, *substring, *second = NULL;
342 	xmlNodePtr  node;
343 	char		*arg;
344 	zend_long        offset, count;
345 	int         length;
346 	size_t arg_len;
347 	dom_object	*intern;
348 
349 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Olls", &id, dom_characterdata_class_entry, &offset, &count, &arg, &arg_len) == FAILURE) {
350 		return;
351 	}
352 
353 	DOM_GET_OBJ(node, id, xmlNodePtr, intern);
354 
355 	cur = xmlNodeGetContent(node);
356 	if (cur == NULL) {
357 		RETURN_FALSE;
358 	}
359 
360 	length = xmlUTF8Strlen(cur);
361 
362 	if (offset < 0 || count < 0 || ZEND_LONG_INT_OVFL(offset) || ZEND_LONG_INT_OVFL(count) || offset > length) {
363 		xmlFree(cur);
364 		php_dom_throw_error(INDEX_SIZE_ERR, dom_get_strict_error(intern->document));
365 		RETURN_FALSE;
366 	}
367 
368 	if (offset > 0) {
369 		substring = xmlUTF8Strsub(cur, 0, (int)offset);
370 	} else {
371 		substring = NULL;
372 	}
373 
374 	if ((offset + count) > length) {
375 		count = length - offset;
376 	}
377 
378 	if (offset < length) {
379 		second = xmlUTF8Strsub(cur, (int)offset + count, length - (int)offset);
380 	}
381 
382 	substring = xmlStrcat(substring, (xmlChar *) arg);
383 	substring = xmlStrcat(substring, second);
384 
385 	xmlNodeSetContent(node, substring);
386 
387 	xmlFree(cur);
388 	if (second) {
389 		xmlFree(second);
390 	}
391 	xmlFree(substring);
392 
393 	RETURN_TRUE;
394 }
395 /* }}} end dom_characterdata_replace_data */
396 
397 #endif
398 
399 /*
400  * Local variables:
401  * tab-width: 4
402  * c-basic-offset: 4
403  * End:
404  * vim600: noet sw=4 ts=4 fdm=marker
405  * vim<600: noet sw=4 ts=4
406  */
407