1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2011 Index Data
3 * See the file LICENSE for details.
7 * \brief Implements SOAP
9 * This implements encoding and decoding of SOAP packages using
19 #include <libxml/parser.h>
20 #include <libxml/tree.h>
22 static const char *soap_v1_1 = "http://schemas.xmlsoap.org/soap/envelope/";
23 static const char *soap_v1_2 = "http://www.w3.org/2001/06/soap-envelope";
25 int z_soap_codec_enc_xsl(ODR o, Z_SOAP **pp,
26 char **content_buf, int *content_len,
27 Z_SOAP_Handler *handlers,
29 const char *stylesheet)
31 if (o->direction == ODR_DECODE)
38 if (!content_buf || !*content_buf || !content_len)
41 *pp = p = (Z_SOAP *) odr_malloc(o, sizeof(*p));
44 doc = xmlParseMemory(*content_buf, *content_len);
46 return z_soap_error(o, p, "SOAP-ENV:Client",
47 "Bad XML Document", 0);
49 ptr = xmlDocGetRootElement(doc);
53 return z_soap_error(o, p, "SOAP-ENV:Client",
54 "No Envelope element", 0);
56 /* check for SRU root node match */
58 for (i = 0; handlers[i].ns; i++)
59 if (!xmlStrcmp(ptr->ns->href, BAD_CAST handlers[i].ns))
63 void *handler_data = 0;
64 xmlNode p_top_tmp; /* pseudo parent node needed */
66 p_top_tmp.children = ptr;
67 ret = (*handlers[i].f)(o, &p_top_tmp, &handler_data,
68 handlers[i].client_data,
71 if (ret || !handler_data)
72 z_soap_error(o, p, "SOAP-ENV:Client",
73 "SOAP Handler returned error", 0);
76 p->which = Z_SOAP_generic;
77 p->u.generic = (Z_SOAP_Generic *)
78 odr_malloc(o, sizeof(*p->u.generic));
80 p->u.generic->ns = handlers[i].ns;
81 p->u.generic->p = handler_data;
88 if (!ptr || ptr->type != XML_ELEMENT_NODE ||
89 xmlStrcmp(ptr->name, BAD_CAST "Envelope") || !ptr->ns)
92 return z_soap_error(o, p, "SOAP-ENV:Client",
93 "No Envelope element", 0);
97 /* determine SOAP version */
98 const char * ns_envelope = (const char *) ptr->ns->href;
99 if (!strcmp(ns_envelope, soap_v1_1))
101 else if (!strcmp(ns_envelope, soap_v1_2))
106 return z_soap_error(o, p, "SOAP-ENV:Client",
107 "Bad SOAP version", 0);
111 while(ptr && ptr->type == XML_TEXT_NODE)
113 if (ptr && ptr->type == XML_ELEMENT_NODE &&
114 !xmlStrcmp(ptr->ns->href, BAD_CAST p->ns) &&
115 !xmlStrcmp(ptr->name, BAD_CAST "Header"))
118 while(ptr && ptr->type == XML_TEXT_NODE)
121 /* check that Body is present */
122 if (!ptr || ptr->type != XML_ELEMENT_NODE ||
123 xmlStrcmp(ptr->name, BAD_CAST "Body"))
126 return z_soap_error(o, p, "SOAP-ENV:Client",
127 "SOAP Body element not found", 0);
129 if (xmlStrcmp(ptr->ns->href, BAD_CAST p->ns))
132 return z_soap_error(o, p, "SOAP-ENV:Client",
133 "SOAP bad NS for Body element", 0);
137 while (ptr && ptr->type == XML_TEXT_NODE)
139 if (!ptr || ptr->type != XML_ELEMENT_NODE)
142 return z_soap_error(o, p, "SOAP-ENV:Client",
143 "SOAP No content for Body", 0);
148 return z_soap_error(o, p, "SOAP-ENV:Client",
149 "SOAP No namespace for content", 0);
151 /* check for fault package */
152 if (!xmlStrcmp(ptr->ns->href, BAD_CAST p->ns)
153 && !xmlStrcmp(ptr->name, BAD_CAST "Fault") && ptr->children)
157 p->which = Z_SOAP_fault;
158 p->u.fault = (Z_SOAP_Fault *) odr_malloc(o, sizeof(*p->u.fault));
159 p->u.fault->fault_code = 0;
160 p->u.fault->fault_string = 0;
161 p->u.fault->details = 0;
164 if (ptr->children && ptr->children->type == XML_TEXT_NODE)
166 if (!xmlStrcmp(ptr->name, BAD_CAST "faultcode"))
167 p->u.fault->fault_code =
168 odr_strdup(o, (const char *)
169 ptr->children->content);
170 if (!xmlStrcmp(ptr->name, BAD_CAST "faultstring"))
171 p->u.fault->fault_string =
172 odr_strdup(o, (const char *)
173 ptr->children->content);
174 if (!xmlStrcmp(ptr->name, BAD_CAST "details"))
175 p->u.fault->details =
176 odr_strdup(o, (const char *)
177 ptr->children->content);
185 for (i = 0; handlers[i].ns; i++)
186 if (!xmlStrcmp(ptr->ns->href, BAD_CAST handlers[i].ns))
190 void *handler_data = 0;
191 ret = (*handlers[i].f)(o, pptr, &handler_data,
192 handlers[i].client_data,
194 if (ret || !handler_data)
195 z_soap_error(o, p, "SOAP-ENV:Client",
196 "SOAP Handler returned error", 0);
199 p->which = Z_SOAP_generic;
200 p->u.generic = (Z_SOAP_Generic *)
201 odr_malloc(o, sizeof(*p->u.generic));
202 p->u.generic->no = i;
203 p->u.generic->ns = handlers[i].ns;
204 p->u.generic->p = handler_data;
209 ret = z_soap_error(o, p, "SOAP-ENV:Client",
211 (const char *)ptr->ns->href);
217 else if (o->direction == ODR_ENCODE)
221 xmlNodePtr envelope_ptr, body_ptr;
223 xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
225 envelope_ptr = xmlNewNode(0, BAD_CAST "Envelope");
226 ns_env = xmlNewNs(envelope_ptr, BAD_CAST p->ns,
227 BAD_CAST "SOAP-ENV");
228 xmlSetNs(envelope_ptr, ns_env);
230 body_ptr = xmlNewChild(envelope_ptr, ns_env, BAD_CAST "Body",
232 xmlDocSetRootElement(doc, envelope_ptr);
234 if (p->which == Z_SOAP_fault || p->which == Z_SOAP_error)
236 Z_SOAP_Fault *f = p->u.fault;
237 xmlNodePtr fault_ptr = xmlNewChild(body_ptr, ns_env,
238 BAD_CAST "Fault", 0);
239 xmlNewChild(fault_ptr, ns_env, BAD_CAST "faultcode",
240 BAD_CAST f->fault_code);
241 xmlNewChild(fault_ptr, ns_env, BAD_CAST "faultstring",
242 BAD_CAST f->fault_string);
244 xmlNewChild(fault_ptr, ns_env, BAD_CAST "details",
245 BAD_CAST f->details);
247 else if (p->which == Z_SOAP_generic)
249 int ret, no = p->u.generic->no;
251 ret = (*handlers[no].f)(o, body_ptr, &p->u.generic->p,
252 handlers[no].client_data,
260 if (p->which == Z_SOAP_generic && !strcmp(p->ns, "SRU"))
262 xmlDocSetRootElement(doc, body_ptr->children);
263 body_ptr->children = 0;
264 xmlFreeNode(envelope_ptr);
268 char *content = (char *) odr_malloc(o, strlen(stylesheet) + 40);
270 xmlNodePtr pi, ptr = xmlDocGetRootElement(doc);
271 sprintf(content, "type=\"text/xsl\" href=\"%s\"", stylesheet);
272 pi = xmlNewPI(BAD_CAST "xml-stylesheet",
274 xmlAddPrevSibling(ptr, pi);
281 xmlDocDumpMemoryEnc(doc, &buf_out, &len_out, encoding);
283 xmlDocDumpMemory(doc, &buf_out, &len_out);
284 *content_buf = (char *) odr_malloc(o, len_out);
285 *content_len = len_out;
286 memcpy(*content_buf, buf_out, len_out);
295 int z_soap_codec_enc_xsl(ODR o, Z_SOAP **pp,
296 char **content_buf, int *content_len,
297 Z_SOAP_Handler *handlers, const char *encoding,
298 const char *stylesheet)
300 static char *err_xml =
301 "<?xml version=\"1.0\"?>\n"
303 " xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
304 "\t<SOAP-ENV:Body>\n"
305 "\t\t<SOAP-ENV:Fault>\n"
306 "\t\t\t<faultcode>SOAP-ENV:Server</faultcode>\n"
307 "\t\t\t<faultstring>HTTP error</faultstring>\n"
308 "\t\t\t<detail>SOAP not supported in this YAZ configuration</detail>\n"
309 "\t\t</SOAP-ENV:Fault>\n"
310 "\t</SOAP-ENV:Body>\n"
311 "</SOAP-ENV:Envelope>\n";
312 if (o->direction == ODR_ENCODE)
314 *content_buf = err_xml;
315 *content_len = strlen(err_xml);
320 int z_soap_codec_enc(ODR o, Z_SOAP **pp,
321 char **content_buf, int *content_len,
322 Z_SOAP_Handler *handlers,
323 const char *encoding)
325 return z_soap_codec_enc_xsl(o, pp, content_buf, content_len, handlers,
329 int z_soap_codec(ODR o, Z_SOAP **pp,
330 char **content_buf, int *content_len,
331 Z_SOAP_Handler *handlers)
333 return z_soap_codec_enc(o, pp, content_buf, content_len, handlers, 0);
336 int z_soap_error(ODR o, Z_SOAP *p,
337 const char *fault_code, const char *fault_string,
340 p->which = Z_SOAP_error;
341 p->u.soap_error = (Z_SOAP_Fault *)
342 odr_malloc(o, sizeof(*p->u.soap_error));
343 p->u.soap_error->fault_code = odr_strdup(o, fault_code);
344 p->u.soap_error->fault_string = odr_strdup(o, fault_string);
346 p->u.soap_error->details = odr_strdup(o, details);
348 p->u.soap_error->details = 0;
355 * c-file-style: "Stroustrup"
356 * indent-tabs-mode: nil
358 * vim: shiftwidth=4 tabstop=8 expandtab