2 * Copyright (C) 1995-2005, Index Data ApS
3 * See the file LICENSE for details.
5 * $Id: soap.c,v 1.11 2005-06-25 15:46:05 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);
47 /* check that root node is Envelope */
48 ptr = xmlDocGetRootElement(doc);
49 if (!ptr || ptr->type != XML_ELEMENT_NODE ||
50 strcmp(ptr->name, "Envelope") || !ptr->ns)
53 return z_soap_error(o, p, "SOAP-ENV:Client",
54 "No Envelope element", 0);
58 /* determine SOAP version */
59 const char * ns_envelope = ptr->ns->href;
60 if (!strcmp(ns_envelope, soap_v1_1))
62 else if (!strcmp(ns_envelope, soap_v1_2))
67 return z_soap_error(o, p, "SOAP-ENV:Client",
68 "Bad SOAP version", 0);
72 while(ptr && ptr->type == XML_TEXT_NODE)
74 if (ptr && ptr->type == XML_ELEMENT_NODE &&
75 !strcmp(ptr->ns->href, p->ns) &&
76 !strcmp(ptr->name, "Header"))
79 while(ptr && ptr->type == XML_TEXT_NODE)
82 /* check that Body is present */
83 if (!ptr || ptr->type != XML_ELEMENT_NODE ||
84 strcmp(ptr->name, "Body"))
87 return z_soap_error(o, p, "SOAP-ENV:Client",
88 "SOAP Body element not found", 0);
90 if (strcmp(ptr->ns->href, p->ns))
93 return z_soap_error(o, p, "SOAP-ENV:Client",
94 "SOAP bad NS for Body element", 0);
98 while (ptr && ptr->type == XML_TEXT_NODE)
100 if (!ptr || ptr->type != XML_ELEMENT_NODE)
103 return z_soap_error(o, p, "SOAP-ENV:Client",
104 "SOAP No content for Body", 0);
109 return z_soap_error(o, p, "SOAP-ENV:Client",
110 "SOAP No namespace for content", 0);
112 /* check for fault package */
113 if (!strcmp(ptr->ns->href, p->ns)
114 && !strcmp(ptr->name, "Fault") && ptr->children)
118 p->which = Z_SOAP_fault;
119 p->u.fault = (Z_SOAP_Fault *) odr_malloc(o, sizeof(*p->u.fault));
120 p->u.fault->fault_code = 0;
121 p->u.fault->fault_string = 0;
122 p->u.fault->details = 0;
125 if (ptr->children && ptr->children->type == XML_TEXT_NODE)
127 if (!strcmp(ptr->name, "faultcode"))
128 p->u.fault->fault_code =
129 odr_strdup(o, ptr->children->content);
130 if (!strcmp(ptr->name, "faultstring"))
131 p->u.fault->fault_string =
132 odr_strdup(o, ptr->children->content);
133 if (!strcmp(ptr->name, "details"))
134 p->u.fault->details =
135 odr_strdup(o, ptr->children->content);
143 for (i = 0; handlers[i].ns; i++)
144 if (!strcmp(ptr->ns->href, handlers[i].ns))
148 void *handler_data = 0;
149 ret = (*handlers[i].f)(o, pptr, &handler_data,
150 handlers[i].client_data,
152 if (ret || !handler_data)
153 z_soap_error(o, p, "SOAP-ENV:Client",
154 "SOAP Handler returned error", 0);
157 p->which = Z_SOAP_generic;
158 p->u.generic = (Z_SOAP_Generic *)
159 odr_malloc(o, sizeof(*p->u.generic));
160 p->u.generic->no = i;
161 p->u.generic->ns = handlers[i].ns;
162 p->u.generic->p = handler_data;
167 ret = z_soap_error(o, p, "SOAP-ENV:Client",
168 "No handler for NS", ptr->ns->href);
174 else if (o->direction == ODR_ENCODE)
178 xmlNodePtr envelope_ptr, body_ptr;
180 xmlDocPtr doc = xmlNewDoc("1.0");
182 envelope_ptr = xmlNewNode(0, "Envelope");
183 ns_env = xmlNewNs(envelope_ptr, p->ns, "SOAP-ENV");
184 xmlSetNs(envelope_ptr, ns_env);
186 body_ptr = xmlNewChild(envelope_ptr, ns_env, "Body", 0);
187 xmlDocSetRootElement(doc, envelope_ptr);
189 if (p->which == Z_SOAP_fault || p->which == Z_SOAP_error)
191 Z_SOAP_Fault *f = p->u.fault;
192 xmlNodePtr fault_ptr = xmlNewChild(body_ptr, ns_env, "Fault", 0);
193 xmlNewChild(fault_ptr, ns_env, "faultcode", f->fault_code);
194 xmlNewChild(fault_ptr, ns_env, "faultstring", f->fault_string);
196 xmlNewChild(fault_ptr, ns_env, "details", f->details);
198 else if (p->which == Z_SOAP_generic)
200 int ret, no = p->u.generic->no;
202 ret = (*handlers[no].f)(o, body_ptr, &p->u.generic->p,
203 handlers[no].client_data,
211 if (p->which == Z_SOAP_generic && !strcmp(p->ns, "SRU"))
213 xmlDocSetRootElement(doc, body_ptr->children);
214 body_ptr->children = 0;
215 xmlFreeNode(envelope_ptr);
219 char *content = odr_malloc(o, strlen(stylesheet) + 40);
221 xmlNodePtr pi, ptr = xmlDocGetRootElement(doc);
222 sprintf(content, "type=\"text/xsl\" href=\"%s\"", stylesheet);
223 pi = xmlNewPI("xml-stylesheet", content);
224 xmlAddPrevSibling(ptr, pi);
231 xmlDocDumpMemoryEnc(doc, &buf_out, &len_out, encoding);
233 xmlDocDumpMemory(doc, &buf_out, &len_out);
234 *content_buf = (char *) odr_malloc(o, len_out);
235 *content_len = len_out;
236 memcpy(*content_buf, buf_out, len_out);
245 int z_soap_codec_enc_xsl(ODR o, Z_SOAP **pp,
246 char **content_buf, int *content_len,
247 Z_SOAP_Handler *handlers, const char *encoding,
248 const char *stylesheet)
250 static char *err_xml =
251 "<?xml version=\"1.0\"?>\n"
253 " xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
254 "\t<SOAP-ENV:Body>\n"
255 "\t\t<SOAP-ENV:Fault>\n"
256 "\t\t\t<faultcode>SOAP-ENV:Server</faultcode>\n"
257 "\t\t\t<faultstring>HTTP error</faultstring>\n"
258 "\t\t\t<detail>SOAP not supported in this YAZ configuration</detail>\n"
259 "\t\t</SOAP-ENV:Fault>\n"
260 "\t</SOAP-ENV:Body>\n"
261 "</SOAP-ENV:Envelope>\n";
262 if (o->direction == ODR_ENCODE)
264 *content_buf = err_xml;
265 *content_len = strlen(err_xml);
270 int z_soap_codec_enc(ODR o, Z_SOAP **pp,
271 char **content_buf, int *content_len,
272 Z_SOAP_Handler *handlers,
273 const char *encoding)
275 return z_soap_codec_enc_xsl(o, pp, content_buf, content_len, handlers,
279 int z_soap_codec(ODR o, Z_SOAP **pp,
280 char **content_buf, int *content_len,
281 Z_SOAP_Handler *handlers)
283 return z_soap_codec_enc(o, pp, content_buf, content_len, handlers, 0);
286 int z_soap_error(ODR o, Z_SOAP *p,
287 const char *fault_code, const char *fault_string,
290 p->which = Z_SOAP_error;
291 p->u.soap_error = (Z_SOAP_Fault *)
292 odr_malloc(o, sizeof(*p->u.soap_error));
293 p->u.soap_error->fault_code = odr_strdup(o, fault_code);
294 p->u.soap_error->fault_string = odr_strdup(o, fault_string);
296 p->u.soap_error->details = odr_strdup(o, details);
298 p->u.soap_error->details = 0;
305 * indent-tabs-mode: nil
307 * vim: shiftwidth=4 tabstop=8 expandtab