2 * Copyright (c) 2002-2004, Index Data.
3 * See the file LICENSE for details.
5 * $Id: soap.c,v 1.5 2004-01-07 20:36:44 adam Exp $
11 #include <libxml/parser.h>
12 #include <libxml/tree.h>
14 static const char *soap_v1_1 = "http://schemas.xmlsoap.org/soap/envelope/";
15 static const char *soap_v1_2 = "http://www.w3.org/2001/06/soap-envelope";
17 int z_soap_codec_enc(ODR o, Z_SOAP **pp,
18 char **content_buf, int *content_len,
19 Z_SOAP_Handler *handlers,
21 const char *stylesheet)
23 if (o->direction == ODR_DECODE)
30 if (!content_buf || !*content_buf || !content_len)
33 *pp = p = (Z_SOAP *) odr_malloc(o, sizeof(*p));
36 doc = xmlParseMemory(*content_buf, *content_len);
38 return z_soap_error(o, p, "SOAP-ENV:Client",
39 "Bad XML Document", 0);
40 /* check that root node is Envelope */
41 ptr = xmlDocGetRootElement(doc);
42 if (!ptr || ptr->type != XML_ELEMENT_NODE ||
43 strcmp(ptr->name, "Envelope") || !ptr->ns)
46 return z_soap_error(o, p, "SOAP-ENV:Client",
47 "No Envelope element", 0);
51 /* determine SOAP version */
52 const char * ns_envelope = ptr->ns->href;
53 if (!strcmp(ns_envelope, soap_v1_1))
55 else if (!strcmp(ns_envelope, soap_v1_2))
60 return z_soap_error(o, p, "SOAP-ENV:Client",
61 "Bad SOAP version", 0);
65 while(ptr && ptr->type == XML_TEXT_NODE)
67 if (ptr && ptr->type == XML_ELEMENT_NODE &&
68 !strcmp(ptr->ns->href, p->ns) &&
69 !strcmp(ptr->name, "Header"))
72 while(ptr && ptr->type == XML_TEXT_NODE)
75 /* check that Body is present */
76 if (!ptr || ptr->type != XML_ELEMENT_NODE ||
77 strcmp(ptr->name, "Body"))
80 return z_soap_error(o, p, "SOAP-ENV:Client",
81 "SOAP Body element not found", 0);
83 if (strcmp(ptr->ns->href, p->ns))
86 return z_soap_error(o, p, "SOAP-ENV:Client",
87 "SOAP bad NS for Body element", 0);
91 while (ptr && ptr->type == XML_TEXT_NODE)
93 if (!ptr || ptr->type != XML_ELEMENT_NODE)
96 return z_soap_error(o, p, "SOAP-ENV:Client",
97 "SOAP No content for Body", 0);
102 return z_soap_error(o, p, "SOAP-ENV:Client",
103 "SOAP No namespace for content", 0);
105 /* check for fault package */
106 if (!strcmp(ptr->ns->href, p->ns)
107 && !strcmp(ptr->name, "Fault") && ptr->children)
111 p->which = Z_SOAP_fault;
112 p->u.fault = odr_malloc(o, sizeof(*p->u.fault));
113 p->u.fault->fault_code = 0;
114 p->u.fault->fault_string = 0;
115 p->u.fault->details = 0;
118 if (ptr->children && ptr->children->type == XML_TEXT_NODE)
120 if (!strcmp(ptr->name, "faultcode"))
121 p->u.fault->fault_code =
122 odr_strdup(o, ptr->children->content);
123 if (!strcmp(ptr->name, "faultstring"))
124 p->u.fault->fault_string =
125 odr_strdup(o, ptr->children->content);
126 if (!strcmp(ptr->name, "details"))
127 p->u.fault->details =
128 odr_strdup(o, ptr->children->content);
136 for (i = 0; handlers[i].ns; i++)
137 if (!strcmp(ptr->ns->href, handlers[i].ns))
141 void *handler_data = 0;
142 ret = (*handlers[i].f)(o, pptr, &handler_data,
143 handlers[i].client_data,
145 if (ret || !handler_data)
146 z_soap_error(o, p, "SOAP-ENV:Client",
147 "SOAP Handler returned error", 0);
150 p->which = Z_SOAP_generic;
151 p->u.generic = odr_malloc(o, sizeof(*p->u.generic));
152 p->u.generic->no = i;
153 p->u.generic->ns = handlers[i].ns;
154 p->u.generic->p = handler_data;
159 ret = z_soap_error(o, p, "SOAP-ENV:Client",
160 "No handler for NS", ptr->ns->href);
166 else if (o->direction == ODR_ENCODE)
170 xmlNodePtr envelope_ptr, body_ptr;
172 xmlDocPtr doc = xmlNewDoc("1.0");
174 envelope_ptr = xmlNewNode(0, "Envelope");
175 ns_env = xmlNewNs(envelope_ptr, p->ns, "SOAP-ENV");
176 xmlSetNs(envelope_ptr, ns_env);
178 body_ptr = xmlNewChild(envelope_ptr, ns_env, "Body", 0);
179 xmlDocSetRootElement(doc, envelope_ptr);
181 if (p->which == Z_SOAP_fault || p->which == Z_SOAP_error)
183 Z_SOAP_Fault *f = p->u.fault;
184 xmlNodePtr fault_ptr = xmlNewChild(body_ptr, ns_env, "Fault", 0);
185 xmlNewChild(fault_ptr, ns_env, "faultcode", f->fault_code);
186 xmlNewChild(fault_ptr, ns_env, "faultstring", f->fault_string);
188 xmlNewChild(fault_ptr, ns_env, "details", f->details);
190 else if (p->which == Z_SOAP_generic)
192 int ret, no = p->u.generic->no;
194 ret = (*handlers[no].f)(o, body_ptr, &p->u.generic->p,
195 handlers[no].client_data,
203 if (p->which == Z_SOAP_generic && !strcmp(p->ns, "SRU"))
205 xmlDocSetRootElement(doc, body_ptr->children);
209 char *content = odr_malloc(o, strlen(stylesheet) + 40);
211 xmlNodePtr pi, ptr = xmlDocGetRootElement(doc);
212 sprintf(content, "type=\"text/xsl\" href=\"%s\"", stylesheet);
213 pi = xmlNewPI("xml-stylesheet", content);
214 xmlAddPrevSibling(ptr, pi);
221 xmlDocDumpMemoryEnc(doc, &buf_out, &len_out, encoding);
223 xmlDocDumpMemory(doc, &buf_out, &len_out);
224 *content_buf = (char *) odr_malloc(o, len_out);
225 *content_len = len_out;
226 memcpy(*content_buf, buf_out, len_out);
235 int z_soap_codec_enc(ODR o, Z_SOAP **pp,
236 char **content_buf, int *content_len,
237 Z_SOAP_Handler *handlers, const char *encoding,
238 const char *stylesheet)
240 static char *err_xml =
241 "<?xml version=\"1.0\"?>\n"
243 " xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
244 "\t<SOAP-ENV:Body>\n"
245 "\t\t<SOAP-ENV:Fault>\n"
246 "\t\t\t<faultcode>SOAP-ENV:Server</faultcode>\n"
247 "\t\t\t<faultstring>HTTP error</faultstring>\n"
248 "\t\t\t<detail>SOAP not supported in this YAZ configuration</detail>\n"
249 "\t\t</SOAP-ENV:Fault>\n"
250 "\t</SOAP-ENV:Body>\n"
251 "</SOAP-ENV:Envelope>\n";
252 if (o->direction == ODR_ENCODE)
254 *content_buf = err_xml;
255 *content_len = strlen(err_xml);
260 int z_soap_codec(ODR o, Z_SOAP **pp,
261 char **content_buf, int *content_len,
262 Z_SOAP_Handler *handlers)
264 return z_soap_codec_enc(o, pp, content_buf, content_len, handlers, 0, 0);
267 int z_soap_error(ODR o, Z_SOAP *p,
268 const char *fault_code, const char *fault_string,
271 p->which = Z_SOAP_error;
272 p->u.soap_error = (Z_SOAP_Fault *)
273 odr_malloc(o, sizeof(*p->u.soap_error));
274 p->u.soap_error->fault_code = odr_strdup(o, fault_code);
275 p->u.soap_error->fault_string = odr_strdup(o, fault_string);
277 p->u.soap_error->details = odr_strdup(o, details);
279 p->u.soap_error->details = 0;