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;
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
103int 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
136readonly=yes
137URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-7D61178C
138Since:
139*/
140int 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);
170URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-6531BCCF
171Since:
172*/
173PHP_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);
219URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-32791A2F
220Since:
221*/
222PHP_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);
253URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-3EDB695F
254Since:
255*/
256PHP_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);
301URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-7C603781
302Since:
303*/
304PHP_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);
356URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-E5CBA7FB
357Since:
358*/
359PHP_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