1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 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 ctxt->options |= XML_PARSE_HUGE;
103 old = php_libxml_disable_entity_loader(1);
104 xmlParseDocument(ctxt);
105 php_libxml_disable_entity_loader(old);
106 if (ctxt->wellFormed) {
107 ret = ctxt->myDoc;
108 if (ret->URL == NULL && ctxt->directory != NULL) {
109 ret->URL = xmlCharStrdup(ctxt->directory);
110 }
111 } else {
112 ret = NULL;
113 xmlFreeDoc(ctxt->myDoc);
114 ctxt->myDoc = NULL;
115 }
116 xmlFreeParserCtxt(ctxt);
117 } else {
118 ret = NULL;
119 }
120
121 /*
122 xmlCleanupParser();
123 */
124
125 if (ret) {
126 cleanup_xml_node((xmlNodePtr)ret);
127 }
128 return ret;
129 }
130
soap_xmlParseMemory(const void * buf,size_t buf_size)131 xmlDocPtr soap_xmlParseMemory(const void *buf, size_t buf_size)
132 {
133 xmlParserCtxtPtr ctxt = NULL;
134 xmlDocPtr ret;
135
136
137 /*
138 xmlInitParser();
139 */
140 ctxt = xmlCreateMemoryParserCtxt(buf, buf_size);
141 if (ctxt) {
142 zend_bool old;
143
144 ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
145 ctxt->sax->comment = soap_Comment;
146 ctxt->sax->warning = NULL;
147 ctxt->sax->error = NULL;
148 /*ctxt->sax->fatalError = NULL;*/
149 ctxt->options |= XML_PARSE_HUGE;
150 old = php_libxml_disable_entity_loader(1);
151 xmlParseDocument(ctxt);
152 php_libxml_disable_entity_loader(old);
153 if (ctxt->wellFormed) {
154 ret = ctxt->myDoc;
155 if (ret->URL == NULL && ctxt->directory != NULL) {
156 ret->URL = xmlCharStrdup(ctxt->directory);
157 }
158 } else {
159 ret = NULL;
160 xmlFreeDoc(ctxt->myDoc);
161 ctxt->myDoc = NULL;
162 }
163 xmlFreeParserCtxt(ctxt);
164 } else {
165 ret = NULL;
166 }
167
168 /*
169 xmlCleanupParser();
170 */
171
172 /*
173 if (ret) {
174 cleanup_xml_node((xmlNodePtr)ret);
175 }
176 */
177 return ret;
178 }
179
attr_find_ns(xmlAttrPtr node)180 xmlNsPtr attr_find_ns(xmlAttrPtr node)
181 {
182 if (node->ns) {
183 return node->ns;
184 } else if (node->parent->ns) {
185 return node->parent->ns;
186 } else {
187 return xmlSearchNs(node->doc, node->parent, NULL);
188 }
189 }
190
node_find_ns(xmlNodePtr node)191 xmlNsPtr node_find_ns(xmlNodePtr node)
192 {
193 if (node->ns) {
194 return node->ns;
195 } else {
196 return xmlSearchNs(node->doc, node, NULL);
197 }
198 }
199
attr_is_equal_ex(xmlAttrPtr node,char * name,char * ns)200 int attr_is_equal_ex(xmlAttrPtr node, char *name, char *ns)
201 {
202 if (name == NULL || ((node->name) && strcmp((char*)node->name, name) == 0)) {
203 if (ns) {
204 xmlNsPtr nsPtr = attr_find_ns(node);
205 if (nsPtr) {
206 return (strcmp((char*)nsPtr->href, ns) == 0);
207 } else {
208 return FALSE;
209 }
210 }
211 return TRUE;
212 }
213 return FALSE;
214 }
215
node_is_equal_ex(xmlNodePtr node,char * name,char * ns)216 int node_is_equal_ex(xmlNodePtr node, char *name, char *ns)
217 {
218 if (name == NULL || ((node->name) && strcmp((char*)node->name, name) == 0)) {
219 if (ns) {
220 xmlNsPtr nsPtr = node_find_ns(node);
221 if (nsPtr) {
222 return (strcmp((char*)nsPtr->href, ns) == 0);
223 } else {
224 return FALSE;
225 }
226 }
227 return TRUE;
228 }
229 return FALSE;
230 }
231
232
get_attribute_ex(xmlAttrPtr node,char * name,char * ns)233 xmlAttrPtr get_attribute_ex(xmlAttrPtr node, char *name, char *ns)
234 {
235 while (node!=NULL) {
236 if (attr_is_equal_ex(node, name, ns)) {
237 return node;
238 }
239 node = node->next;
240 }
241 return NULL;
242 }
243
get_node_ex(xmlNodePtr node,char * name,char * ns)244 xmlNodePtr get_node_ex(xmlNodePtr node, char *name, char *ns)
245 {
246 while (node!=NULL) {
247 if (node_is_equal_ex(node, name, ns)) {
248 return node;
249 }
250 node = node->next;
251 }
252 return NULL;
253 }
254
get_node_recurisve_ex(xmlNodePtr node,char * name,char * ns)255 xmlNodePtr get_node_recurisve_ex(xmlNodePtr node, char *name, char *ns)
256 {
257 while (node != NULL) {
258 if (node_is_equal_ex(node, name, ns)) {
259 return node;
260 } else if (node->children != NULL) {
261 xmlNodePtr tmp = get_node_recurisve_ex(node->children, name, ns);
262 if (tmp) {
263 return tmp;
264 }
265 }
266 node = node->next;
267 }
268 return NULL;
269 }
270
get_node_with_attribute_ex(xmlNodePtr node,char * name,char * name_ns,char * attribute,char * value,char * attr_ns)271 xmlNodePtr get_node_with_attribute_ex(xmlNodePtr node, char *name, char *name_ns, char *attribute, char *value, char *attr_ns)
272 {
273 xmlAttrPtr attr;
274
275 while (node != NULL) {
276 if (name != NULL) {
277 node = get_node_ex(node, name, name_ns);
278 if (node==NULL) {
279 return NULL;
280 }
281 }
282
283 attr = get_attribute_ex(node->properties, attribute, attr_ns);
284 if (attr != NULL && strcmp((char*)attr->children->content, value) == 0) {
285 return node;
286 }
287 node = node->next;
288 }
289 return NULL;
290 }
291
get_node_with_attribute_recursive_ex(xmlNodePtr node,char * name,char * name_ns,char * attribute,char * value,char * attr_ns)292 xmlNodePtr get_node_with_attribute_recursive_ex(xmlNodePtr node, char *name, char *name_ns, char *attribute, char *value, char *attr_ns)
293 {
294 while (node != NULL) {
295 if (node_is_equal_ex(node, name, name_ns)) {
296 xmlAttrPtr attr = get_attribute_ex(node->properties, attribute, attr_ns);
297 if (attr != NULL && strcmp((char*)attr->children->content, value) == 0) {
298 return node;
299 }
300 }
301 if (node->children != NULL) {
302 xmlNodePtr tmp = get_node_with_attribute_recursive_ex(node->children, name, name_ns, attribute, value, attr_ns);
303 if (tmp) {
304 return tmp;
305 }
306 }
307 node = node->next;
308 }
309 return NULL;
310 }
311
parse_namespace(const xmlChar * inval,char ** value,char ** namespace)312 int parse_namespace(const xmlChar *inval, char **value, char **namespace)
313 {
314 char *found = strrchr((char*)inval, ':');
315
316 if (found != NULL && found != (char*)inval) {
317 (*namespace) = estrndup((char*)inval, found - (char*)inval);
318 (*value) = estrdup(++found);
319 } else {
320 (*value) = estrdup((char*)inval);
321 (*namespace) = NULL;
322 }
323
324 return FALSE;
325 }
326