1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | http://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Christian Stocker <chregu@php.net> |
14 | Rob Richards <rrichards@php.net> |
15 +----------------------------------------------------------------------+
16 */
17
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include "php.h"
23 #if defined(HAVE_LIBXML) && defined(HAVE_DOM)
24 #include "php_dom.h"
25
26 /*
27 * class DOMImplementation
28 *
29 * URL: https://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-102161490
30 * Since:
31 */
32
33 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-5CED94D7
34 Since:
35 */
PHP_METHOD(DOMImplementation,hasFeature)36 PHP_METHOD(DOMImplementation, hasFeature)
37 {
38 size_t feature_len, version_len;
39 char *feature, *version;
40
41 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &feature, &feature_len, &version, &version_len) == FAILURE) {
42 RETURN_THROWS();
43 }
44
45 if (dom_has_feature(feature, version)) {
46 RETURN_TRUE;
47 } else {
48 RETURN_FALSE;
49 }
50 }
51 /* }}} end dom_domimplementation_has_feature */
52
53 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Level-2-Core-DOM-createDocType
54 Since: DOM Level 2
55 */
PHP_METHOD(DOMImplementation,createDocumentType)56 PHP_METHOD(DOMImplementation, createDocumentType)
57 {
58 xmlDtd *doctype;
59 int ret;
60 size_t name_len = 0, publicid_len = 0, systemid_len = 0;
61 char *name = NULL, *publicid = NULL, *systemid = NULL;
62 xmlChar *pch1 = NULL, *pch2 = NULL, *localname = NULL;
63 xmlURIPtr uri;
64
65 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|ss", &name, &name_len, &publicid, &publicid_len, &systemid, &systemid_len) == FAILURE) {
66 RETURN_THROWS();
67 }
68
69 if (name_len == 0) {
70 zend_argument_value_error(1, "cannot be empty");
71 RETURN_THROWS();
72 }
73
74 if (publicid_len > 0) {
75 pch1 = (xmlChar *) publicid;
76 }
77 if (systemid_len > 0) {
78 pch2 = (xmlChar *) systemid;
79 }
80
81 if (strstr(name, "%00")) {
82 php_error_docref(NULL, E_WARNING, "URI must not contain percent-encoded NUL bytes");
83 RETURN_FALSE;
84 }
85
86 uri = xmlParseURI(name);
87 if (uri != NULL && uri->opaque != NULL) {
88 localname = xmlStrdup((xmlChar *) uri->opaque);
89 if (xmlStrchr(localname, (xmlChar) ':') != NULL) {
90 php_dom_throw_error(NAMESPACE_ERR, 1);
91 xmlFreeURI(uri);
92 xmlFree(localname);
93 RETURN_FALSE;
94 }
95 } else {
96 localname = xmlStrdup((xmlChar *) name);
97 }
98
99 /* TODO: Test that localname has no invalid chars
100 php_dom_throw_error(INVALID_CHARACTER_ERR,);
101 */
102
103 if (uri) {
104 xmlFreeURI(uri);
105 }
106
107 doctype = xmlCreateIntSubset(NULL, localname, pch1, pch2);
108 xmlFree(localname);
109
110 if (doctype == NULL) {
111 php_error_docref(NULL, E_WARNING, "Unable to create DocumentType");
112 RETURN_FALSE;
113 }
114
115 DOM_RET_OBJ((xmlNodePtr) doctype, &ret, NULL);
116 }
117 /* }}} end dom_domimplementation_create_document_type */
118
119 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Level-2-Core-DOM-createDocument
120 Since: DOM Level 2
121 */
PHP_METHOD(DOMImplementation,createDocument)122 PHP_METHOD(DOMImplementation, createDocument)
123 {
124 zval *node = NULL;
125 xmlDoc *docp;
126 xmlNode *nodep;
127 xmlDtdPtr doctype = NULL;
128 xmlNsPtr nsptr = NULL;
129 int ret, errorcode = 0;
130 size_t uri_len = 0, name_len = 0;
131 char *uri = NULL, *name = NULL;
132 char *prefix = NULL, *localname = NULL;
133 dom_object *doctobj;
134
135 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!sO!", &uri, &uri_len, &name, &name_len, &node, dom_documenttype_class_entry) == FAILURE) {
136 RETURN_THROWS();
137 }
138
139 if (node != NULL) {
140 DOM_GET_OBJ(doctype, node, xmlDtdPtr, doctobj);
141 if (doctype->type == XML_DOCUMENT_TYPE_NODE) {
142 zend_argument_value_error(3, "is an invalid DocumentType object");
143 RETURN_THROWS();
144 }
145 if (doctype->doc != NULL) {
146 php_dom_throw_error(WRONG_DOCUMENT_ERR, 1);
147 RETURN_THROWS();
148 }
149 } else {
150 doctobj = NULL;
151 }
152
153 if (name_len > 0) {
154 errorcode = dom_check_qname(name, &localname, &prefix, 1, name_len);
155 if (errorcode == 0 && uri_len > 0
156 && ((nsptr = xmlNewNs(NULL, (xmlChar *) uri, (xmlChar *) prefix)) == NULL)
157 ) {
158 errorcode = NAMESPACE_ERR;
159 }
160 }
161
162 if (prefix != NULL) {
163 xmlFree(prefix);
164 }
165
166 if (errorcode != 0) {
167 if (localname != NULL) {
168 xmlFree(localname);
169 }
170 php_dom_throw_error(errorcode, 1);
171 RETURN_THROWS();
172 }
173
174 /* currently letting libxml2 set the version string */
175 docp = xmlNewDoc(NULL);
176 if (!docp) {
177 if (localname != NULL) {
178 xmlFree(localname);
179 }
180 RETURN_FALSE;
181 }
182
183 if (doctype != NULL) {
184 docp->intSubset = doctype;
185 doctype->parent = docp;
186 doctype->doc = docp;
187 docp->children = (xmlNodePtr) doctype;
188 docp->last = (xmlNodePtr) doctype;
189 }
190
191 if (localname != NULL) {
192 nodep = xmlNewDocNode(docp, nsptr, (xmlChar *) localname, NULL);
193 if (!nodep) {
194 if (doctype != NULL) {
195 docp->intSubset = NULL;
196 doctype->parent = NULL;
197 doctype->doc = NULL;
198 docp->children = NULL;
199 docp->last = NULL;
200 }
201 xmlFreeDoc(docp);
202 xmlFree(localname);
203 /* Need some better type of error here */
204 php_dom_throw_error(PHP_ERR, 1);
205 RETURN_THROWS();
206 }
207
208 nodep->nsDef = nsptr;
209
210 xmlDocSetRootElement(docp, nodep);
211 xmlFree(localname);
212 }
213
214 DOM_RET_OBJ((xmlNodePtr) docp, &ret, NULL);
215
216 if (doctobj != NULL) {
217 doctobj->document = ((dom_object *)((php_libxml_node_ptr *)docp->_private)->_private)->document;
218 php_libxml_increment_doc_ref((php_libxml_node_object *)doctobj, docp);
219 }
220 }
221 /* }}} end dom_domimplementation_create_document */
222
223 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#DOMImplementation3-getFeature
224 Since: DOM Level 3
225 */
PHP_METHOD(DOMImplementation,getFeature)226 PHP_METHOD(DOMImplementation, getFeature)
227 {
228 size_t feature_len, version_len;
229 char *feature, *version;
230
231 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &feature, &feature_len, &version, &version_len) == FAILURE) {
232 RETURN_THROWS();
233 }
234
235 DOM_NOT_IMPLEMENTED();
236 }
237 /* }}} end dom_domimplementation_get_feature */
238
239 #endif
240