1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2017 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: Brad Lafountain <rodif_bl@yahoo.com> |
16 | Shane Caraveo <shane@caraveo.com> |
17 | Dmitry Stogov <dmitry@zend.com> |
18 +----------------------------------------------------------------------+
19 */
20 /* $Id$ */
21
22 #include "php_soap.h"
23 #include "ext/libxml/php_libxml.h"
24 #include "libxml/parser.h"
25 #include "libxml/parserInternals.h"
26
27 /* Channel libxml file io layer through the PHP streams subsystem.
28 * This allows use of ftps:// and https:// urls */
29
is_blank(const xmlChar * str)30 static int is_blank(const xmlChar* str)
31 {
32 while (*str != '\0') {
33 if (*str != ' ' && *str != 0x9 && *str != 0xa && *str != 0xd) {
34 return 0;
35 }
36 str++;
37 }
38 return 1;
39 }
40
41 /* removes all empty text, comments and other insignoficant nodes */
cleanup_xml_node(xmlNodePtr node)42 static void cleanup_xml_node(xmlNodePtr node)
43 {
44 xmlNodePtr trav;
45 xmlNodePtr del = NULL;
46
47 trav = node->children;
48 while (trav != NULL) {
49 if (del != NULL) {
50 xmlUnlinkNode(del);
51 xmlFreeNode(del);
52 del = NULL;
53 }
54 if (trav->type == XML_TEXT_NODE) {
55 if (is_blank(trav->content)) {
56 del = trav;
57 }
58 } else if ((trav->type != XML_ELEMENT_NODE) &&
59 (trav->type != XML_CDATA_SECTION_NODE)) {
60 del = trav;
61 } else if (trav->children != NULL) {
62 cleanup_xml_node(trav);
63 }
64 trav = trav->next;
65 }
66 if (del != NULL) {
67 xmlUnlinkNode(del);
68 xmlFreeNode(del);
69 }
70 }
71
soap_ignorableWhitespace(void * ctx,const xmlChar * ch,int len)72 static void soap_ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
73 {
74 }
75
soap_Comment(void * ctx,const xmlChar * value)76 static void soap_Comment(void *ctx, const xmlChar *value)
77 {
78 }
79
soap_xmlParseFile(const char * filename)80 xmlDocPtr soap_xmlParseFile(const char *filename)
81 {
82 xmlParserCtxtPtr ctxt = NULL;
83 xmlDocPtr ret;
84 zend_bool old_allow_url_fopen;
85
86 /*
87 xmlInitParser();
88 */
89
90 old_allow_url_fopen = PG(allow_url_fopen);
91 PG(allow_url_fopen) = 1;
92 ctxt = xmlCreateFileParserCtxt(filename);
93 PG(allow_url_fopen) = old_allow_url_fopen;
94 if (ctxt) {
95 zend_bool old;
96
97 ctxt->keepBlanks = 0;
98 ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
99 ctxt->sax->comment = soap_Comment;
100 ctxt->sax->warning = NULL;
101 ctxt->sax->error = NULL;
102 /*ctxt->sax->fatalError = NULL;*/
103 #if LIBXML_VERSION >= 20703
104 ctxt->options |= XML_PARSE_HUGE;
105 #endif
106 old = php_libxml_disable_entity_loader(1);
107 xmlParseDocument(ctxt);
108 php_libxml_disable_entity_loader(old);
109 if (ctxt->wellFormed) {
110 ret = ctxt->myDoc;
111 if (ret->URL == NULL && ctxt->directory != NULL) {
112 ret->URL = xmlCharStrdup(ctxt->directory);
113 }
114 } else {
115 ret = NULL;
116 xmlFreeDoc(ctxt->myDoc);
117 ctxt->myDoc = NULL;
118 }
119 xmlFreeParserCtxt(ctxt);
120 } else {
121 ret = NULL;
122 }
123
124 /*
125 xmlCleanupParser();
126 */
127
128 if (ret) {
129 cleanup_xml_node((xmlNodePtr)ret);
130 }
131 return ret;
132 }
133
soap_xmlParseMemory(const void * buf,size_t buf_size)134 xmlDocPtr soap_xmlParseMemory(const void *buf, size_t buf_size)
135 {
136 xmlParserCtxtPtr ctxt = NULL;
137 xmlDocPtr ret;
138
139
140 /*
141 xmlInitParser();
142 */
143 ctxt = xmlCreateMemoryParserCtxt(buf, buf_size);
144 if (ctxt) {
145 zend_bool old;
146
147 ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
148 ctxt->sax->comment = soap_Comment;
149 ctxt->sax->warning = NULL;
150 ctxt->sax->error = NULL;
151 /*ctxt->sax->fatalError = NULL;*/
152 #if LIBXML_VERSION >= 20703
153 ctxt->options |= XML_PARSE_HUGE;
154 #endif
155 old = php_libxml_disable_entity_loader(1);
156 xmlParseDocument(ctxt);
157 php_libxml_disable_entity_loader(old);
158 if (ctxt->wellFormed) {
159 ret = ctxt->myDoc;
160 if (ret->URL == NULL && ctxt->directory != NULL) {
161 ret->URL = xmlCharStrdup(ctxt->directory);
162 }
163 } else {
164 ret = NULL;
165 xmlFreeDoc(ctxt->myDoc);
166 ctxt->myDoc = NULL;
167 }
168 xmlFreeParserCtxt(ctxt);
169 } else {
170 ret = NULL;
171 }
172
173 /*
174 xmlCleanupParser();
175 */
176
177 /*
178 if (ret) {
179 cleanup_xml_node((xmlNodePtr)ret);
180 }
181 */
182 return ret;
183 }
184
attr_find_ns(xmlAttrPtr node)185 xmlNsPtr attr_find_ns(xmlAttrPtr node)
186 {
187 if (node->ns) {
188 return node->ns;
189 } else if (node->parent->ns) {
190 return node->parent->ns;
191 } else {
192 return xmlSearchNs(node->doc, node->parent, NULL);
193 }
194 }
195
node_find_ns(xmlNodePtr node)196 xmlNsPtr node_find_ns(xmlNodePtr node)
197 {
198 if (node->ns) {
199 return node->ns;
200 } else {
201 return xmlSearchNs(node->doc, node, NULL);
202 }
203 }
204
attr_is_equal_ex(xmlAttrPtr node,char * name,char * ns)205 int attr_is_equal_ex(xmlAttrPtr node, char *name, char *ns)
206 {
207 if (name == NULL || strcmp((char*)node->name, name) == 0) {
208 if (ns) {
209 xmlNsPtr nsPtr = attr_find_ns(node);
210 if (nsPtr) {
211 return (strcmp((char*)nsPtr->href, ns) == 0);
212 } else {
213 return FALSE;
214 }
215 }
216 return TRUE;
217 }
218 return FALSE;
219 }
220
node_is_equal_ex(xmlNodePtr node,char * name,char * ns)221 int node_is_equal_ex(xmlNodePtr node, char *name, char *ns)
222 {
223 if (name == NULL || strcmp((char*)node->name, name) == 0) {
224 if (ns) {
225 xmlNsPtr nsPtr = node_find_ns(node);
226 if (nsPtr) {
227 return (strcmp((char*)nsPtr->href, ns) == 0);
228 } else {
229 return FALSE;
230 }
231 }
232 return TRUE;
233 }
234 return FALSE;
235 }
236
237
get_attribute_ex(xmlAttrPtr node,char * name,char * ns)238 xmlAttrPtr get_attribute_ex(xmlAttrPtr node, char *name, char *ns)
239 {
240 while (node!=NULL) {
241 if (attr_is_equal_ex(node, name, ns)) {
242 return node;
243 }
244 node = node->next;
245 }
246 return NULL;
247 }
248
get_node_ex(xmlNodePtr node,char * name,char * ns)249 xmlNodePtr get_node_ex(xmlNodePtr node, char *name, char *ns)
250 {
251 while (node!=NULL) {
252 if (node_is_equal_ex(node, name, ns)) {
253 return node;
254 }
255 node = node->next;
256 }
257 return NULL;
258 }
259
get_node_recurisve_ex(xmlNodePtr node,char * name,char * ns)260 xmlNodePtr get_node_recurisve_ex(xmlNodePtr node, char *name, char *ns)
261 {
262 while (node != NULL) {
263 if (node_is_equal_ex(node, name, ns)) {
264 return node;
265 } else if (node->children != NULL) {
266 xmlNodePtr tmp = get_node_recurisve_ex(node->children, name, ns);
267 if (tmp) {
268 return tmp;
269 }
270 }
271 node = node->next;
272 }
273 return NULL;
274 }
275
get_node_with_attribute_ex(xmlNodePtr node,char * name,char * name_ns,char * attribute,char * value,char * attr_ns)276 xmlNodePtr get_node_with_attribute_ex(xmlNodePtr node, char *name, char *name_ns, char *attribute, char *value, char *attr_ns)
277 {
278 xmlAttrPtr attr;
279
280 while (node != NULL) {
281 if (name != NULL) {
282 node = get_node_ex(node, name, name_ns);
283 if (node==NULL) {
284 return NULL;
285 }
286 }
287
288 attr = get_attribute_ex(node->properties, attribute, attr_ns);
289 if (attr != NULL && strcmp((char*)attr->children->content, value) == 0) {
290 return node;
291 }
292 node = node->next;
293 }
294 return NULL;
295 }
296
get_node_with_attribute_recursive_ex(xmlNodePtr node,char * name,char * name_ns,char * attribute,char * value,char * attr_ns)297 xmlNodePtr get_node_with_attribute_recursive_ex(xmlNodePtr node, char *name, char *name_ns, char *attribute, char *value, char *attr_ns)
298 {
299 while (node != NULL) {
300 if (node_is_equal_ex(node, name, name_ns)) {
301 xmlAttrPtr attr = get_attribute_ex(node->properties, attribute, attr_ns);
302 if (attr != NULL && strcmp((char*)attr->children->content, value) == 0) {
303 return node;
304 }
305 }
306 if (node->children != NULL) {
307 xmlNodePtr tmp = get_node_with_attribute_recursive_ex(node->children, name, name_ns, attribute, value, attr_ns);
308 if (tmp) {
309 return tmp;
310 }
311 }
312 node = node->next;
313 }
314 return NULL;
315 }
316
parse_namespace(const xmlChar * inval,char ** value,char ** namespace)317 int parse_namespace(const xmlChar *inval, char **value, char **namespace)
318 {
319 char *found = strrchr((char*)inval, ':');
320
321 if (found != NULL && found != (char*)inval) {
322 (*namespace) = estrndup((char*)inval, found - (char*)inval);
323 (*value) = estrdup(++found);
324 } else {
325 (*value) = estrdup((char*)inval);
326 (*namespace) = NULL;
327 }
328
329 return FALSE;
330 }
331