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 272374 2008-12-31 11:17: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 68843 : {
43 : xmlNodePtr trav;
44 68843 : xmlNodePtr del = NULL;
45 :
46 68843 : trav = node->children;
47 275249 : while (trav != NULL) {
48 137563 : if (del != NULL) {
49 2 : xmlUnlinkNode(del);
50 2 : xmlFreeNode(del);
51 2 : del = NULL;
52 : }
53 137563 : if (trav->type == XML_TEXT_NODE) {
54 434 : if (is_blank(trav->content)) {
55 212 : del = trav;
56 : }
57 137131 : } else if ((trav->type != XML_ELEMENT_NODE) &&
58 : (trav->type != XML_CDATA_SECTION_NODE)) {
59 2 : del = trav;
60 137127 : } else if (trav->children != NULL) {
61 68127 : cleanup_xml_node(trav);
62 : }
63 137563 : trav = trav->next;
64 : }
65 68843 : if (del != NULL) {
66 212 : xmlUnlinkNode(del);
67 212 : xmlFreeNode(del);
68 : }
69 68843 : }
70 :
71 : static void soap_ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
72 211365 : {
73 211365 : }
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 718 : {
81 718 : xmlParserCtxtPtr ctxt = NULL;
82 : xmlDocPtr ret;
83 : zend_bool old_allow_url_fopen;
84 :
85 : /*
86 : xmlInitParser();
87 : */
88 :
89 718 : old_allow_url_fopen = PG(allow_url_fopen);
90 718 : PG(allow_url_fopen) = 1;
91 718 : ctxt = xmlCreateFileParserCtxt(filename);
92 718 : PG(allow_url_fopen) = old_allow_url_fopen;
93 718 : if (ctxt) {
94 717 : ctxt->keepBlanks = 0;
95 717 : ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
96 717 : ctxt->sax->comment = soap_Comment;
97 717 : ctxt->sax->warning = NULL;
98 717 : ctxt->sax->error = NULL;
99 : /*ctxt->sax->fatalError = NULL;*/
100 717 : xmlParseDocument(ctxt);
101 717 : if (ctxt->wellFormed) {
102 716 : ret = ctxt->myDoc;
103 716 : 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 717 : xmlFreeParserCtxt(ctxt);
112 : } else {
113 1 : ret = NULL;
114 : }
115 :
116 : /*
117 : xmlCleanupParser();
118 : */
119 :
120 718 : if (ret) {
121 716 : cleanup_xml_node((xmlNodePtr)ret);
122 : }
123 718 : return ret;
124 : }
125 :
126 : xmlDocPtr soap_xmlParseMemory(const void *buf, size_t buf_size)
127 542 : {
128 542 : xmlParserCtxtPtr ctxt = NULL;
129 : xmlDocPtr ret;
130 :
131 : /*
132 : xmlInitParser();
133 : */
134 542 : ctxt = xmlCreateMemoryParserCtxt(buf, buf_size);
135 542 : if (ctxt) {
136 542 : ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
137 542 : ctxt->sax->comment = soap_Comment;
138 542 : ctxt->sax->warning = NULL;
139 542 : ctxt->sax->error = NULL;
140 : /*ctxt->sax->fatalError = NULL;*/
141 542 : xmlParseDocument(ctxt);
142 542 : if (ctxt->wellFormed) {
143 542 : ret = ctxt->myDoc;
144 542 : if (ret->URL == NULL && ctxt->directory != NULL) {
145 0 : ret->URL = xmlCharStrdup(ctxt->directory);
146 : }
147 : } else {
148 0 : ret = NULL;
149 0 : xmlFreeDoc(ctxt->myDoc);
150 0 : ctxt->myDoc = NULL;
151 : }
152 542 : 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 542 : 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 7358 : {
197 7358 : if (node->ns) {
198 4579 : return node->ns;
199 2779 : } else if (node->parent->ns) {
200 2779 : 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 156022 : {
208 156022 : if (node->ns) {
209 156022 : 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 741106 : {
217 741106 : if (name == NULL || strcmp((char*)node->name, name) == 0) {
218 271200 : if (ns) {
219 6317 : xmlNsPtr nsPtr = attr_find_ns(node);
220 6317 : if (nsPtr) {
221 6317 : return (strcmp((char*)nsPtr->href, ns) == 0);
222 : } else {
223 0 : return FALSE;
224 : }
225 : }
226 264883 : return TRUE;
227 : }
228 469906 : return FALSE;
229 : }
230 :
231 : int node_is_equal_ex(xmlNodePtr node, char *name, char *ns)
232 564285 : {
233 564285 : if (name == NULL || strcmp((char*)node->name, name) == 0) {
234 285722 : if (ns) {
235 156022 : xmlNsPtr nsPtr = node_find_ns(node);
236 156022 : if (nsPtr) {
237 156022 : return (strcmp((char*)nsPtr->href, ns) == 0);
238 : } else {
239 0 : return FALSE;
240 : }
241 : }
242 129700 : return TRUE;
243 : }
244 278563 : return FALSE;
245 : }
246 :
247 :
248 : xmlAttrPtr get_attribute_ex(xmlAttrPtr node, char *name, char *ns)
249 493491 : {
250 1435739 : while (node!=NULL) {
251 716958 : if (attr_is_equal_ex(node, name, ns)) {
252 268201 : return node;
253 : }
254 448757 : node = node->next;
255 : }
256 225290 : return NULL;
257 : }
258 :
259 : xmlNodePtr get_node_ex(xmlNodePtr node, char *name, char *ns)
260 114801 : {
261 267260 : while (node!=NULL) {
262 150832 : if (node_is_equal_ex(node, name, ns)) {
263 113174 : return node;
264 : }
265 37658 : 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 10418 : {
288 : xmlAttrPtr attr;
289 :
290 80956 : while (node != NULL) {
291 70538 : if (name != NULL) {
292 70538 : node = get_node_ex(node, name, name_ns);
293 70538 : if (node==NULL) {
294 34 : return NULL;
295 : }
296 : }
297 :
298 70504 : attr = get_attribute_ex(node->properties, attribute, attr_ns);
299 70504 : if (attr != NULL && strcmp((char*)attr->children->content, value) == 0) {
300 10384 : 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 36540 : {
329 36540 : char *found = strrchr((char*)inval, ':');
330 :
331 71643 : if (found != NULL && found != (char*)inval) {
332 35103 : (*namespace) = estrndup((char*)inval, found - (char*)inval);
333 35103 : (*value) = estrdup(++found);
334 : } else {
335 1437 : (*value) = estrdup((char*)inval);
336 1437 : (*namespace) = NULL;
337 : }
338 :
339 36540 : return FALSE;
340 : }
|