2 * Copyright (c) 2002-2003, Index Data.
3 * See the file LICENSE for details.
5 * $Id: soap.c,v 1.4 2003-02-17 22:35:48 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_error(ODR o, Z_SOAP *p,
18 const char *fault_code, const char *fault_string,
21 p->which = Z_SOAP_error;
22 p->u.soap_error = (Z_SOAP_Fault *)
23 odr_malloc(o, sizeof(*p->u.soap_error));
24 p->u.soap_error->fault_code = odr_strdup(o, fault_code);
25 p->u.soap_error->fault_string = odr_strdup(o, fault_string);
27 p->u.soap_error->details = odr_strdup(o, details);
29 p->u.soap_error->details = 0;
33 int z_soap_codec(ODR o, Z_SOAP **pp,
34 char **content_buf, int *content_len,
35 Z_SOAP_Handler *handlers)
37 if (o->direction == ODR_DECODE)
44 if (!content_buf || !*content_buf || !content_len)
47 *pp = p = (Z_SOAP *) odr_malloc(o, sizeof(*p));
50 doc = xmlParseMemory(*content_buf, *content_len);
52 return z_soap_error(o, p, "SOAP-ENV:Client",
53 "Bad XML Document", 0);
54 /* check that root node is Envelope */
55 ptr = xmlDocGetRootElement(doc);
56 if (!ptr || ptr->type != XML_ELEMENT_NODE ||
57 strcmp(ptr->name, "Envelope") || !ptr->ns)
60 return z_soap_error(o, p, "SOAP-ENV:Client",
61 "No Envelope element", 0);
65 /* determine SOAP version */
66 const char * ns_envelope = ptr->ns->href;
67 if (!strcmp(ns_envelope, soap_v1_1))
69 else if (!strcmp(ns_envelope, soap_v1_2))
74 return z_soap_error(o, p, "SOAP-ENV:Client",
75 "Bad SOAP version", 0);
79 while(ptr && ptr->type == XML_TEXT_NODE)
81 if (ptr && ptr->type == XML_ELEMENT_NODE &&
82 !strcmp(ptr->ns->href, p->ns) &&
83 !strcmp(ptr->name, "Header"))
86 while(ptr && ptr->type == XML_TEXT_NODE)
89 /* check that Body is present */
90 if (!ptr || ptr->type != XML_ELEMENT_NODE ||
91 strcmp(ptr->name, "Body"))
94 return z_soap_error(o, p, "SOAP-ENV:Client",
95 "SOAP Body element not found", 0);
97 if (strcmp(ptr->ns->href, p->ns))
100 return z_soap_error(o, p, "SOAP-ENV:Client",
101 "SOAP bad NS for Body element", 0);
105 while (ptr && ptr->type == XML_TEXT_NODE)
107 if (!ptr || ptr->type != XML_ELEMENT_NODE)
110 return z_soap_error(o, p, "SOAP-ENV:Client",
111 "SOAP No content for Body", 0);
113 /* check for fault package */
114 if (!strcmp(ptr->ns->href, p->ns)
115 && !strcmp(ptr->name, "Fault") && ptr->children)
119 p->which = Z_SOAP_fault;
120 p->u.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 (!strcmp(ptr->name, "faultcode"))
129 p->u.fault->fault_code =
130 odr_strdup(o, ptr->children->content);
131 if (!strcmp(ptr->name, "faultstring"))
132 p->u.fault->fault_string =
133 odr_strdup(o, ptr->children->content);
134 if (!strcmp(ptr->name, "details"))
135 p->u.fault->details =
136 odr_strdup(o, ptr->children->content);
144 for (i = 0; handlers[i].ns; i++)
145 if (!strcmp(ptr->ns->href, handlers[i].ns))
149 void *handler_data = 0;
150 ret = (*handlers[i].f)(o, pptr, &handler_data,
151 handlers[i].client_data,
153 if (ret || !handler_data)
154 z_soap_error(o, p, "SOAP-ENV:Client",
155 "SOAP Handler returned error", 0);
158 p->which = Z_SOAP_generic;
159 p->u.generic = 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", 0);
174 else if (o->direction == ODR_ENCODE)
178 xmlNodePtr envelope_ptr, body_ptr;
182 xmlDocPtr doc = xmlNewDoc("1.0");
184 envelope_ptr = xmlNewNode(0, "Envelope");
185 ns_env = xmlNewNs(envelope_ptr, p->ns, "SOAP-ENV");
186 xmlSetNs(envelope_ptr, ns_env);
188 body_ptr = xmlNewChild(envelope_ptr, ns_env, "Body", 0);
189 xmlDocSetRootElement(doc, envelope_ptr);
191 if (p->which == Z_SOAP_fault || p->which == Z_SOAP_error)
193 Z_SOAP_Fault *f = p->u.fault;
194 xmlNodePtr fault_ptr = xmlNewChild(body_ptr, ns_env, "Fault", 0);
195 xmlNewChild(fault_ptr, ns_env, "faultcode", f->fault_code);
196 xmlNewChild(fault_ptr, ns_env, "faultstring", f->fault_string);
198 xmlNewChild(fault_ptr, ns_env, "details", f->details);
200 else if (p->which == Z_SOAP_generic)
202 int ret, no = p->u.generic->no;
204 ret = (*handlers[no].f)(o, body_ptr, &p->u.generic->p,
205 handlers[no].client_data,
210 xmlDocDumpMemory(doc, &buf_out, &len_out);
211 *content_buf = (char *) odr_malloc(o, len_out);
212 *content_len = len_out;
213 memcpy(*content_buf, buf_out, len_out);