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: Brad Lafountain <rodif_bl@yahoo.com> |
14 | Shane Caraveo <shane@caraveo.com> |
15 | Dmitry Stogov <dmitry@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 #include "php_soap.h"
20 #include "ext/libxml/php_libxml.h"
21 #include "libxml/parser.h"
22 #include "libxml/parserInternals.h"
23
24 /* Channel libxml file io layer through the PHP streams subsystem.
25 * This allows use of ftps:// and https:// urls */
26
is_blank(const xmlChar * str)27 static int is_blank(const xmlChar* str)
28 {
29 while (*str != '\0') {
30 if (*str != ' ' && *str != 0x9 && *str != 0xa && *str != 0xd) {
31 return 0;
32 }
33 str++;
34 }
35 return 1;
36 }
37
38 /* removes all empty text, comments and other insignoficant nodes */
cleanup_xml_node(xmlNodePtr node)39 static void cleanup_xml_node(xmlNodePtr node)
40 {
41 xmlNodePtr trav;
42 xmlNodePtr del = NULL;
43
44 trav = node->children;
45 while (trav != NULL) {
46 if (del != NULL) {
47 xmlUnlinkNode(del);
48 xmlFreeNode(del);
49 del = NULL;
50 }
51 if (trav->type == XML_TEXT_NODE) {
52 if (is_blank(trav->content)) {
53 del = trav;
54 }
55 } else if ((trav->type != XML_ELEMENT_NODE) &&
56 (trav->type != XML_CDATA_SECTION_NODE)) {
57 del = trav;
58 } else if (trav->children != NULL) {
59 cleanup_xml_node(trav);
60 }
61 trav = trav->next;
62 }
63 if (del != NULL) {
64 xmlUnlinkNode(del);
65 xmlFreeNode(del);
66 }
67 }
68
soap_ignorableWhitespace(void * ctx,const xmlChar * ch,int len)69 static void soap_ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
70 {
71 }
72
soap_Comment(void * ctx,const xmlChar * value)73 static void soap_Comment(void *ctx, const xmlChar *value)
74 {
75 }
76
soap_xmlParseFile(const char * filename)77 xmlDocPtr soap_xmlParseFile(const char *filename)
78 {
79 xmlParserCtxtPtr ctxt = NULL;
80 xmlDocPtr ret;
81 zend_bool old_allow_url_fopen;
82
83 /*
84 xmlInitParser();
85 */
86
87 old_allow_url_fopen = PG(allow_url_fopen);
88 PG(allow_url_fopen) = 1;
89 ctxt = xmlCreateFileParserCtxt(filename);
90 PG(allow_url_fopen) = old_allow_url_fopen;
91 if (ctxt) {
92 zend_bool old;
93
94 php_libxml_sanitize_parse_ctxt_options(ctxt);
95 ctxt->keepBlanks = 0;
96 ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
97 ctxt->sax->comment = soap_Comment;
98 ctxt->sax->warning = NULL;
99 ctxt->sax->error = NULL;
100 /*ctxt->sax->fatalError = NULL;*/
101 ctxt->options |= XML_PARSE_HUGE;
102 old = php_libxml_disable_entity_loader(1);
103 xmlParseDocument(ctxt);
104 php_libxml_disable_entity_loader(old);
105 if (ctxt->wellFormed) {
106 ret = ctxt->myDoc;
107 if (ret->URL == NULL && ctxt->directory != NULL) {
108 ret->URL = xmlCharStrdup(ctxt->directory);
109 }
110 } else {
111 ret = NULL;
112 xmlFreeDoc(ctxt->myDoc);
113 ctxt->myDoc = NULL;
114 }
115 xmlFreeParserCtxt(ctxt);
116 } else {
117 ret = NULL;
118 }
119
120 /*
121 xmlCleanupParser();
122 */
123
124 if (ret) {
125 cleanup_xml_node((xmlNodePtr)ret);
126 }
127 return ret;
128 }
129
soap_xmlParseMemory(const void * buf,size_t buf_size)130 xmlDocPtr soap_xmlParseMemory(const void *buf, size_t buf_size)
131 {
132 xmlParserCtxtPtr ctxt = NULL;
133 xmlDocPtr ret;
134
135
136 /*
137 xmlInitParser();
138 */
139 ctxt = xmlCreateMemoryParserCtxt(buf, buf_size);
140 if (ctxt) {
141 zend_bool old;
142
143 php_libxml_sanitize_parse_ctxt_options(ctxt);
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