2 * Copyright (c) 2002-2003, Index Data.
3 * See the file LICENSE for details.
5 * $Id: soap.c,v 1.1 2003-02-12 15:06:44 adam Exp $
10 static const char *soap_v1_1 = "http://schemas.xmlsoap.org/soap/envelope/";
11 static const char *soap_v1_2 = "http://www.w3.org/2001/06/soap-envelope";
13 int z_soap_error(ODR o, Z_SOAP *p,
14 const char *fault_code, const char *fault_string,
17 p->which = Z_SOAP_error;
18 p->u.soap_error = odr_malloc(o, sizeof(*p->u.soap_error));
19 p->u.soap_error->fault_code = odr_strdup(o, fault_code);
20 p->u.soap_error->fault_string = odr_strdup(o, fault_string);
22 p->u.soap_error->details = odr_strdup(o, details);
24 p->u.soap_error->details = 0;
28 int z_soap_codec(ODR o, Z_SOAP **pp,
29 char **content_buf, int *content_len,
30 Z_SOAP_Handler *handlers)
32 if (o->direction == ODR_DECODE)
39 if (!content_buf || !*content_buf || !content_len)
42 *pp = p = odr_malloc(o, sizeof(*p));
45 doc = xmlParseMemory(*content_buf, *content_len);
47 return z_soap_error(o, p, "SOAP-ENV:Client",
48 "Bad XML Document", 0);
49 /* check that root node is Envelope */
50 ptr = xmlDocGetRootElement(doc);
51 if (!ptr || ptr->type != XML_ELEMENT_NODE ||
52 strcmp(ptr->name, "Envelope"))
55 return z_soap_error(o, p, "SOAP-ENV:Client",
56 "No Envelope element", 0);
60 /* determine SOAP version */
61 const char * ns_envelope = ptr->ns->href;
62 if (!strcmp(ns_envelope, soap_v1_1))
64 else if (!strcmp(ns_envelope, soap_v1_2))
69 return z_soap_error(o, p, "SOAP-ENV:Client",
70 "Bad SOAP version", 0);
74 while(ptr && ptr->type == XML_TEXT_NODE)
76 if (ptr && ptr->type == XML_ELEMENT_NODE &&
77 !strcmp(ptr->ns->href, p->ns) &&
78 !strcmp(ptr->name, "Header"))
81 while(ptr && ptr->type == XML_TEXT_NODE)
84 /* check that Body is present */
85 if (!ptr || ptr->type != XML_ELEMENT_NODE ||
86 strcmp(ptr->name, "Body"))
89 return z_soap_error(o, p, "SOAP-ENV:Client",
90 "SOAP Body element not found", 0);
92 if (strcmp(ptr->ns->href, p->ns))
95 return z_soap_error(o, p, "SOAP-ENV:Client",
96 "SOAP bad NS for Body element", 0);
100 while (ptr && ptr->type == XML_TEXT_NODE)
102 if (!ptr || ptr->type != XML_ELEMENT_NODE)
105 return z_soap_error(o, p, "SOAP-ENV:Client",
106 "SOAP No content for Body", 0);
108 /* check for fault package */
109 if (!strcmp(ptr->ns->href, p->ns)
110 && !strcmp(ptr->name, "Fault") && ptr->children)
114 p->which = Z_SOAP_fault;
115 p->u.fault = odr_malloc(o, sizeof(*p->u.fault));
116 p->u.fault->fault_code = 0;
117 p->u.fault->fault_string = 0;
118 p->u.fault->details = 0;
121 if (ptr->children && ptr->children->type == XML_TEXT_NODE)
123 if (!strcmp(ptr->name, "faultcode"))
124 p->u.fault->fault_code =
125 odr_strdup(o, ptr->children->content);
126 if (!strcmp(ptr->name, "faultstring"))
127 p->u.fault->fault_string =
128 odr_strdup(o, ptr->children->content);
129 if (!strcmp(ptr->name, "details"))
130 p->u.fault->details =
131 odr_strdup(o, ptr->children->content);
139 for (i = 0; handlers[i].ns; i++)
140 if (!strcmp(ptr->ns->href, handlers[i].ns))
144 void *handler_data = 0;
145 ret = (*handlers[i].f)(o, pptr, &handler_data,
146 handlers[i].client_data,
148 if (ret || !handler_data)
149 z_soap_error(o, p, "SOAP-ENV:Client",
150 "SOAP Handler returned error", 0);
153 p->which = Z_SOAP_generic;
154 p->u.generic = odr_malloc(o, sizeof(*p->u.generic));
155 p->u.generic->no = i;
156 p->u.generic->ns = handlers[i].ns;
157 p->u.generic->p = handler_data;
162 ret = z_soap_error(o, p, "SOAP-ENV:Client",
163 "No handler for NS", 0);
169 else if (o->direction == ODR_ENCODE)
173 xmlNodePtr envelope_ptr, body_ptr;
177 xmlDocPtr doc = xmlNewDoc("1.0");
179 envelope_ptr = xmlNewNode(0, "Envelope");
180 ns_env = xmlNewNs(envelope_ptr, p->ns, "SOAP-ENV");
181 body_ptr = xmlNewChild(envelope_ptr, ns_env, "Body", 0);
182 xmlDocSetRootElement(doc, envelope_ptr);
184 if (p->which == Z_SOAP_fault || p->which == Z_SOAP_error)
186 Z_SOAP_Fault *f = p->u.fault;
187 xmlNodePtr fault_ptr = xmlNewChild(body_ptr, ns_env, "Fault", 0);
188 xmlNewChild(fault_ptr, ns_env, "faultcode", f->fault_code);
189 xmlNewChild(fault_ptr, ns_env, "faultstring", f->fault_string);
191 xmlNewChild(fault_ptr, ns_env, "details", f->details);
193 else if (p->which == Z_SOAP_generic)
195 int ret, no = p->u.generic->no;
197 ret = (*handlers[no].f)(o, body_ptr, &p->u.generic->p,
198 handlers[no].client_data,
203 xmlDocDumpMemory(doc, &buf_out, &len_out);
204 *content_buf = odr_malloc(o, len_out);
205 *content_len = len_out;
206 memcpy(*content_buf, buf_out, len_out);