X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=src%2Fsoap.c;h=94e0f1942e6dac8f191302300332cf14bb94c568;hp=64310bc26485d8215b589b90d16502cf94c6cea9;hb=f0df1959fda559c0d952810c338a9fde667b5a63;hpb=2f5de47d0b100194d42e6ae9d17a994e8203da0d diff --git a/src/soap.c b/src/soap.c index 64310bc..94e0f19 100644 --- a/src/soap.c +++ b/src/soap.c @@ -1,39 +1,33 @@ -/* - * Copyright (c) 2002-2003, Index Data. +/* This file is part of the YAZ toolkit. + * Copyright (C) Index Data * See the file LICENSE for details. + */ +/** + * \file soap.c + * \brief Implements SOAP * - * $Id: soap.c,v 1.2 2003-12-18 23:04:23 adam Exp $ + * This implements encoding and decoding of SOAP packages using + * Libxml2. */ +#if HAVE_CONFIG_H +#include +#endif #include +#include -#if HAVE_XML2 +#if YAZ_HAVE_XML2 #include #include static const char *soap_v1_1 = "http://schemas.xmlsoap.org/soap/envelope/"; static const char *soap_v1_2 = "http://www.w3.org/2001/06/soap-envelope"; -int z_soap_error(ODR o, Z_SOAP *p, - const char *fault_code, const char *fault_string, - const char *details) -{ - p->which = Z_SOAP_error; - p->u.soap_error = (Z_SOAP_Fault *) - odr_malloc(o, sizeof(*p->u.soap_error)); - p->u.soap_error->fault_code = odr_strdup(o, fault_code); - p->u.soap_error->fault_string = odr_strdup(o, fault_string); - if (details) - p->u.soap_error->details = odr_strdup(o, details); - else - p->u.soap_error->details = 0; - return -1; -} - -int z_soap_codec_enc(ODR o, Z_SOAP **pp, - char **content_buf, int *content_len, - Z_SOAP_Handler *handlers, - const char *encoding) +int z_soap_codec_enc_xsl(ODR o, Z_SOAP **pp, + char **content_buf, int *content_len, + Z_SOAP_Handler *handlers, + const char *encoding, + const char *stylesheet) { if (o->direction == ODR_DECODE) { @@ -52,10 +46,56 @@ int z_soap_codec_enc(ODR o, Z_SOAP **pp, if (!doc) return z_soap_error(o, p, "SOAP-ENV:Client", "Bad XML Document", 0); - /* check that root node is Envelope */ + ptr = xmlDocGetRootElement(doc); - if (!ptr || ptr->type != XML_ELEMENT_NODE || - strcmp(ptr->name, "Envelope") || !ptr->ns) + if (!ptr || ptr->type != XML_ELEMENT_NODE || !ptr->ns) + { + xmlFreeDoc(doc); + return z_soap_error(o, p, "SOAP-ENV:Client", + "No Envelope element", 0); + } + /* check for SRU root node match */ + for (i = 0; handlers[i].ns; i++) + { + const char *hns = handlers[i].ns; + if (strchr(hns, ':')) + { + if (yaz_match_glob(hns, (const char *) ptr->ns->href)) + break; + } + else + { + if (yaz_match_glob(hns, (const char *) ptr->name)) + break; + } + } + if (handlers[i].ns) + { + void *handler_data = 0; + xmlNode p_top_tmp; /* pseudo parent node needed */ + + p_top_tmp.children = ptr; + ret = (*handlers[i].f)(o, &p_top_tmp, &handler_data, + handlers[i].client_data, + (const char *)ptr->ns->href); + + if (ret || !handler_data) + z_soap_error(o, p, "SOAP-ENV:Client", + "SOAP Handler returned error", 0); + else + { + p->which = Z_SOAP_generic; + p->u.generic = (Z_SOAP_Generic *) + odr_malloc(o, sizeof(*p->u.generic)); + p->u.generic->no = i; + p->u.generic->ns = handlers[i].ns; + p->u.generic->p = handler_data; + } + xmlFreeDoc(doc); + return ret; + } + /* OK: assume SOAP */ + if (xmlStrcmp(ptr->name, BAD_CAST "Envelope")) { xmlFreeDoc(doc); return z_soap_error(o, p, "SOAP-ENV:Client", @@ -64,7 +104,7 @@ int z_soap_codec_enc(ODR o, Z_SOAP **pp, else { /* determine SOAP version */ - const char * ns_envelope = ptr->ns->href; + const char * ns_envelope = (const char *) ptr->ns->href; if (!strcmp(ns_envelope, soap_v1_1)) p->ns = soap_v1_1; else if (!strcmp(ns_envelope, soap_v1_2)) @@ -80,22 +120,22 @@ int z_soap_codec_enc(ODR o, Z_SOAP **pp, while(ptr && ptr->type == XML_TEXT_NODE) ptr = ptr->next; if (ptr && ptr->type == XML_ELEMENT_NODE && - !strcmp(ptr->ns->href, p->ns) && - !strcmp(ptr->name, "Header")) + !xmlStrcmp(ptr->ns->href, BAD_CAST p->ns) && + !xmlStrcmp(ptr->name, BAD_CAST "Header")) { ptr = ptr->next; while(ptr && ptr->type == XML_TEXT_NODE) ptr = ptr->next; } /* check that Body is present */ - if (!ptr || ptr->type != XML_ELEMENT_NODE || - strcmp(ptr->name, "Body")) + if (!ptr || ptr->type != XML_ELEMENT_NODE || + xmlStrcmp(ptr->name, BAD_CAST "Body")) { xmlFreeDoc(doc); return z_soap_error(o, p, "SOAP-ENV:Client", "SOAP Body element not found", 0); } - if (strcmp(ptr->ns->href, p->ns)) + if (xmlStrcmp(ptr->ns->href, BAD_CAST p->ns)) { xmlFreeDoc(doc); return z_soap_error(o, p, "SOAP-ENV:Client", @@ -111,14 +151,20 @@ int z_soap_codec_enc(ODR o, Z_SOAP **pp, return z_soap_error(o, p, "SOAP-ENV:Client", "SOAP No content for Body", 0); } + if (!ptr->ns) + { + xmlFreeDoc(doc); + return z_soap_error(o, p, "SOAP-ENV:Client", + "SOAP No namespace for content", 0); + } /* check for fault package */ - if (!strcmp(ptr->ns->href, p->ns) - && !strcmp(ptr->name, "Fault") && ptr->children) + if (!xmlStrcmp(ptr->ns->href, BAD_CAST p->ns) + && !xmlStrcmp(ptr->name, BAD_CAST "Fault") && ptr->children) { ptr = ptr->children; p->which = Z_SOAP_fault; - p->u.fault = odr_malloc(o, sizeof(*p->u.fault)); + p->u.fault = (Z_SOAP_Fault *) odr_malloc(o, sizeof(*p->u.fault)); p->u.fault->fault_code = 0; p->u.fault->fault_string = 0; p->u.fault->details = 0; @@ -126,15 +172,18 @@ int z_soap_codec_enc(ODR o, Z_SOAP **pp, { if (ptr->children && ptr->children->type == XML_TEXT_NODE) { - if (!strcmp(ptr->name, "faultcode")) + if (!xmlStrcmp(ptr->name, BAD_CAST "faultcode")) p->u.fault->fault_code = - odr_strdup(o, ptr->children->content); - if (!strcmp(ptr->name, "faultstring")) + odr_strdup(o, (const char *) + ptr->children->content); + if (!xmlStrcmp(ptr->name, BAD_CAST "faultstring")) p->u.fault->fault_string = - odr_strdup(o, ptr->children->content); - if (!strcmp(ptr->name, "details")) + odr_strdup(o, (const char *) + ptr->children->content); + if (!xmlStrcmp(ptr->name, BAD_CAST "details")) p->u.fault->details = - odr_strdup(o, ptr->children->content); + odr_strdup(o, (const char *) + ptr->children->content); } ptr = ptr->next; } @@ -142,22 +191,26 @@ int z_soap_codec_enc(ODR o, Z_SOAP **pp, } else { + const char *ns = (const char *) ptr->ns->href; for (i = 0; handlers[i].ns; i++) - if (!strcmp(ptr->ns->href, handlers[i].ns)) + { + if (strchr(handlers[i].ns, ':') && + yaz_match_glob(handlers[i].ns, ns)) break; + } if (handlers[i].ns) { void *handler_data = 0; ret = (*handlers[i].f)(o, pptr, &handler_data, - handlers[i].client_data, - handlers[i].ns); + handlers[i].client_data, ns); if (ret || !handler_data) z_soap_error(o, p, "SOAP-ENV:Client", "SOAP Handler returned error", 0); else { p->which = Z_SOAP_generic; - p->u.generic = odr_malloc(o, sizeof(*p->u.generic)); + p->u.generic = (Z_SOAP_Generic *) + odr_malloc(o, sizeof(*p->u.generic)); p->u.generic->no = i; p->u.generic->ns = handlers[i].ns; p->u.generic->p = handler_data; @@ -165,8 +218,8 @@ int z_soap_codec_enc(ODR o, Z_SOAP **pp, } else { - ret = z_soap_error(o, p, "SOAP-ENV:Client", - "No handler for NS", ptr->ns->href); + ret = z_soap_error(o, p, "SOAP-ENV:Client", + "No handler for NS", ns); } } xmlFreeDoc(doc); @@ -178,41 +231,58 @@ int z_soap_codec_enc(ODR o, Z_SOAP **pp, xmlNsPtr ns_env; xmlNodePtr envelope_ptr, body_ptr; - xmlDocPtr doc = xmlNewDoc("1.0"); + xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0"); - envelope_ptr = xmlNewNode(0, "Envelope"); - ns_env = xmlNewNs(envelope_ptr, p->ns, "SOAP-ENV"); + envelope_ptr = xmlNewNode(0, BAD_CAST "Envelope"); + ns_env = xmlNewNs(envelope_ptr, BAD_CAST p->ns, + BAD_CAST "SOAP-ENV"); xmlSetNs(envelope_ptr, ns_env); - body_ptr = xmlNewChild(envelope_ptr, ns_env, "Body", 0); + body_ptr = xmlNewChild(envelope_ptr, ns_env, BAD_CAST "Body", + 0); xmlDocSetRootElement(doc, envelope_ptr); if (p->which == Z_SOAP_fault || p->which == Z_SOAP_error) { Z_SOAP_Fault *f = p->u.fault; - xmlNodePtr fault_ptr = xmlNewChild(body_ptr, ns_env, "Fault", 0); - xmlNewChild(fault_ptr, ns_env, "faultcode", f->fault_code); - xmlNewChild(fault_ptr, ns_env, "faultstring", f->fault_string); + xmlNodePtr fault_ptr = xmlNewChild(body_ptr, ns_env, + BAD_CAST "Fault", 0); + xmlNewChild(fault_ptr, ns_env, BAD_CAST "faultcode", + BAD_CAST f->fault_code); + xmlNewChild(fault_ptr, ns_env, BAD_CAST "faultstring", + BAD_CAST f->fault_string); if (f->details) - xmlNewChild(fault_ptr, ns_env, "details", f->details); + xmlNewChild(fault_ptr, ns_env, BAD_CAST "details", + BAD_CAST f->details); } else if (p->which == Z_SOAP_generic) { int ret, no = p->u.generic->no; - + ret = (*handlers[no].f)(o, body_ptr, &p->u.generic->p, handlers[no].client_data, handlers[no].ns); if (ret) - { - xmlFreeNode(envelope_ptr); - xmlFreeDoc(doc); + { + xmlFreeDoc(doc); return ret; - } + } } if (p->which == Z_SOAP_generic && !strcmp(p->ns, "SRU")) { xmlDocSetRootElement(doc, body_ptr->children); + body_ptr->children = 0; + xmlFreeNode(envelope_ptr); + } + if (stylesheet) + { + char *content = (char *) odr_malloc(o, strlen(stylesheet) + 40); + + xmlNodePtr pi, ptr = xmlDocGetRootElement(doc); + sprintf(content, "type=\"text/xsl\" href=\"%s\"", stylesheet); + pi = xmlNewPI(BAD_CAST "xml-stylesheet", + BAD_CAST content); + xmlAddPrevSibling(ptr, pi); } if (1) { @@ -227,16 +297,16 @@ int z_soap_codec_enc(ODR o, Z_SOAP **pp, memcpy(*content_buf, buf_out, len_out); xmlFree(buf_out); } - xmlFreeNode(envelope_ptr); xmlFreeDoc(doc); return 0; } return 0; } #else -int z_soap_codec_enc(ODR o, Z_SOAP **pp, - char **content_buf, int *content_len, - Z_SOAP_Handler *handlers, const char *encoding) +int z_soap_codec_enc_xsl(ODR o, Z_SOAP **pp, + char **content_buf, int *content_len, + Z_SOAP_Handler *handlers, const char *encoding, + const char *stylesheet) { static char *err_xml = "\n" @@ -258,10 +328,44 @@ int z_soap_codec_enc(ODR o, Z_SOAP **pp, return -1; } #endif -int z_soap_codec(ODR o, Z_SOAP **pp, +int z_soap_codec_enc(ODR o, Z_SOAP **pp, + char **content_buf, int *content_len, + Z_SOAP_Handler *handlers, + const char *encoding) +{ + return z_soap_codec_enc_xsl(o, pp, content_buf, content_len, handlers, + encoding, 0); +} + +int z_soap_codec(ODR o, Z_SOAP **pp, char **content_buf, int *content_len, Z_SOAP_Handler *handlers) { return z_soap_codec_enc(o, pp, content_buf, content_len, handlers, 0); } +int z_soap_error(ODR o, Z_SOAP *p, + const char *fault_code, const char *fault_string, + const char *details) +{ + p->which = Z_SOAP_error; + p->u.soap_error = (Z_SOAP_Fault *) + odr_malloc(o, sizeof(*p->u.soap_error)); + p->u.soap_error->fault_code = odr_strdup(o, fault_code); + p->u.soap_error->fault_string = odr_strdup(o, fault_string); + if (details) + p->u.soap_error->details = odr_strdup(o, details); + else + p->u.soap_error->details = 0; + return -1; +} + +/* + * Local variables: + * c-basic-offset: 4 + * c-file-style: "Stroustrup" + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ +