xref: /PHP-5.6/ext/dom/characterdata.c (revision 49493a2d)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 5                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2016 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 TSRMLS_DC)79 int dom_characterdata_data_read(dom_object *obj, zval **retval TSRMLS_DC)
80 {
81 	xmlNodePtr nodep;
82 	xmlChar *content;
83 
84 	nodep = dom_object_get_node(obj);
85 
86 	if (nodep == NULL) {
87 		php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
88 		return FAILURE;
89 	}
90 
91 	ALLOC_ZVAL(*retval);
92 
93 	if ((content = xmlNodeGetContent(nodep)) != NULL) {
94 		ZVAL_STRING(*retval, content, 1);
95 		xmlFree(content);
96 	} else {
97 		ZVAL_EMPTY_STRING(*retval);
98 	}
99 
100 	return SUCCESS;
101 }
102 
dom_characterdata_data_write(dom_object * obj,zval * newval TSRMLS_DC)103 int dom_characterdata_data_write(dom_object *obj, zval *newval TSRMLS_DC)
104 {
105 	zval value_copy;
106 	xmlNode *nodep;
107 
108 	nodep = dom_object_get_node(obj);
109 
110 	if (nodep == NULL) {
111 		php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
112 		return FAILURE;
113 	}
114 
115 	convert_to_string_copy(newval, value_copy);
116 
117 	xmlNodeSetContentLen(nodep, Z_STRVAL_P(newval), Z_STRLEN_P(newval) + 1);
118 
119 	if (newval == &value_copy) {
120 		zval_dtor(newval);
121 	}
122 
123 	return SUCCESS;
124 }
125 
126 /* }}} */
127 
128 /* {{{ length	long
129 readonly=yes
130 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-7D61178C
131 Since:
132 */
dom_characterdata_length_read(dom_object * obj,zval ** retval TSRMLS_DC)133 int dom_characterdata_length_read(dom_object *obj, zval **retval TSRMLS_DC)
134 {
135 	xmlNodePtr nodep;
136 	xmlChar *content;
137 	long length = 0;
138 
139 	nodep = dom_object_get_node(obj);
140 
141 	if (nodep == NULL) {
142 		php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
143 		return FAILURE;
144 	}
145 
146 	ALLOC_ZVAL(*retval);
147 
148 	content = xmlNodeGetContent(nodep);
149 
150 	if (content) {
151 		length = xmlUTF8Strlen(content);
152 		xmlFree(content);
153 	}
154 
155 	ZVAL_LONG(*retval, length);
156 
157 	return SUCCESS;
158 }
159 
160 /* }}} */
161 
162 /* {{{ proto string dom_characterdata_substring_data(int offset, int count);
163 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-6531BCCF
164 Since:
165 */
PHP_FUNCTION(dom_characterdata_substring_data)166 PHP_FUNCTION(dom_characterdata_substring_data)
167 {
168 	zval       *id;
169 	xmlChar    *cur;
170 	xmlChar    *substring;
171 	xmlNodePtr  node;
172 	long        offset, count;
173 	int         length;
174 	dom_object	*intern;
175 
176 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oll", &id, dom_characterdata_class_entry, &offset, &count) == FAILURE) {
177 		return;
178 	}
179 
180 	DOM_GET_OBJ(node, id, xmlNodePtr, intern);
181 
182 	cur = xmlNodeGetContent(node);
183 	if (cur == NULL) {
184 		RETURN_FALSE;
185 	}
186 
187 	length = xmlUTF8Strlen(cur);
188 
189 	if (offset < 0 || count < 0 || offset > length) {
190 		xmlFree(cur);
191 		php_dom_throw_error(INDEX_SIZE_ERR, dom_get_strict_error(intern->document) TSRMLS_CC);
192 		RETURN_FALSE;
193 	}
194 
195 	if ((offset + count) > length) {
196 		count = length - offset;
197 	}
198 
199 	substring = xmlUTF8Strsub(cur, offset, count);
200 	xmlFree(cur);
201 
202 	if (substring) {
203 		RETVAL_STRING(substring, 1);
204 		xmlFree(substring);
205 	} else {
206 		RETVAL_EMPTY_STRING();
207 	}
208 }
209 /* }}} end dom_characterdata_substring_data */
210 
211 /* {{{ proto void dom_characterdata_append_data(string arg);
212 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-32791A2F
213 Since:
214 */
PHP_FUNCTION(dom_characterdata_append_data)215 PHP_FUNCTION(dom_characterdata_append_data)
216 {
217 	zval *id;
218 	xmlNode *nodep;
219 	dom_object *intern;
220 	char *arg;
221 	int arg_len;
222 
223 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &id, dom_characterdata_class_entry, &arg, &arg_len) == FAILURE) {
224 		return;
225 	}
226 
227 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
228 #if LIBXML_VERSION < 20627
229 /* Implement logic from libxml xmlTextConcat to add suport for comments and PI */
230     if ((nodep->content == (xmlChar *) &(nodep->properties)) ||
231         ((nodep->doc != NULL) && (nodep->doc->dict != NULL) &&
232 		xmlDictOwns(nodep->doc->dict, nodep->content))) {
233 	nodep->content = xmlStrncatNew(nodep->content, arg, arg_len);
234     } else {
235         nodep->content = xmlStrncat(nodep->content, arg, arg_len);
236     }
237     nodep->properties = NULL;
238 #else
239 	xmlTextConcat(nodep, arg, arg_len);
240 #endif
241 	RETURN_TRUE;
242 }
243 /* }}} end dom_characterdata_append_data */
244 
245 /* {{{ proto void dom_characterdata_insert_data(int offset, string arg);
246 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-3EDB695F
247 Since:
248 */
PHP_FUNCTION(dom_characterdata_insert_data)249 PHP_FUNCTION(dom_characterdata_insert_data)
250 {
251 	zval *id;
252 	xmlChar		*cur, *first, *second;
253 	xmlNodePtr  node;
254 	char		*arg;
255 	long        offset;
256 	int         length, arg_len;
257 	dom_object	*intern;
258 
259 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ols", &id, dom_characterdata_class_entry, &offset, &arg, &arg_len) == FAILURE) {
260 		return;
261 	}
262 
263 	DOM_GET_OBJ(node, id, xmlNodePtr, intern);
264 
265 	cur = xmlNodeGetContent(node);
266 	if (cur == NULL) {
267 		RETURN_FALSE;
268 	}
269 
270 	length = xmlUTF8Strlen(cur);
271 
272 	if (offset < 0 || offset > length) {
273 		xmlFree(cur);
274 		php_dom_throw_error(INDEX_SIZE_ERR, dom_get_strict_error(intern->document) TSRMLS_CC);
275 		RETURN_FALSE;
276 	}
277 
278 	first = xmlUTF8Strndup(cur, offset);
279 	second = xmlUTF8Strsub(cur, offset, length - offset);
280 	xmlFree(cur);
281 
282 	xmlNodeSetContent(node, first);
283 	xmlNodeAddContent(node, arg);
284 	xmlNodeAddContent(node, second);
285 
286 	xmlFree(first);
287 	xmlFree(second);
288 
289 	RETURN_TRUE;
290 }
291 /* }}} end dom_characterdata_insert_data */
292 
293 /* {{{ proto void dom_characterdata_delete_data(int offset, int count);
294 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-7C603781
295 Since:
296 */
PHP_FUNCTION(dom_characterdata_delete_data)297 PHP_FUNCTION(dom_characterdata_delete_data)
298 {
299 	zval *id;
300 	xmlChar    *cur, *substring, *second;
301 	xmlNodePtr  node;
302 	long        offset, count;
303 	int         length;
304 	dom_object	*intern;
305 
306 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oll", &id, dom_characterdata_class_entry, &offset, &count) == FAILURE) {
307 		return;
308 	}
309 
310 	DOM_GET_OBJ(node, id, xmlNodePtr, intern);
311 
312 	cur = xmlNodeGetContent(node);
313 	if (cur == NULL) {
314 		RETURN_FALSE;
315 	}
316 
317 	length = xmlUTF8Strlen(cur);
318 
319 	if (offset < 0 || count < 0 || offset > length) {
320 		xmlFree(cur);
321 		php_dom_throw_error(INDEX_SIZE_ERR, dom_get_strict_error(intern->document) TSRMLS_CC);
322 		RETURN_FALSE;
323 	}
324 
325 	if (offset > 0) {
326 		substring = xmlUTF8Strsub(cur, 0, offset);
327 	} else {
328 		substring = NULL;
329 	}
330 
331 	if ((offset + count) > length) {
332 		count = length - offset;
333 	}
334 
335 	second = xmlUTF8Strsub(cur, offset + count, length - offset);
336 	substring = xmlStrcat(substring, second);
337 
338 	xmlNodeSetContent(node, substring);
339 
340 	xmlFree(cur);
341 	xmlFree(second);
342 	xmlFree(substring);
343 
344 	RETURN_TRUE;
345 }
346 /* }}} end dom_characterdata_delete_data */
347 
348 /* {{{ proto void dom_characterdata_replace_data(int offset, int count, string arg);
349 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-E5CBA7FB
350 Since:
351 */
PHP_FUNCTION(dom_characterdata_replace_data)352 PHP_FUNCTION(dom_characterdata_replace_data)
353 {
354 	zval *id;
355 	xmlChar		*cur, *substring, *second = NULL;
356 	xmlNodePtr  node;
357 	char		*arg;
358 	long        offset, count;
359 	int         length, arg_len;
360 	dom_object	*intern;
361 
362 	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Olls", &id, dom_characterdata_class_entry, &offset, &count, &arg, &arg_len) == FAILURE) {
363 		return;
364 	}
365 
366 	DOM_GET_OBJ(node, id, xmlNodePtr, intern);
367 
368 	cur = xmlNodeGetContent(node);
369 	if (cur == NULL) {
370 		RETURN_FALSE;
371 	}
372 
373 	length = xmlUTF8Strlen(cur);
374 
375 	if (offset < 0 || count < 0 || offset > length) {
376 		xmlFree(cur);
377 		php_dom_throw_error(INDEX_SIZE_ERR, dom_get_strict_error(intern->document) TSRMLS_CC);
378 		RETURN_FALSE;
379 	}
380 
381 	if (offset > 0) {
382 		substring = xmlUTF8Strsub(cur, 0, offset);
383 	} else {
384 		substring = NULL;
385 	}
386 
387 	if ((offset + count) > length) {
388 		count = length - offset;
389 	}
390 
391 	if (offset < length) {
392 		second = xmlUTF8Strsub(cur, offset + count, length - offset);
393 	}
394 
395 	substring = xmlStrcat(substring, arg);
396 	substring = xmlStrcat(substring, second);
397 
398 	xmlNodeSetContent(node, substring);
399 
400 	xmlFree(cur);
401 	if (second) {
402 		xmlFree(second);
403 	}
404 	xmlFree(substring);
405 
406 	RETURN_TRUE;
407 }
408 /* }}} end dom_characterdata_replace_data */
409 
410 #endif
411 
412 /*
413  * Local variables:
414  * tab-width: 4
415  * c-basic-offset: 4
416  * End:
417  * vim600: noet sw=4 ts=4 fdm=marker
418  * vim<600: noet sw=4 ts=4
419  */
420