2 * Copyright (C) 1995-2005, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: soap.c,v 1.12 2005-08-22 20:34:21 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 /* check that root node is Envelope */
49 ptr = xmlDocGetRootElement(doc);
50 if (!ptr || ptr->type != XML_ELEMENT_NODE ||
51 xmlStrcmp(ptr->name, BAD_CAST "Envelope") || !ptr->ns)
54 return z_soap_error(o, p, "SOAP-ENV:Client",
55 "No Envelope element", 0);
59 /* determine SOAP version */
60 const char * ns_envelope = (const char *) ptr->ns->href;
61 if (!strcmp(ns_envelope, soap_v1_1))
63 else if (!strcmp(ns_envelope, soap_v1_2))
68 return z_soap_error(o, p, "SOAP-ENV:Client",
69 "Bad SOAP version", 0);
73 while(ptr && ptr->type == XML_TEXT_NODE)
75 if (ptr && ptr->type == XML_ELEMENT_NODE &&
76 !xmlStrcmp(ptr->ns->href, BAD_CAST p->ns) &&
77 !xmlStrcmp(ptr->name, BAD_CAST "Header"))
80 while(ptr && ptr->type == XML_TEXT_NODE)
83 /* check that Body is present */
84 if (!ptr || ptr->type != XML_ELEMENT_NODE ||
85 xmlStrcmp(ptr->name, BAD_CAST "Body"))
88 return z_soap_error(o, p, "SOAP-ENV:Client",
89 "SOAP Body element not found", 0);
91 if (xmlStrcmp(ptr->ns->href, BAD_CAST p->ns))
94 return z_soap_error(o, p, "SOAP-ENV:Client",
95 "SOAP bad NS for Body element", 0);
99 while (ptr && ptr->type == XML_TEXT_NODE)
101 if (!ptr || ptr->type != XML_ELEMENT_NODE)
104 return z_soap_error(o, p, "SOAP-ENV:Client",
105 "SOAP No content for Body", 0);
110 return z_soap_error(o, p, "SOAP-ENV:Client",
111 "SOAP No namespace for content", 0);
113 /* check for fault package */
114 if (!xmlStrcmp(ptr->ns->href, BAD_CAST p->ns)
115 && !xmlStrcmp(ptr->name, BAD_CAST "Fault") && ptr->children)
119 p->which = Z_SOAP_fault;
120 p->u.fault = (Z_SOAP_Fault *) odr_malloc(o, sizeof(*p->u.fault));
121 p->u.fault->fault_code = 0;
122 p->u.fault->fault_string = 0;
123 p->u.fault->details = 0;
126 if (ptr->children && ptr->children->type == XML_TEXT_NODE)
128 if (!xmlStrcmp(ptr->name, BAD_CAST "faultcode"))
129 p->u.fault->fault_code =
130 odr_strdup(o, (const char *)
131 ptr->children->content);
132 if (!xmlStrcmp(ptr->name, BAD_CAST "faultstring"))
133 p->u.fault->fault_string =
134 odr_strdup(o, (const char *)
135 ptr->children->content);
136 if (!xmlStrcmp(ptr->name, BAD_CAST "details"))
137 p->u.fault->details =
138 odr_strdup(o, (const char *)
139 ptr->children->content);
147 for (i = 0; handlers[i].ns; i++)
148 if (!xmlStrcmp(ptr->ns->href, BAD_CAST handlers[i].ns))
152 void *handler_data = 0;
153 ret = (*handlers[i].f)(o, pptr, &handler_data,
154 handlers[i].client_data,
156 if (ret || !handler_data)
157 z_soap_error(o, p, "SOAP-ENV:Client",
158 "SOAP Handler returned error", 0);
161 p->which = Z_SOAP_generic;
162 p->u.generic = (Z_SOAP_Generic *)
163 odr_malloc(o, sizeof(*p->u.generic));
164 p->u.generic->no = i;
165 p->u.generic->ns = handlers[i].ns;
166 p->u.generic->p = handler_data;
171 ret = z_soap_error(o, p, "SOAP-ENV:Client",
173 (const char *)ptr->ns->href);
179 else if (o->direction == ODR_ENCODE)
183 xmlNodePtr envelope_ptr, body_ptr;
185 xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
187 envelope_ptr = xmlNewNode(0, BAD_CAST "Envelope");
188 ns_env = xmlNewNs(envelope_ptr, BAD_CAST p->ns,
189 BAD_CAST "SOAP-ENV");
190 xmlSetNs(envelope_ptr, ns_env);
192 body_ptr = xmlNewChild(envelope_ptr, ns_env, BAD_CAST "Body",
194 xmlDocSetRootElement(doc, envelope_ptr);
196 if (p->which == Z_SOAP_fault || p->which == Z_SOAP_error)
198 Z_SOAP_Fault *f = p->u.fault;
199 xmlNodePtr fault_ptr = xmlNewChild(body_ptr, ns_env,
200 BAD_CAST "Fault", 0);
201 xmlNewChild(fault_ptr, ns_env, BAD_CAST "faultcode",
202 BAD_CAST f->fault_code);
203 xmlNewChild(fault_ptr, ns_env, BAD_CAST "faultstring",
204 BAD_CAST f->fault_string);
206 xmlNewChild(fault_ptr, ns_env, BAD_CAST "details",
207 BAD_CAST f->details);
209 else if (p->which == Z_SOAP_generic)
211 int ret, no = p->u.generic->no;
213 ret = (*handlers[no].f)(o, body_ptr, &p->u.generic->p,
214 handlers[no].client_data,
222 if (p->which == Z_SOAP_generic && !strcmp(p->ns, "SRU"))
224 xmlDocSetRootElement(doc, body_ptr->children);
225 body_ptr->children = 0;
226 xmlFreeNode(envelope_ptr);
230 char *content = odr_malloc(o, strlen(stylesheet) + 40);
232 xmlNodePtr pi, ptr = xmlDocGetRootElement(doc);
233 sprintf(content, "type=\"text/xsl\" href=\"%s\"", stylesheet);
234 pi = xmlNewPI(BAD_CAST "xml-stylesheet",
236 xmlAddPrevSibling(ptr, pi);
243 xmlDocDumpMemoryEnc(doc, &buf_out, &len_out, encoding);
245 xmlDocDumpMemory(doc, &buf_out, &len_out);
246 *content_buf = (char *) odr_malloc(o, len_out);
247 *content_len = len_out;
248 memcpy(*content_buf, buf_out, len_out);
257 int z_soap_codec_enc_xsl(ODR o, Z_SOAP **pp,
258 char **content_buf, int *content_len,
259 Z_SOAP_Handler *handlers, const char *encoding,
260 const char *stylesheet)
262 static char *err_xml =
263 "<?xml version=\"1.0\"?>\n"
265 " xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
266 "\t<SOAP-ENV:Body>\n"
267 "\t\t<SOAP-ENV:Fault>\n"
268 "\t\t\t<faultcode>SOAP-ENV:Server</faultcode>\n"
269 "\t\t\t<faultstring>HTTP error</faultstring>\n"
270 "\t\t\t<detail>SOAP not supported in this YAZ configuration</detail>\n"
271 "\t\t</SOAP-ENV:Fault>\n"
272 "\t</SOAP-ENV:Body>\n"
273 "</SOAP-ENV:Envelope>\n";
274 if (o->direction == ODR_ENCODE)
276 *content_buf = err_xml;
277 *content_len = strlen(err_xml);
282 int z_soap_codec_enc(ODR o, Z_SOAP **pp,
283 char **content_buf, int *content_len,
284 Z_SOAP_Handler *handlers,
285 const char *encoding)
287 return z_soap_codec_enc_xsl(o, pp, content_buf, content_len, handlers,
291 int z_soap_codec(ODR o, Z_SOAP **pp,
292 char **content_buf, int *content_len,
293 Z_SOAP_Handler *handlers)
295 return z_soap_codec_enc(o, pp, content_buf, content_len, handlers, 0);
298 int z_soap_error(ODR o, Z_SOAP *p,
299 const char *fault_code, const char *fault_string,
302 p->which = Z_SOAP_error;
303 p->u.soap_error = (Z_SOAP_Fault *)
304 odr_malloc(o, sizeof(*p->u.soap_error));
305 p->u.soap_error->fault_code = odr_strdup(o, fault_code);
306 p->u.soap_error->fault_string = odr_strdup(o, fault_string);
308 p->u.soap_error->details = odr_strdup(o, details);
310 p->u.soap_error->details = 0;
317 * indent-tabs-mode: nil
319 * vim: shiftwidth=4 tabstop=8 expandtab