Add z_HTTP_header_add_basic_auth()
[yaz-moved-to-github.git] / src / srw.c
index bda1844..54aa7ba 100644 (file)
--- a/src/srw.c
+++ b/src/srw.c
@@ -1,8 +1,8 @@
 /*
- * Copyright (C) 1995-2006, Index Data ApS
+ * Copyright (C) 1995-2007, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: srw.c,v 1.52 2006-12-06 21:35:58 adam Exp $
+ * $Id: srw.c,v 1.57 2007-08-23 14:23:23 adam Exp $
  */
 /**
  * \file srw.c
@@ -126,46 +126,6 @@ static int match_xsd_string(xmlNodePtr ptr, const char *elem, ODR o,
     return match_xsd_string_n(ptr, elem, o, val, 0);
 }
 
-
-/** \brief fixes NS for root node of record data (bug #740) */
-static void fixup_xmlns(xmlNodePtr ptr, ODR o)
-{
-    /* should go towards root and collect NS not defined in the record here! */
-    xmlNodePtr p = ptr;
-
-    while (p)
-    {
-        assert(p->type == XML_ELEMENT_NODE);
-
-        p = p->parent;
-        while (p && p->type != XML_ELEMENT_NODE)
-            p = p->prev;
-        if (p)
-        {
-            xmlNsPtr ns = p->ns;
-            for (; ns; ns = ns->next)
-            {
-                xmlNsPtr n;
-                for (n = ptr->nsDef; n; n = n->next)
-                    if ((n->prefix == 0 && ns->prefix == 0)
-                        || (n->prefix && ns->prefix 
-                            && !strcmp((const char *) n->prefix,
-                                       (const char *) ns->prefix)))
-                    {
-                        break;
-                    }
-                if (!n)
-                {
-                    xmlNsPtr new_ns = xmlCopyNamespace(ns);
-                    
-                    new_ns->next = ptr->nsDef;
-                    ptr->nsDef = new_ns;
-                }
-            }
-        }
-    }
-}
-
 static int match_xsd_XML_n(xmlNodePtr ptr, const char *elem, ODR o,
                            char **val, int *len)
 {
@@ -174,19 +134,27 @@ static int match_xsd_XML_n(xmlNodePtr ptr, const char *elem, ODR o,
     if (!match_element(ptr, elem))
         return 0;
 
-    ptr = ptr->children;
-    while (ptr && (ptr->type == XML_TEXT_NODE || ptr->type == XML_COMMENT_NODE))
-        ptr = ptr->next;
-    if (!ptr)
-        return 0;
-
-    fixup_xmlns(ptr, o);
-
     buf = xmlBufferCreate();
 
-    xmlNodeDump(buf, ptr->doc, ptr, 0, 0);
+    /* Copy each element nodes at top.
+       In most cases there is only one root node.. At least one server
+       http://www.theeuropeanlibrary.org/sru/sru.pl
+       has multiple root nodes in recordData.
+    */
+    for (ptr = ptr->children; ptr; ptr = ptr->next)
+    {
+        if (ptr->type == XML_ELEMENT_NODE)
+        {
+            /* copy node to get NS right (bug #740). */
+            xmlNode *tmp = xmlCopyNode(ptr, 1);
+            
+            xmlNodeDump(buf, tmp->doc, tmp, 0, 0);
+            
+            xmlFreeNode(tmp);
+        }
+    }
     
-    *val = odr_malloc(o, buf->use+1);
+    *val = (char *) odr_malloc(o, buf->use+1);
     memcpy (*val, buf->content, buf->use);
     (*val)[buf->use] = '\0';
 
@@ -228,6 +196,16 @@ static int match_xsd_integer(xmlNodePtr ptr, const char *elem, ODR o, int **val)
     return 1;
 }
 
+char *yaz_negotiate_sru_version(char *input_ver)
+{
+    if (!input_ver)
+        input_ver = "1.1";
+
+    if (!strcmp(input_ver, "1.1"))
+        return "1.1";
+    return  "1.2"; /* our latest supported version */
+}
+
 static int yaz_srw_record(ODR o, xmlNodePtr pptr, Z_SRW_record *rec,
                           Z_SRW_extra_record **extra,
                           void *client_data, const char *ns)
@@ -258,12 +236,8 @@ static int yaz_srw_record(ODR o, xmlNodePtr pptr, Z_SRW_record *rec,
                 ;
             else if (match_xsd_string(ptr, "recordPacking", o, &spack))
             {
-                if (spack && !strcmp(spack, "xml"))
-                    pack = Z_SRW_recordPacking_XML;
-                if (spack && !strcmp(spack, "url"))
-                    pack = Z_SRW_recordPacking_URL;
-                if (spack && !strcmp(spack, "string"))
-                    pack = Z_SRW_recordPacking_string;
+                if (spack)
+                    pack = yaz_srw_str_to_pack(spack);
             }
             else if (match_xsd_integer(ptr, "recordPosition", o, 
                                        &rec->recordPosition))
@@ -317,22 +291,22 @@ static int yaz_srw_record(ODR o, xmlNodePtr pptr, Z_SRW_record *rec,
     {
         xmlNodePtr ptr = pptr;
         int pack = rec->recordPacking;
-        add_xsd_string(ptr, "recordSchema", rec->recordSchema);
+        const char *spack = yaz_srw_pack_to_str(pack);
 
+        add_xsd_string(ptr, "recordSchema", rec->recordSchema);
+        if (spack)
+            add_xsd_string(ptr, "recordPacking", spack);
         switch(pack)
         {
         case Z_SRW_recordPacking_string:
-            add_xsd_string(ptr, "recordPacking", "string");
             add_xsd_string_n(ptr, "recordData", rec->recordData_buf,
                              rec->recordData_len);
             break;
         case Z_SRW_recordPacking_XML:
-            add_xsd_string(ptr, "recordPacking", "xml");
             add_XML_n(ptr, "recordData", rec->recordData_buf,
                       rec->recordData_len, 0);
             break;
         case Z_SRW_recordPacking_URL:
-            add_xsd_string(ptr, "recordPacking", "url");
             add_xsd_string_n(ptr, "recordData", rec->recordData_buf,
                              rec->recordData_len);
             break;
@@ -630,6 +604,7 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
     {
         Z_SRW_PDU **p = handler_data;
         xmlNodePtr method = pptr->children;
+        char *neg_version;
 
         while (method && method->type == XML_TEXT_NODE)
             method = method->next;
@@ -887,6 +862,9 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
             *p = 0;
             return -1;
         }
+        neg_version = yaz_negotiate_sru_version((*p)->srw_version);
+        if (neg_version)
+            (*p)->srw_version = neg_version;
     }
     else if (o->direction == ODR_ENCODE)
     {