1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 6 |
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 276986 2009-03-10 23:40:06Z helly $ */
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 432 : {
31 1620 : while (*str != '\0') {
32 976 : if (*str != ' ' && *str != 0x9 && *str != 0xa && *str != 0xd) {
33 220 : 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 68067 : {
43 : xmlNodePtr trav;
44 68067 : xmlNodePtr del = NULL;
45 :
46 68067 : trav = node->children;
47 272249 : while (trav != NULL) {
48 136115 : if (del != NULL) {
49 2 : xmlUnlinkNode(del);
50 2 : xmlFreeNode(del);
51 2 : del = NULL;
52 : }
53 136115 : if (trav->type == XML_TEXT_NODE) {
54 432 : if (is_blank(trav->content)) {
55 212 : del = trav;
56 : }
57 135685 : } else if ((trav->type != XML_ELEMENT_NODE) &&
58 : (trav->type != XML_CDATA_SECTION_NODE)) {
59 2 : del = trav;
60 135681 : } else if (trav->children != NULL) {
61 67353 : cleanup_xml_node(trav);
62 : }
63 136115 : trav = trav->next;
64 : }
65 68067 : if (del != NULL) {
66 212 : xmlUnlinkNode(del);
67 212 : xmlFreeNode(del);
68 : }
69 68067 : }
70 :
71 : static void soap_ignorableWhitespace(void *ctx, const xmlChar *ch, int len)
72 209153 : {
73 209153 : }
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 716 : {
81 716 : xmlParserCtxtPtr ctxt = NULL;
82 : xmlDocPtr ret;
83 : char *old_allow_url_fopen_list;
84 :
85 : /*
86 : xmlInitParser();
87 : */
88 :
89 716 : old_allow_url_fopen_list = PG(allow_url_fopen_list);
90 716 : if (old_allow_url_fopen_list) {
91 716 : old_allow_url_fopen_list = estrdup(old_allow_url_fopen_list);
92 : } else {
93 0 : old_allow_url_fopen_list = STR_EMPTY_ALLOC();
94 : }
95 :
96 716 : zend_alter_ini_entry("allow_url_fopen", sizeof("allow_url_fopen"), "*", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME);
97 716 : ctxt = xmlCreateFileParserCtxt(filename);
98 716 : zend_alter_ini_entry("allow_url_fopen", sizeof("allow_url_fopen"), old_allow_url_fopen_list, strlen(old_allow_url_fopen_list), PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME);
99 716 : efree(old_allow_url_fopen_list);
100 :
101 716 : if (ctxt) {
102 715 : ctxt->keepBlanks = 0;
103 715 : ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
104 715 : ctxt->sax->comment = soap_Comment;
105 715 : ctxt->sax->warning = NULL;
106 715 : ctxt->sax->error = NULL;
107 : /*ctxt->sax->fatalError = NULL;*/
108 715 : xmlParseDocument(ctxt);
109 715 : if (ctxt->wellFormed) {
110 714 : ret = ctxt->myDoc;
111 714 : if (ret->URL == NULL && ctxt->directory != NULL) {
112 0 : ret->URL = xmlCharStrdup(ctxt->directory);
113 : }
114 : } else {
115 1 : ret = NULL;
116 1 : xmlFreeDoc(ctxt->myDoc);
117 1 : ctxt->myDoc = NULL;
118 : }
119 715 : xmlFreeParserCtxt(ctxt);
120 : } else {
121 1 : ret = NULL;
122 : }
123 :
124 : /*
125 : xmlCleanupParser();
126 : */
127 :
128 716 : if (ret) {
129 714 : cleanup_xml_node((xmlNodePtr)ret);
130 : }
131 716 : return ret;
132 : }
133 :
134 : xmlDocPtr soap_xmlParseMemory(const void *buf, size_t buf_size)
135 536 : {
136 536 : xmlParserCtxtPtr ctxt = NULL;
137 : xmlDocPtr ret;
138 :
139 : /*
140 : xmlInitParser();
141 : */
142 536 : ctxt = xmlCreateMemoryParserCtxt(buf, buf_size);
143 536 : if (ctxt) {
144 536 : ctxt->sax->ignorableWhitespace = soap_ignorableWhitespace;
145 536 : ctxt->sax->comment = soap_Comment;
146 536 : ctxt->sax->warning = NULL;
147 536 : ctxt->sax->error = NULL;
148 : /*ctxt->sax->fatalError = NULL;*/
149 536 : xmlParseDocument(ctxt);
150 536 : if (ctxt->wellFormed) {
151 535 : ret = ctxt->myDoc;
152 535 : if (ret->URL == NULL && ctxt->directory != NULL) {
153 0 : ret->URL = xmlCharStrdup(ctxt->directory);
154 : }
155 : } else {
156 1 : ret = NULL;
157 1 : xmlFreeDoc(ctxt->myDoc);
158 1 : ctxt->myDoc = NULL;
159 : }
160 536 : xmlFreeParserCtxt(ctxt);
161 : } else {
162 0 : ret = NULL;
163 : }
164 :
165 : /*
166 : xmlCleanupParser();
167 : */
168 :
169 : /*
170 : if (ret) {
171 : cleanup_xml_node((xmlNodePtr)ret);
172 : }
173 : */
174 536 : return ret;
175 : }
176 :
177 : xmlNsPtr attr_find_ns(xmlAttrPtr node)
178 7349 : {
179 7349 : if (node->ns) {
180 4574 : return node->ns;
181 2775 : } else if (node->parent->ns) {
182 2775 : return node->parent->ns;
183 : } else {
184 0 : return xmlSearchNs(node->doc, node->parent, NULL);
185 : }
186 : }
187 :
188 : xmlNsPtr node_find_ns(xmlNodePtr node)
189 153864 : {
190 153864 : if (node->ns) {
191 153864 : return node->ns;
192 : } else {
193 0 : return xmlSearchNs(node->doc, node, NULL);
194 : }
195 : }
196 :
197 : int attr_is_equal_ex(xmlAttrPtr node, char *name, char *ns)
198 731839 : {
199 731839 : if (name == NULL || strcmp((char*)node->name, name) == 0) {
200 267860 : if (ns) {
201 6306 : xmlNsPtr nsPtr = attr_find_ns(node);
202 6306 : if (nsPtr) {
203 6306 : return (strcmp((char*)nsPtr->href, ns) == 0);
204 : } else {
205 0 : return FALSE;
206 : }
207 : }
208 261554 : return TRUE;
209 : }
210 463979 : return FALSE;
211 : }
212 :
213 : int node_is_equal_ex(xmlNodePtr node, char *name, char *ns)
214 557595 : {
215 557595 : if (name == NULL || strcmp((char*)node->name, name) == 0) {
216 282475 : if (ns) {
217 153864 : xmlNsPtr nsPtr = node_find_ns(node);
218 153864 : if (nsPtr) {
219 153864 : return (strcmp((char*)nsPtr->href, ns) == 0);
220 : } else {
221 0 : return FALSE;
222 : }
223 : }
224 128611 : return TRUE;
225 : }
226 275120 : return FALSE;
227 : }
228 :
229 :
230 : xmlAttrPtr get_attribute_ex(xmlAttrPtr node, char *name, char *ns)
231 487470 : {
232 1417778 : while (node!=NULL) {
233 707705 : if (attr_is_equal_ex(node, name, ns)) {
234 264867 : return node;
235 : }
236 442838 : node = node->next;
237 : }
238 222603 : return NULL;
239 : }
240 :
241 : xmlNodePtr get_node_ex(xmlNodePtr node, char *name, char *ns)
242 113202 : {
243 263687 : while (node!=NULL) {
244 148864 : if (node_is_equal_ex(node, name, ns)) {
245 111581 : return node;
246 : }
247 37283 : node = node->next;
248 : }
249 1621 : return NULL;
250 : }
251 :
252 : xmlNodePtr get_node_recurisve_ex(xmlNodePtr node, char *name, char *ns)
253 0 : {
254 0 : while (node != NULL) {
255 0 : if (node_is_equal_ex(node, name, ns)) {
256 0 : return node;
257 0 : } else if (node->children != NULL) {
258 0 : xmlNodePtr tmp = get_node_recurisve_ex(node->children, name, ns);
259 0 : if (tmp) {
260 0 : return tmp;
261 : }
262 : }
263 0 : node = node->next;
264 : }
265 0 : return NULL;
266 : }
267 :
268 : xmlNodePtr get_node_with_attribute_ex(xmlNodePtr node, char *name, char *name_ns, char *attribute, char *value, char *attr_ns)
269 10310 : {
270 : xmlAttrPtr attr;
271 :
272 79728 : while (node != NULL) {
273 69418 : if (name != NULL) {
274 69418 : node = get_node_ex(node, name, name_ns);
275 69418 : if (node==NULL) {
276 34 : return NULL;
277 : }
278 : }
279 :
280 69384 : attr = get_attribute_ex(node->properties, attribute, attr_ns);
281 69384 : if (attr != NULL && strcmp((char*)attr->children->content, value) == 0) {
282 10276 : return node;
283 : }
284 59108 : node = node->next;
285 : }
286 0 : return NULL;
287 : }
288 :
289 : xmlNodePtr get_node_with_attribute_recursive_ex(xmlNodePtr node, char *name, char *name_ns, char *attribute, char *value, char *attr_ns)
290 18957 : {
291 70230 : while (node != NULL) {
292 32986 : if (node_is_equal_ex(node, name, name_ns)) {
293 32986 : xmlAttrPtr attr = get_attribute_ex(node->properties, attribute, attr_ns);
294 32986 : if (attr != NULL && strcmp((char*)attr->children->content, value) == 0) {
295 221 : return node;
296 : }
297 : }
298 32765 : if (node->children != NULL) {
299 18735 : xmlNodePtr tmp = get_node_with_attribute_recursive_ex(node->children, name, name_ns, attribute, value, attr_ns);
300 18735 : if (tmp) {
301 449 : return tmp;
302 : }
303 : }
304 32316 : node = node->next;
305 : }
306 18287 : return NULL;
307 : }
308 :
309 : int parse_namespace(const xmlChar *inval, char **value, char **namespace)
310 36191 : {
311 36191 : char *found = strrchr((char*)inval, ':');
312 :
313 70943 : if (found != NULL && found != (char*)inval) {
314 34752 : (*namespace) = estrndup((char*)inval, found - (char*)inval);
315 34752 : (*value) = estrdup(++found);
316 : } else {
317 1439 : (*value) = estrdup((char*)inval);
318 1439 : (*namespace) = NULL;
319 : }
320 :
321 36191 : return FALSE;
322 : }
|