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