1/*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2014 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 */
32ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_characterdata_substring_data, 0, 0, 2)
33    ZEND_ARG_INFO(0, offset)
34    ZEND_ARG_INFO(0, count)
35ZEND_END_ARG_INFO();
36
37ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_characterdata_append_data, 0, 0, 1)
38    ZEND_ARG_INFO(0, arg)
39ZEND_END_ARG_INFO();
40
41ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_characterdata_insert_data, 0, 0, 2)
42    ZEND_ARG_INFO(0, offset)
43    ZEND_ARG_INFO(0, arg)
44ZEND_END_ARG_INFO();
45
46ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_characterdata_delete_data, 0, 0, 2)
47    ZEND_ARG_INFO(0, offset)
48    ZEND_ARG_INFO(0, count)
49ZEND_END_ARG_INFO();
50
51ZEND_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)
55ZEND_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
65const 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
75readonly=no
76URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-72AB8359
77Since:
78*/
79int dom_characterdata_data_read(dom_object *obj, zval *retval TSRMLS_DC)
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 TSRMLS_CC);
86        return FAILURE;
87    }
88
89    if ((content = xmlNodeGetContent(nodep)) != NULL) {
90        ZVAL_STRING(retval, content);
91        xmlFree(content);
92    } else {
93        ZVAL_EMPTY_STRING(retval);
94    }
95
96    return SUCCESS;
97}
98
99int dom_characterdata_data_write(dom_object *obj, zval *newval TSRMLS_DC)
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 TSRMLS_CC);
106        return FAILURE;
107    }
108
109    str = zval_get_string(newval);
110
111    xmlNodeSetContentLen(nodep, str->val, str->len + 1);
112
113    STR_RELEASE(str);
114    return SUCCESS;
115}
116
117/* }}} */
118
119/* {{{ length   long
120readonly=yes
121URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-7D61178C
122Since:
123*/
124int dom_characterdata_length_read(dom_object *obj, zval *retval TSRMLS_DC)
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 TSRMLS_CC);
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);
150URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-6531BCCF
151Since:
152*/
153PHP_FUNCTION(dom_characterdata_substring_data)
154{
155    zval       *id;
156    xmlChar    *cur;
157    xmlChar    *substring;
158    xmlNodePtr  node;
159    long        offset, count;
160    int         length;
161    dom_object  *intern;
162
163    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 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 || offset > length) {
177        xmlFree(cur);
178        php_dom_throw_error(INDEX_SIZE_ERR, dom_get_strict_error(intern->document) TSRMLS_CC);
179        RETURN_FALSE;
180    }
181
182    if ((offset + count) > length) {
183        count = length - offset;
184    }
185
186    substring = xmlUTF8Strsub(cur, offset, count);
187    xmlFree(cur);
188
189    if (substring) {
190        RETVAL_STRING(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);
199URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-32791A2F
200Since:
201*/
202PHP_FUNCTION(dom_characterdata_append_data)
203{
204    zval *id;
205    xmlNode *nodep;
206    dom_object *intern;
207    char *arg;
208    int arg_len;
209
210    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 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, 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);
233URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-3EDB695F
234Since:
235*/
236PHP_FUNCTION(dom_characterdata_insert_data)
237{
238    zval *id;
239    xmlChar     *cur, *first, *second;
240    xmlNodePtr  node;
241    char        *arg;
242    long        offset;
243    int         length, arg_len;
244    dom_object  *intern;
245
246    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ols", &id, dom_characterdata_class_entry, &offset, &arg, &arg_len) == FAILURE) {
247        return;
248    }
249
250    DOM_GET_OBJ(node, id, xmlNodePtr, intern);
251
252    cur = xmlNodeGetContent(node);
253    if (cur == NULL) {
254        RETURN_FALSE;
255    }
256
257    length = xmlUTF8Strlen(cur);
258
259    if (offset < 0 || offset > length) {
260        xmlFree(cur);
261        php_dom_throw_error(INDEX_SIZE_ERR, dom_get_strict_error(intern->document) TSRMLS_CC);
262        RETURN_FALSE;
263    }
264
265    first = xmlUTF8Strndup(cur, offset);
266    second = xmlUTF8Strsub(cur, offset, length - offset);
267    xmlFree(cur);
268
269    xmlNodeSetContent(node, first);
270    xmlNodeAddContent(node, arg);
271    xmlNodeAddContent(node, second);
272
273    xmlFree(first);
274    xmlFree(second);
275
276    RETURN_TRUE;
277}
278/* }}} end dom_characterdata_insert_data */
279
280/* {{{ proto void dom_characterdata_delete_data(int offset, int count);
281URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-7C603781
282Since:
283*/
284PHP_FUNCTION(dom_characterdata_delete_data)
285{
286    zval *id;
287    xmlChar    *cur, *substring, *second;
288    xmlNodePtr  node;
289    long        offset, count;
290    int         length;
291    dom_object  *intern;
292
293    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oll", &id, dom_characterdata_class_entry, &offset, &count) == FAILURE) {
294        return;
295    }
296
297    DOM_GET_OBJ(node, id, xmlNodePtr, intern);
298
299    cur = xmlNodeGetContent(node);
300    if (cur == NULL) {
301        RETURN_FALSE;
302    }
303
304    length = xmlUTF8Strlen(cur);
305
306    if (offset < 0 || count < 0 || offset > length) {
307        xmlFree(cur);
308        php_dom_throw_error(INDEX_SIZE_ERR, dom_get_strict_error(intern->document) TSRMLS_CC);
309        RETURN_FALSE;
310    }
311
312    if (offset > 0) {
313        substring = xmlUTF8Strsub(cur, 0, offset);
314    } else {
315        substring = NULL;
316    }
317
318    if ((offset + count) > length) {
319        count = length - offset;
320    }
321
322    second = xmlUTF8Strsub(cur, offset + count, length - offset);
323    substring = xmlStrcat(substring, second);
324
325    xmlNodeSetContent(node, substring);
326
327    xmlFree(cur);
328    xmlFree(second);
329    xmlFree(substring);
330
331    RETURN_TRUE;
332}
333/* }}} end dom_characterdata_delete_data */
334
335/* {{{ proto void dom_characterdata_replace_data(int offset, int count, string arg);
336URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-E5CBA7FB
337Since:
338*/
339PHP_FUNCTION(dom_characterdata_replace_data)
340{
341    zval *id;
342    xmlChar     *cur, *substring, *second = NULL;
343    xmlNodePtr  node;
344    char        *arg;
345    long        offset, count;
346    int         length, arg_len;
347    dom_object  *intern;
348
349    if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, 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 || offset > length) {
363        xmlFree(cur);
364        php_dom_throw_error(INDEX_SIZE_ERR, dom_get_strict_error(intern->document) TSRMLS_CC);
365        RETURN_FALSE;
366    }
367
368    if (offset > 0) {
369        substring = xmlUTF8Strsub(cur, 0, 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, offset + count, length - offset);
380    }
381
382    substring = xmlStrcat(substring, 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