1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 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: php_xml.c 272370 2008-12-31 11:15:49Z sebastian $ */
21 :
22 : #include "php_soap.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 :
29 : static int is_blank(const xmlChar* str)
30 434 : {
31 1624 : while (*str != '\0') {
32 978 : if (*str != ' ' && *str != 0x9 && *str != 0xa && *str != 0xd) {
33 222 : return 0;
34 : }
35 756 : str++;
36 : }
37 212 : return 1;
38 : }
39 :
40 : /* removes all empty text, comments and other insignoficant nodes */
41 : static void cleanup_xml_node(xmlNodePtr node)
42 68877 : {
43 : xmlNodePtr trav;
44 68877 : xmlNodePtr del = NULL;
45 :
46 68877 : trav = node->children;
47 275371 : while (trav != NULL) {
48 137617 : if (del != NULL) {
49 2 : xmlUnlinkNode(del);
50 2 : xmlFreeNode(del);
51 2 : del = NULL;
52 : }
53 137617 : if (trav->type == XML_TEXT_NODE) {
54 434 : if (is_blank(trav->content)) {
55 212 : del = trav;
56 : }
57 137185 : } else if ((trav->type != XML_ELEMENT_NODE) &&
58 : (trav->type != XML_CDATA_SECTION_NODE)) {
59 2 : del = trav;
60 137181 : } else if (trav->children != NULL) {
61 68159 : cleanup_xml_node(trav);
62 : }
63 137617 : trav = trav->next;
64 : }
65 68877 : if (del != NULL) {
66 212 : xmlUnlinkNode(del);
67 212 : xmlFreeNode(del);
68 : }
69 68877 : }
70 :
71 : static void soap_ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
72 211457 : {
73 211457 : }
74 :
75 : static void soap_Comment(void *ctx, const xmlChar *value)
76 6210 : {
77 6210 : }
78 :
79 : xmlDocPtr soap_xmlParseFile(const char *filename TSRMLS_DC)
80 720 : {
81 720 : xmlParserCtxtPtr ctxt = NULL;
82 : xmlDocPtr ret;
83 : zend_bool old_allow_url_fopen;
84 :
85 : /*
86 : xmlInitParser();
87 : */
88 :
89 720 : old_allow_url_fopen = PG(allow_url_fopen);
90 720 : PG(allow_url_fopen) = 1;
91 720 : ctxt = xmlCreateFileParserCtxt(filename);
92 720 : PG(allow_url_fopen) = old_allow_url_fopen;
93 720 : if (ctxt) {
94 719 : ctxt->keepBlanks = 0;
95 719 : ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
96 719 : ctxt->sax->comment = soap_Comment;
97 719 : ctxt->sax->warning = NULL;
98 719 : ctxt->sax->error = NULL;
99 : /*ctxt->sax->fatalError = NULL;*/
100 719 : xmlParseDocument(ctxt);
101 719 : if (ctxt->wellFormed) {
102 718 : ret = ctxt->myDoc;
103 718 : if (ret->URL == NULL && ctxt->directory != NULL) {
104 0 : ret->URL = xmlCharStrdup(ctxt->directory);
105 : }
106 : } else {
107 1 : ret = NULL;
108 1 : xmlFreeDoc(ctxt->myDoc);
109 1 : ctxt->myDoc = NULL;
110 : }
111 719 : xmlFreeParserCtxt(ctxt);
112 : } else {
113 1 : ret = NULL;
114 : }
115 :
116 : /*
117 : xmlCleanupParser();
118 : */
119 :
120 720 : if (ret) {
121 718 : cleanup_xml_node((xmlNodePtr)ret);
122 : }
123 720 : return ret;
124 : }
125 :
126 : xmlDocPtr soap_xmlParseMemory(const void *buf, size_t buf_size)
127 545 : {
128 545 : xmlParserCtxtPtr ctxt = NULL;
129 : xmlDocPtr ret;
130 :
131 : /*
132 : xmlInitParser();
133 : */
134 545 : ctxt = xmlCreateMemoryParserCtxt(buf, buf_size);
135 545 : if (ctxt) {
136 545 : ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
137 545 : ctxt->sax->comment = soap_Comment;
138 545 : ctxt->sax->warning = NULL;
139 545 : ctxt->sax->error = NULL;
140 : /*ctxt->sax->fatalError = NULL;*/
141 545 : xmlParseDocument(ctxt);
142 545 : if (ctxt->wellFormed) {
143 544 : ret = ctxt->myDoc;
144 544 : if (ret->URL == NULL && ctxt->directory != NULL) {
145 0 : ret->URL = xmlCharStrdup(ctxt->directory);
146 : }
147 : } else {
148 1 : ret = NULL;
149 1 : xmlFreeDoc(ctxt->myDoc);
150 1 : ctxt->myDoc = NULL;
151 : }
152 545 : xmlFreeParserCtxt(ctxt);
153 : } else {
154 0 : ret = NULL;
155 : }
156 :
157 : /*
158 : xmlCleanupParser();
159 : */
160 :
161 : /*
162 : if (ret) {
163 : cleanup_xml_node((xmlNodePtr)ret);
164 : }
165 : */
166 545 : return ret;
167 : }
168 :
169 : #ifndef ZEND_ENGINE_2
170 : int php_stream_xmlIO_match_wrapper(const char *filename)
171 : {
172 : TSRMLS_FETCH();
173 : return php_stream_locate_url_wrapper(filename, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ? 1 : 0;
174 : }
175 :
176 : void *php_stream_xmlIO_open_wrapper(const char *filename)
177 : {
178 : TSRMLS_FETCH();
179 : return php_stream_open_wrapper((char*)filename, "rb", ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
180 : }
181 :
182 : int php_stream_xmlIO_read(void *context, char *buffer, int len)
183 : {
184 : TSRMLS_FETCH();
185 : return php_stream_read((php_stream*)context, buffer, len);
186 : }
187 :
188 : int php_stream_xmlIO_close(void *context)
189 : {
190 : TSRMLS_FETCH();
191 : return php_stream_close((php_stream*)context);
192 : }
193 : #endif
194 :
195 : xmlNsPtr attr_find_ns(xmlAttrPtr node)
196 7361 : {
197 7361 : if (node->ns) {
198 4580 : return node->ns;
199 2781 : } else if (node->parent->ns) {
200 2781 : return node->parent->ns;
201 : } else {
202 0 : return xmlSearchNs(node->doc, node->parent, NULL);
203 : }
204 : }
205 :
206 : xmlNsPtr node_find_ns(xmlNodePtr node)
207 156054 : {
208 156054 : if (node->ns) {
209 156054 : return node->ns;
210 : } else {
211 0 : return xmlSearchNs(node->doc, node, NULL);
212 : }
213 : }
214 :
215 : int attr_is_equal_ex(xmlAttrPtr node, char *name, char *ns)
216 741265 : {
217 741265 : if (name == NULL || strcmp((char*)node->name, name) == 0) {
218 271259 : if (ns) {
219 6318 : xmlNsPtr nsPtr = attr_find_ns(node);
220 6318 : if (nsPtr) {
221 6318 : return (strcmp((char*)nsPtr->href, ns) == 0);
222 : } else {
223 0 : return FALSE;
224 : }
225 : }
226 264941 : return TRUE;
227 : }
228 470006 : return FALSE;
229 : }
230 :
231 : int node_is_equal_ex(xmlNodePtr node, char *name, char *ns)
232 564469 : {
233 564469 : if (name == NULL || strcmp((char*)node->name, name) == 0) {
234 285792 : if (ns) {
235 156054 : xmlNsPtr nsPtr = node_find_ns(node);
236 156054 : if (nsPtr) {
237 156054 : return (strcmp((char*)nsPtr->href, ns) == 0);
238 : } else {
239 0 : return FALSE;
240 : }
241 : }
242 129738 : return TRUE;
243 : }
244 278677 : return FALSE;
245 : }
246 :
247 :
248 : xmlAttrPtr get_attribute_ex(xmlAttrPtr node, char *name, char *ns)
249 493585 : {
250 1436001 : while (node!=NULL) {
251 717087 : if (attr_is_equal_ex(node, name, ns)) {
252 268256 : return node;
253 : }
254 448831 : node = node->next;
255 : }
256 225329 : return NULL;
257 : }
258 :
259 : xmlNodePtr get_node_ex(xmlNodePtr node, char *name, char *ns)
260 114817 : {
261 267300 : while (node!=NULL) {
262 150856 : if (node_is_equal_ex(node, name, ns)) {
263 113190 : return node;
264 : }
265 37666 : node = node->next;
266 : }
267 1627 : return NULL;
268 : }
269 :
270 : xmlNodePtr get_node_recurisve_ex(xmlNodePtr node, char *name, char *ns)
271 0 : {
272 0 : while (node != NULL) {
273 0 : if (node_is_equal_ex(node, name, ns)) {
274 0 : return node;
275 0 : } else if (node->children != NULL) {
276 0 : xmlNodePtr tmp = get_node_recurisve_ex(node->children, name, ns);
277 0 : if (tmp) {
278 0 : return tmp;
279 : }
280 : }
281 0 : node = node->next;
282 : }
283 0 : return NULL;
284 : }
285 :
286 : xmlNodePtr get_node_with_attribute_ex(xmlNodePtr node, char *name, char *name_ns, char *attribute, char *value, char *attr_ns)
287 10420 : {
288 : xmlAttrPtr attr;
289 :
290 80960 : while (node != NULL) {
291 70540 : if (name != NULL) {
292 70540 : node = get_node_ex(node, name, name_ns);
293 70540 : if (node==NULL) {
294 34 : return NULL;
295 : }
296 : }
297 :
298 70506 : attr = get_attribute_ex(node->properties, attribute, attr_ns);
299 70506 : if (attr != NULL && strcmp((char*)attr->children->content, value) == 0) {
300 10386 : return node;
301 : }
302 60120 : node = node->next;
303 : }
304 0 : return NULL;
305 : }
306 :
307 : xmlNodePtr get_node_with_attribute_recursive_ex(xmlNodePtr node, char *name, char *name_ns, char *attribute, char *value, char *attr_ns)
308 18957 : {
309 70230 : while (node != NULL) {
310 32986 : if (node_is_equal_ex(node, name, name_ns)) {
311 32986 : xmlAttrPtr attr = get_attribute_ex(node->properties, attribute, attr_ns);
312 32986 : if (attr != NULL && strcmp((char*)attr->children->content, value) == 0) {
313 221 : return node;
314 : }
315 : }
316 32765 : if (node->children != NULL) {
317 18735 : xmlNodePtr tmp = get_node_with_attribute_recursive_ex(node->children, name, name_ns, attribute, value, attr_ns);
318 18735 : if (tmp) {
319 449 : return tmp;
320 : }
321 : }
322 32316 : node = node->next;
323 : }
324 18287 : return NULL;
325 : }
326 :
327 : int parse_namespace(const xmlChar *inval, char **value, char **namespace)
328 36550 : {
329 36550 : char *found = strrchr((char*)inval, ':');
330 :
331 71661 : if (found != NULL && found != (char*)inval) {
332 35111 : (*namespace) = estrndup((char*)inval, found - (char*)inval);
333 35111 : (*value) = estrdup(++found);
334 : } else {
335 1439 : (*value) = estrdup((char*)inval);
336 1439 : (*namespace) = NULL;
337 : }
338 :
339 36550 : return FALSE;
340 : }
|