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