Move main YAZ manual to book.xml; use nxml YAZ-758
[yaz-moved-to-github.git] / src / soap.c
index 5bbc9cc..94e0f19 100644 (file)
@@ -1,8 +1,6 @@
-/*
- * Copyright (C) 1995-2005, Index Data ApS
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) Index Data
  * See the file LICENSE for details.
- *
- * $Id: soap.c,v 1.12 2005-08-22 20:34:21 adam Exp $
  */
 /**
  * \file soap.c
  * This implements encoding and decoding of SOAP packages using
  * Libxml2.
  */
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
 
 #include <yaz/soap.h>
+#include <yaz/match_glob.h>
 
-#if HAVE_XML2
+#if YAZ_HAVE_XML2
 #include <libxml/parser.h>
 #include <libxml/tree.h>
 
 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_codec_enc_xsl(ODR o, Z_SOAP **pp, 
+int z_soap_codec_enc_xsl(ODR o, Z_SOAP **pp,
                          char **content_buf, int *content_len,
                          Z_SOAP_Handler *handlers,
                          const char *encoding,
@@ -45,10 +47,55 @@ int z_soap_codec_enc_xsl(ODR o, Z_SOAP **pp,
             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 ||
-            xmlStrcmp(ptr->name, BAD_CAST "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",
@@ -81,7 +128,7 @@ int z_soap_codec_enc_xsl(ODR o, Z_SOAP **pp,
                 ptr = ptr->next;
         }
         /* check that Body is present */
-        if (!ptr || ptr->type != XML_ELEMENT_NODE || 
+        if (!ptr || ptr->type != XML_ELEMENT_NODE ||
             xmlStrcmp(ptr->name, BAD_CAST "Body"))
         {
             xmlFreeDoc(doc);
@@ -144,15 +191,18 @@ int z_soap_codec_enc_xsl(ODR o, Z_SOAP **pp,
         }
         else
         {
+            const char *ns = (const char *) ptr->ns->href;
             for (i = 0; handlers[i].ns; i++)
-                if (!xmlStrcmp(ptr->ns->href, BAD_CAST 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);
@@ -168,9 +218,8 @@ int z_soap_codec_enc_xsl(ODR o, Z_SOAP **pp,
             }
             else
             {
-                ret = z_soap_error(o, p, "SOAP-ENV:Client", 
-                                   "No handler for NS",
-                                   (const char *)ptr->ns->href);
+                ret = z_soap_error(o, p, "SOAP-ENV:Client",
+                                   "No handler for NS", ns);
             }
         }
         xmlFreeDoc(doc);
@@ -198,7 +247,7 @@ int z_soap_codec_enc_xsl(ODR o, Z_SOAP **pp,
             Z_SOAP_Fault *f = p->u.fault;
             xmlNodePtr fault_ptr = xmlNewChild(body_ptr, ns_env,
                                                BAD_CAST "Fault", 0);
-            xmlNewChild(fault_ptr, ns_env, BAD_CAST "faultcode", 
+            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);
@@ -209,7 +258,7 @@ int z_soap_codec_enc_xsl(ODR o, Z_SOAP **pp,
         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);
@@ -227,8 +276,8 @@ int z_soap_codec_enc_xsl(ODR o, Z_SOAP **pp,
         }
         if (stylesheet)
         {
-            char *content = odr_malloc(o, strlen(stylesheet) + 40);
-            
+            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",
@@ -254,7 +303,7 @@ int z_soap_codec_enc_xsl(ODR o, Z_SOAP **pp,
     return 0;
 }
 #else
-int z_soap_codec_enc_xsl(ODR o, Z_SOAP **pp, 
+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)
@@ -279,7 +328,7 @@ int z_soap_codec_enc_xsl(ODR o, Z_SOAP **pp,
     return -1;
 }
 #endif
-int z_soap_codec_enc(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)
@@ -288,7 +337,7 @@ int z_soap_codec_enc(ODR o, Z_SOAP **pp,
                                 encoding, 0);
 }
 
-int z_soap_codec(ODR o, Z_SOAP **pp, 
+int z_soap_codec(ODR o, Z_SOAP **pp,
                  char **content_buf, int *content_len,
                  Z_SOAP_Handler *handlers)
 {
@@ -300,7 +349,7 @@ int z_soap_error(ODR o, Z_SOAP *p,
                  const char *details)
 {
     p->which = Z_SOAP_error;
-    p->u.soap_error = (Z_SOAP_Fault *) 
+    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);
@@ -314,6 +363,7 @@ int z_soap_error(ODR o, Z_SOAP *p,
 /*
  * Local variables:
  * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
  * indent-tabs-mode: nil
  * End:
  * vim: shiftwidth=4 tabstop=8 expandtab