xref: /PHP-7.4/ext/dom/characterdata.c (revision 457392fa)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 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_try_get_string(newval);
108 	if (UNEXPECTED(!str)) {
109 		return FAILURE;
110 	}
111 
112 	xmlNodeSetContentLen(nodep, (xmlChar *) ZSTR_VAL(str), ZSTR_LEN(str) + 1);
113 
114 	zend_string_release_ex(str, 0);
115 	return SUCCESS;
116 }
117 
118 /* }}} */
119 
120 /* {{{ length	long
121 readonly=yes
122 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-7D61178C
123 Since:
124 */
dom_characterdata_length_read(dom_object * obj,zval * retval)125 int dom_characterdata_length_read(dom_object *obj, zval *retval)
126 {
127 	xmlNodePtr nodep = dom_object_get_node(obj);
128 	xmlChar *content;
129 	long length = 0;
130 
131 	if (nodep == NULL) {
132 		php_dom_throw_error(INVALID_STATE_ERR, 0);
133 		return FAILURE;
134 	}
135 
136 	content = xmlNodeGetContent(nodep);
137 
138 	if (content) {
139 		length = xmlUTF8Strlen(content);
140 		xmlFree(content);
141 	}
142 
143 	ZVAL_LONG(retval, length);
144 
145 	return SUCCESS;
146 }
147 
148 /* }}} */
149 
150 /* {{{ proto string dom_characterdata_substring_data(int offset, int count);
151 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-6531BCCF
152 Since:
153 */
PHP_FUNCTION(dom_characterdata_substring_data)154 PHP_FUNCTION(dom_characterdata_substring_data)
155 {
156 	zval       *id;
157 	xmlChar    *cur;
158 	xmlChar    *substring;
159 	xmlNodePtr  node;
160 	zend_long        offset, count;
161 	int         length;
162 	dom_object	*intern;
163 
164 	id = ZEND_THIS;
165 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll", &offset, &count) == FAILURE) {
166 		return;
167 	}
168 
169 	DOM_GET_OBJ(node, id, xmlNodePtr, intern);
170 
171 	cur = xmlNodeGetContent(node);
172 	if (cur == NULL) {
173 		RETURN_FALSE;
174 	}
175 
176 	length = xmlUTF8Strlen(cur);
177 
178 	if (offset < 0 || count < 0 || ZEND_LONG_INT_OVFL(offset) || ZEND_LONG_INT_OVFL(count) || offset > length) {
179 		xmlFree(cur);
180 		php_dom_throw_error(INDEX_SIZE_ERR, dom_get_strict_error(intern->document));
181 		RETURN_FALSE;
182 	}
183 
184 	if ((offset + count) > length) {
185 		count = length - offset;
186 	}
187 
188 	substring = xmlUTF8Strsub(cur, (int)offset, (int)count);
189 	xmlFree(cur);
190 
191 	if (substring) {
192 		RETVAL_STRING((char *) substring);
193 		xmlFree(substring);
194 	} else {
195 		RETVAL_EMPTY_STRING();
196 	}
197 }
198 /* }}} end dom_characterdata_substring_data */
199 
200 /* {{{ proto void dom_characterdata_append_data(string arg);
201 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-32791A2F
202 Since:
203 */
PHP_FUNCTION(dom_characterdata_append_data)204 PHP_FUNCTION(dom_characterdata_append_data)
205 {
206 	zval *id;
207 	xmlNode *nodep;
208 	dom_object *intern;
209 	char *arg;
210 	size_t arg_len;
211 
212 	id = ZEND_THIS;
213 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &arg, &arg_len) == FAILURE) {
214 		return;
215 	}
216 
217 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
218 	xmlTextConcat(nodep, (xmlChar *) arg, arg_len);
219 	RETURN_TRUE;
220 }
221 /* }}} end dom_characterdata_append_data */
222 
223 /* {{{ proto void dom_characterdata_insert_data(int offset, string arg);
224 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-3EDB695F
225 Since:
226 */
PHP_FUNCTION(dom_characterdata_insert_data)227 PHP_FUNCTION(dom_characterdata_insert_data)
228 {
229 	zval *id;
230 	xmlChar		*cur, *first, *second;
231 	xmlNodePtr  node;
232 	char		*arg;
233 	zend_long        offset;
234 	int         length;
235 	size_t arg_len;
236 	dom_object	*intern;
237 
238 	id = ZEND_THIS;
239 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ls", &offset, &arg, &arg_len) == FAILURE) {
240 		return;
241 	}
242 
243 	DOM_GET_OBJ(node, id, xmlNodePtr, intern);
244 
245 	cur = xmlNodeGetContent(node);
246 	if (cur == NULL) {
247 		RETURN_FALSE;
248 	}
249 
250 	length = xmlUTF8Strlen(cur);
251 
252 	if (offset < 0 || ZEND_LONG_INT_OVFL(offset) || offset > length) {
253 		xmlFree(cur);
254 		php_dom_throw_error(INDEX_SIZE_ERR, dom_get_strict_error(intern->document));
255 		RETURN_FALSE;
256 	}
257 
258 	first = xmlUTF8Strndup(cur, (int)offset);
259 	second = xmlUTF8Strsub(cur, (int)offset, length - (int)offset);
260 	xmlFree(cur);
261 
262 	xmlNodeSetContent(node, first);
263 	xmlNodeAddContent(node, (xmlChar *) arg);
264 	xmlNodeAddContent(node, second);
265 
266 	xmlFree(first);
267 	xmlFree(second);
268 
269 	RETURN_TRUE;
270 }
271 /* }}} end dom_characterdata_insert_data */
272 
273 /* {{{ proto void dom_characterdata_delete_data(int offset, int count);
274 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-7C603781
275 Since:
276 */
PHP_FUNCTION(dom_characterdata_delete_data)277 PHP_FUNCTION(dom_characterdata_delete_data)
278 {
279 	zval *id;
280 	xmlChar    *cur, *substring, *second;
281 	xmlNodePtr  node;
282 	zend_long        offset, count;
283 	int         length;
284 	dom_object	*intern;
285 
286 	id = ZEND_THIS;
287 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll", &offset, &count) == FAILURE) {
288 		return;
289 	}
290 
291 	DOM_GET_OBJ(node, id, xmlNodePtr, intern);
292 
293 	cur = xmlNodeGetContent(node);
294 	if (cur == NULL) {
295 		RETURN_FALSE;
296 	}
297 
298 	length = xmlUTF8Strlen(cur);
299 
300 	if (offset < 0 || count < 0 || ZEND_LONG_INT_OVFL(offset) || ZEND_LONG_INT_OVFL(count) || offset > length) {
301 		xmlFree(cur);
302 		php_dom_throw_error(INDEX_SIZE_ERR, dom_get_strict_error(intern->document));
303 		RETURN_FALSE;
304 	}
305 
306 	if (offset > 0) {
307 		substring = xmlUTF8Strsub(cur, 0, (int)offset);
308 	} else {
309 		substring = NULL;
310 	}
311 
312 	if ((offset + count) > length) {
313 		count = length - offset;
314 	}
315 
316 	second = xmlUTF8Strsub(cur, (int)offset + (int)count, length - (int)offset);
317 	substring = xmlStrcat(substring, second);
318 
319 	xmlNodeSetContent(node, substring);
320 
321 	xmlFree(cur);
322 	xmlFree(second);
323 	xmlFree(substring);
324 
325 	RETURN_TRUE;
326 }
327 /* }}} end dom_characterdata_delete_data */
328 
329 /* {{{ proto void dom_characterdata_replace_data(int offset, int count, string arg);
330 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-E5CBA7FB
331 Since:
332 */
PHP_FUNCTION(dom_characterdata_replace_data)333 PHP_FUNCTION(dom_characterdata_replace_data)
334 {
335 	zval *id;
336 	xmlChar		*cur, *substring, *second = NULL;
337 	xmlNodePtr  node;
338 	char		*arg;
339 	zend_long        offset, count;
340 	int         length;
341 	size_t arg_len;
342 	dom_object	*intern;
343 
344 	id = ZEND_THIS;
345 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "lls", &offset, &count, &arg, &arg_len) == FAILURE) {
346 		return;
347 	}
348 
349 	DOM_GET_OBJ(node, id, xmlNodePtr, intern);
350 
351 	cur = xmlNodeGetContent(node);
352 	if (cur == NULL) {
353 		RETURN_FALSE;
354 	}
355 
356 	length = xmlUTF8Strlen(cur);
357 
358 	if (offset < 0 || count < 0 || ZEND_LONG_INT_OVFL(offset) || ZEND_LONG_INT_OVFL(count) || offset > length) {
359 		xmlFree(cur);
360 		php_dom_throw_error(INDEX_SIZE_ERR, dom_get_strict_error(intern->document));
361 		RETURN_FALSE;
362 	}
363 
364 	if (offset > 0) {
365 		substring = xmlUTF8Strsub(cur, 0, (int)offset);
366 	} else {
367 		substring = NULL;
368 	}
369 
370 	if ((offset + count) > length) {
371 		count = length - offset;
372 	}
373 
374 	if (offset < length) {
375 		second = xmlUTF8Strsub(cur, (int)offset + count, length - (int)offset);
376 	}
377 
378 	substring = xmlStrcat(substring, (xmlChar *) arg);
379 	substring = xmlStrcat(substring, second);
380 
381 	xmlNodeSetContent(node, substring);
382 
383 	xmlFree(cur);
384 	if (second) {
385 		xmlFree(second);
386 	}
387 	xmlFree(substring);
388 
389 	RETURN_TRUE;
390 }
391 /* }}} end dom_characterdata_replace_data */
392 
393 #endif
394