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