2 * Copyright (C) 1995-2005, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: soap.c,v 1.13 2006-03-01 23:24:25 adam Exp $
9 * \brief Implements SOAP
11 * This implements encoding and decoding of SOAP packages using
18 #include <libxml/parser.h>
19 #include <libxml/tree.h>
21 static const char *soap_v1_1 = "http://schemas.xmlsoap.org/soap/envelope/";
22 static const char *soap_v1_2 = "http://www.w3.org/2001/06/soap-envelope";
24 int z_soap_codec_enc_xsl(ODR o, Z_SOAP **pp,
25 char **content_buf, int *content_len,
26 Z_SOAP_Handler *handlers,
28 const char *stylesheet)
30 if (o->direction == ODR_DECODE)
37 if (!content_buf || !*content_buf || !content_len)
40 *pp = p = (Z_SOAP *) odr_malloc(o, sizeof(*p));
43 doc = xmlParseMemory(*content_buf, *content_len);
45 return z_soap_error(o, p, "SOAP-ENV:Client",
46 "Bad XML Document", 0);
48 ptr = xmlDocGetRootElement(doc);
52 return z_soap_error(o, p, "SOAP-ENV:Client",
53 "No Envelope element", 0);
55 /* check for SRU root node match */
57 for (i = 0; handlers[i].ns; i++)
58 if (!xmlStrcmp(ptr->ns->href, BAD_CAST handlers[i].ns))
62 void *handler_data = 0;
63 xmlNode p_top_tmp; /* pseudo parent node needed */
65 p_top_tmp.children = ptr;
66 ret = (*handlers[i].f)(o, &p_top_tmp, &handler_data,
67 handlers[i].client_data,
70 if (ret || !handler_data)
71 z_soap_error(o, p, "SOAP-ENV:Client",
72 "SOAP Handler returned error", 0);
75 p->which = Z_SOAP_generic;
76 p->u.generic = (Z_SOAP_Generic *)
77 odr_malloc(o, sizeof(*p->u.generic));
79 p->u.generic->ns = handlers[i].ns;
80 p->u.generic->p = handler_data;
87 if (!ptr || ptr->type != XML_ELEMENT_NODE ||
88 xmlStrcmp(ptr->name, BAD_CAST "Envelope") || !ptr->ns)
91 return z_soap_error(o, p, "SOAP-ENV:Client",
92 "No Envelope element", 0);
96 /* determine SOAP version */
97 const char * ns_envelope = (const char *) ptr->ns->href;
98 if (!strcmp(ns_envelope, soap_v1_1))
100 else if (!strcmp(ns_envelope, soap_v1_2))
105 return z_soap_error(o, p, "SOAP-ENV:Client",
106 "Bad SOAP version", 0);
110 while(ptr && ptr->type == XML_TEXT_NODE)
112 if (ptr && ptr->type == XML_ELEMENT_NODE &&
113 !xmlStrcmp(ptr->ns->href, BAD_CAST p->ns) &&
114 !xmlStrcmp(ptr->name, BAD_CAST "Header"))
117 while(ptr && ptr->type == XML_TEXT_NODE)
120 /* check that Body is present */
121 if (!ptr || ptr->type != XML_ELEMENT_NODE ||
122 xmlStrcmp(ptr->name, BAD_CAST "Body"))
125 return z_soap_error(o, p, "SOAP-ENV:Client",
126 "SOAP Body element not found", 0);
128 if (xmlStrcmp(ptr->ns->href, BAD_CAST p->ns))
131 return z_soap_error(o, p, "SOAP-ENV:Client",
132 "SOAP bad NS for Body element", 0);
136 while (ptr && ptr->type == XML_TEXT_NODE)
138 if (!ptr || ptr->type != XML_ELEMENT_NODE)
141 return z_soap_error(o, p, "SOAP-ENV:Client",
142 "SOAP No content for Body", 0);
147 return z_soap_error(o, p, "SOAP-ENV:Client",
148 "SOAP No namespace for content", 0);
150 /* check for fault package */
151 if (!xmlStrcmp(ptr->ns->href, BAD_CAST p->ns)
152 && !xmlStrcmp(ptr->name, BAD_CAST "Fault") && ptr->children)
156 p->which = Z_SOAP_fault;
157 p->u.fault = (Z_SOAP_Fault *) odr_malloc(o, sizeof(*p->u.fault));
158 p->u.fault->fault_code = 0;
159 p->u.fault->fault_string = 0;
160 p->u.fault->details = 0;
163 if (ptr->children && ptr->children->type == XML_TEXT_NODE)
165 if (!xmlStrcmp(ptr->name, BAD_CAST "faultcode"))
166 p->u.fault->fault_code =
167 odr_strdup(o, (const char *)
168 ptr->children->content);
169 if (!xmlStrcmp(ptr->name, BAD_CAST "faultstring"))
170 p->u.fault->fault_string =
171 odr_strdup(o, (const char *)
172 ptr->children->content);
173 if (!xmlStrcmp(ptr->name, BAD_CAST "details"))
174 p->u.fault->details =
175 odr_strdup(o, (const char *)
176 ptr->children->content);
184 for (i = 0; handlers[i].ns; i++)
185 if (!xmlStrcmp(ptr->ns->href, BAD_CAST handlers[i].ns))
189 void *handler_data = 0;
190 ret = (*handlers[i].f)(o, pptr, &handler_data,
191 handlers[i].client_data,
193 if (ret || !handler_data)
194 z_soap_error(o, p, "SOAP-ENV:Client",
195 "SOAP Handler returned error", 0);
198 p->which = Z_SOAP_generic;
199 p->u.generic = (Z_SOAP_Generic *)
200 odr_malloc(o, sizeof(*p->u.generic));
201 p->u.generic->no = i;
202 p->u.generic->ns = handlers[i].ns;
203 p->u.generic->p = handler_data;
208 ret = z_soap_error(o, p, "SOAP-ENV:Client",
210 (const char *)ptr->ns->href);
216 else if (o->direction == ODR_ENCODE)
220 xmlNodePtr envelope_ptr, body_ptr;
222 xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
224 envelope_ptr = xmlNewNode(0, BAD_CAST "Envelope");
225 ns_env = xmlNewNs(envelope_ptr, BAD_CAST p->ns,
226 BAD_CAST "SOAP-ENV");
227 xmlSetNs(envelope_ptr, ns_env);
229 body_ptr = xmlNewChild(envelope_ptr, ns_env, BAD_CAST "Body",
231 xmlDocSetRootElement(doc, envelope_ptr);
233 if (p->which == Z_SOAP_fault || p->which == Z_SOAP_error)
235 Z_SOAP_Fault *f = p->u.fault;
236 xmlNodePtr fault_ptr = xmlNewChild(body_ptr, ns_env,
237 BAD_CAST "Fault", 0);
238 xmlNewChild(fault_ptr, ns_env, BAD_CAST "faultcode",
239 BAD_CAST f->fault_code);
240 xmlNewChild(fault_ptr, ns_env, BAD_CAST "faultstring",
241 BAD_CAST f->fault_string);
243 xmlNewChild(fault_ptr, ns_env, BAD_CAST "details",
244 BAD_CAST f->details);
246 else if (p->which == Z_SOAP_generic)
248 int ret, no = p->u.generic->no;
250 ret = (*handlers[no].f)(o, body_ptr, &p->u.generic->p,
251 handlers[no].client_data,
259 if (p->which == Z_SOAP_generic && !strcmp(p->ns, "SRU"))
261 xmlDocSetRootElement(doc, body_ptr->children);
262 body_ptr->children = 0;
263 xmlFreeNode(envelope_ptr);
267 char *content = odr_malloc(o, strlen(stylesheet) + 40);
269 xmlNodePtr pi, ptr = xmlDocGetRootElement(doc);
270 sprintf(content, "type=\"text/xsl\" href=\"%s\"", stylesheet);
271 pi = xmlNewPI(BAD_CAST "xml-stylesheet",
273 xmlAddPrevSibling(ptr, pi);
280 xmlDocDumpMemoryEnc(doc, &buf_out, &len_out, encoding);
282 xmlDocDumpMemory(doc, &buf_out, &len_out);
283 *content_buf = (char *) odr_malloc(o, len_out);
284 *content_len = len_out;
285 memcpy(*content_buf, buf_out, len_out);
294 int z_soap_codec_enc_xsl(ODR o, Z_SOAP **pp,
295 char **content_buf, int *content_len,
296 Z_SOAP_Handler *handlers, const char *encoding,
297 const char *stylesheet)
299 static char *err_xml =
300 "<?xml version=\"1.0\"?>\n"
302 " xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
303 "\t<SOAP-ENV:Body>\n"
304 "\t\t<SOAP-ENV:Fault>\n"
305 "\t\t\t<faultcode>SOAP-ENV:Server</faultcode>\n"
306 "\t\t\t<faultstring>HTTP error</faultstring>\n"
307 "\t\t\t<detail>SOAP not supported in this YAZ configuration</detail>\n"
308 "\t\t</SOAP-ENV:Fault>\n"
309 "\t</SOAP-ENV:Body>\n"
310 "</SOAP-ENV:Envelope>\n";
311 if (o->direction == ODR_ENCODE)
313 *content_buf = err_xml;
314 *content_len = strlen(err_xml);
319 int z_soap_codec_enc(ODR o, Z_SOAP **pp,
320 char **content_buf, int *content_len,
321 Z_SOAP_Handler *handlers,
322 const char *encoding)
324 return z_soap_codec_enc_xsl(o, pp, content_buf, content_len, handlers,
328 int z_soap_codec(ODR o, Z_SOAP **pp,
329 char **content_buf, int *content_len,
330 Z_SOAP_Handler *handlers)
332 return z_soap_codec_enc(o, pp, content_buf, content_len, handlers, 0);
335 int z_soap_error(ODR o, Z_SOAP *p,
336 const char *fault_code, const char *fault_string,
339 p->which = Z_SOAP_error;
340 p->u.soap_error = (Z_SOAP_Fault *)
341 odr_malloc(o, sizeof(*p->u.soap_error));
342 p->u.soap_error->fault_code = odr_strdup(o, fault_code);
343 p->u.soap_error->fault_string = odr_strdup(o, fault_string);
345 p->u.soap_error->details = odr_strdup(o, details);
347 p->u.soap_error->details = 0;
354 * indent-tabs-mode: nil
356 * vim: shiftwidth=4 tabstop=8 expandtab