SRU support for frontend server
authorAdam Dickmeiss <adam@indexdata.dk>
Tue, 18 Mar 2003 13:34:35 +0000 (13:34 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Tue, 18 Mar 2003 13:34:35 +0000 (13:34 +0000)
CHANGELOG
include/yaz/nmem.h
include/yaz/odr.h
odr/odr_mem.c
server/seshigh.c
util/nmemsdup.c
zutil/soap.c
zutil/srw.c

index eb3f90c..f5312b3 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,7 @@
 Possible compatibility problems with earlier versions marked with '*'.
 
+SRU protocol support for frontend server.
+
 Fix compile bug for systems that have nl_langinfo but CODESET undefined.
 
 Added missing PQF transform rules for <= and >= . Thanks to Peter Popovics.
index 2a11b2b..bf29b6a 100644 (file)
@@ -23,7 +23,7 @@
  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  *
- * $Id: nmem.h,v 1.10 2003-01-06 08:20:27 adam Exp $
+ * $Id: nmem.h,v 1.11 2003-03-18 13:34:35 adam Exp $
  */
 
 #ifndef NMEM_H
@@ -64,6 +64,7 @@ typedef struct nmem_control *NMEM;
 YAZ_EXPORT void nmem_reset(NMEM n);
 YAZ_EXPORT int nmem_total(NMEM n);
 YAZ_EXPORT char *nmem_strdup (NMEM mem, const char *src);
+YAZ_EXPORT char *nmem_strdupn (NMEM mem, const char *src, size_t n);
 YAZ_EXPORT int *nmem_intdup (NMEM mem, int v);
 YAZ_EXPORT void nmem_transfer (NMEM dst, NMEM src);
 
index b9bd91f..bfd4d35 100644 (file)
@@ -23,7 +23,7 @@
  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  *
- * $Id: odr.h,v 1.9 2003-03-11 11:03:30 adam Exp $
+ * $Id: odr.h,v 1.10 2003-03-18 13:34:35 adam Exp $
  */
 
 #ifndef ODR_H
@@ -194,6 +194,7 @@ YAZ_EXPORT void odr_setbuf(ODR o, char *buf, int len, int can_grow);
 YAZ_EXPORT char *odr_getbuf(ODR o, int *len, int *size);
 YAZ_EXPORT void *odr_malloc(ODR o, int size);
 YAZ_EXPORT char *odr_strdup(ODR o, const char *str);
+YAZ_EXPORT char *odr_strdupn(ODR o, const char *str, size_t n);
 YAZ_EXPORT int *odr_intdup(ODR o, int v);
 YAZ_EXPORT NMEM odr_extract_mem(ODR o);
 YAZ_EXPORT Odr_null *odr_nullval(void);
index 43f3c54..2ec348a 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: odr_mem.c,v 1.22 2003-03-11 11:03:31 adam Exp $
+ * $Id: odr_mem.c,v 1.23 2003-03-18 13:34:35 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
@@ -37,6 +37,11 @@ char *odr_strdup(ODR o, const char *str)
     return nmem_strdup(o->mem, str);
 }
 
+char *odr_strdupn(ODR o, const char *str, size_t n)
+{
+    return nmem_strdupn(o->mem, str, n);
+}
+
 int *odr_intdup(ODR o, int v)
 {
     return nmem_intdup(o->mem, v);
index e8c6439..5f8a5c2 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: seshigh.c,v 1.148 2003-03-11 11:09:17 adam Exp $
+ * $Id: seshigh.c,v 1.149 2003-03-18 13:34:36 adam Exp $
  */
 
 /*
@@ -539,8 +539,10 @@ static void srw_bend_search(association *assoc, request *req,
     Z_External *ext;
     
     yaz_log(LOG_LOG, "Got SRW SearchRetrieveRequest");
+    yaz_log(LOG_DEBUG, "srw_bend_search");
     if (!assoc->init)
     {
+        yaz_log(LOG_DEBUG, "srw_bend_init");
         if (!srw_bend_init(assoc))
         {
             srw_error = 3;  /* assume Authentication error */
@@ -612,6 +614,7 @@ static void srw_bend_search(association *assoc, request *req,
 
     if (srw_error)
     {
+        yaz_log(LOG_DEBUG, "srw_bend_search returned SRW error %d", srw_error);
         srw_res->num_diagnostics = 1;
         srw_res->diagnostics = (Z_SRW_diagnostic *)
            odr_malloc(assoc->encode, sizeof(*srw_res->diagnostics));
@@ -636,6 +639,7 @@ static void srw_bend_search(association *assoc, request *req,
     srw_res->numberOfRecords = odr_intdup(assoc->encode, rr.hits);
     if (rr.errcode)
     {
+        yaz_log(LOG_DEBUG, "bend_search returned Bib-1 code %d", rr.errcode);
         srw_res->num_diagnostics = 1;
         srw_res->diagnostics = (Z_SRW_diagnostic *)
            odr_malloc(assoc->encode, sizeof(*srw_res->diagnostics));
@@ -643,6 +647,9 @@ static void srw_bend_search(association *assoc, request *req,
             odr_intdup(assoc->encode, 
                        yaz_diag_bib1_to_srw (rr.errcode));
         srw_res->diagnostics[0].details = rr.errstring;
+        yaz_log(LOG_DEBUG, "srw_bend_search returned SRW error %d",
+                srw_res->diagnostics[0].code);
+                
     }
     else
     {
@@ -652,8 +659,13 @@ static void srw_bend_search(association *assoc, request *req,
             int number = *srw_req->maximumRecords;
             int start = 1;
             int i;
+
             if (srw_req->startRecord)
                 start = *srw_req->startRecord;
+
+            yaz_log(LOG_DEBUG, "srw_bend_search. start=%d max=%d",
+                    start, *srw_req->maximumRecords);
+
             if (start <= rr.hits)
             {
                 int j = 0;
@@ -666,6 +678,7 @@ static void srw_bend_search(association *assoc, request *req,
                 {
                     int errcode;
                     srw_res->records[j].recordData_buf = 0;
+                    yaz_log(LOG_DEBUG, "srw_bend_fetch %d", i+start);
                     errcode = srw_bend_fetch(assoc, i+start, srw_req,
                                              srw_res->records + j);
                     if (errcode)
@@ -691,6 +704,70 @@ static void srw_bend_search(association *assoc, request *req,
     }
 }
 
+static int hex_digit (int ch)
+{
+    if (ch >= '0' && ch <= '9')
+        return ch - '0';
+    else if (ch >= 'a' && ch <= 'f')
+        return ch - 'a'+10;
+    else if (ch >= 'A' && ch <= 'F')
+        return ch - 'A'+10;
+    return 0;
+}
+
+static char *uri_val(const char *path, const char *name, ODR o)
+{
+    size_t nlen = strlen(name);
+    if (*path != '?')
+        return 0;
+    path++;
+    while (path && *path)
+    {
+        const char *p1 = strchr(path, '=');
+        if (!p1)
+            break;
+        if (p1 - path == nlen && !memcmp(path, name, nlen))
+        {
+            size_t i = 0;
+            char *ret;
+            
+            path = p1 + 1;
+            p1 = strchr(path, '&');
+            if (!p1)
+                p1 = strlen(path) + path;
+            ret = odr_malloc(o, p1 - path + 1);
+            while (*path && *path != '&')
+            {
+                if (*path == '+')
+                {
+                    ret[i++] = ' ';
+                    path++;
+                }
+                else if (*path == '%' && path[1] && path[2])
+                {
+                    ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
+                    path = path + 3;
+                }
+                else
+                    ret[i++] = *path++;
+            }
+            ret[i] = '\0';
+            return ret;
+        }
+        path = strchr(p1, '&');
+        if (path)
+            path++;
+    }
+    return 0;
+}
+
+void uri_val_int(const char *path, const char *name, ODR o, int **intp)
+{
+    const char *v = uri_val(path, name, o);
+    if (v)
+        *intp = odr_intdup(o, atoi(v));
+}
+
 static void process_http_request(association *assoc, request *req)
 {
     Z_HTTP_Request *hreq = req->gdu_request->u.HTTP_Request;
@@ -701,6 +778,94 @@ static void process_http_request(association *assoc, request *req)
 
     if (!strcmp(hreq->method, "GET"))
     {
+        char *charset = 0;
+        int ret = -1;
+        Z_SOAP *soap_package = 0;
+        char *db = "Default";
+        const char *p0 = hreq->path, *p1;
+        static Z_SOAP_Handler soap_handlers[2] = {
+#if HAVE_XML2
+            {"http://www.loc.gov/zing/srw/v1.0/", 0,
+             (Z_SOAP_fun) yaz_srw_codec},
+#endif
+            {0, 0, 0}
+        };
+        
+        if (*p0 == '/')
+            p0++;
+        p1 = strchr(p0, '?');
+        if (!p1)
+            p1 = p0 + strlen(p0);
+        if (p1 != p0)
+        {
+            db = odr_malloc(assoc->decode, p1 - p0 + 1);
+            memcpy (db, p0, p1 - p0);
+            db[p1 - p0] = '\0';
+        }
+
+        if (p1 && *p1 == '?' && p1[1])
+        {
+            Z_SRW_PDU *res = yaz_srw_get(o, Z_SRW_searchRetrieve_response);
+            Z_SRW_PDU *sr = yaz_srw_get(o, Z_SRW_searchRetrieve_request);
+            char *query = uri_val(p1, "query", o);
+            char *pQuery = uri_val(p1, "pQuery", o);
+            char *sortKeys = uri_val(p1, "sortKeys", o);
+            
+            if (query)
+            {
+                sr->u.request->query_type = Z_SRW_query_type_cql;
+                sr->u.request->query.cql = query;
+            }
+            if (pQuery)
+            {
+                sr->u.request->query_type = Z_SRW_query_type_pqf;
+                sr->u.request->query.pqf = pQuery;
+            }
+            if (sortKeys)
+            {
+                sr->u.request->sort_type = Z_SRW_sort_type_sort;
+                sr->u.request->sort.sortKeys = sortKeys;
+            }
+            sr->u.request->recordSchema = uri_val(p1, "recordSchema", o);
+            uri_val_int(p1, "maximumRecords", o, 
+                        &sr->u.request->maximumRecords);
+            uri_val_int(p1, "startRecord", o,
+                        &sr->u.request->startRecord);
+            if (sr->u.request->startRecord)
+                yaz_log(LOG_LOG, "startRecord=%d", *sr->u.request->startRecord);
+            sr->u.request->database = db;
+            srw_bend_search(assoc, req, sr->u.request,
+                            res->u.response);
+            
+            soap_package = odr_malloc(o, sizeof(*soap_package));
+            soap_package->which = Z_SOAP_generic;
+
+            soap_package->u.generic =
+                odr_malloc(o, sizeof(*soap_package->u.generic));
+
+            soap_package->u.generic->p = res;
+            soap_package->u.generic->ns = soap_handlers[0].ns;
+            soap_package->u.generic->no = 0;
+            
+            soap_package->ns = "SRU";
+
+            p = z_get_HTTP_Response(o, 200);
+            hres = p->u.HTTP_Response;
+
+            ret = z_soap_codec_enc(assoc->encode, &soap_package,
+                                   &hres->content_buf, &hres->content_len,
+                                   soap_handlers, charset);
+            if (!charset)
+                z_HTTP_header_add(o, &hres->headers, "Content-Type", "text/xml");
+            else
+            {
+                char ctype[60];
+                strcpy(ctype, "text/xml; charset=");
+                strcat(ctype, charset);
+                z_HTTP_header_add(o, &hres->headers, "Content-Type", ctype);
+            }
+
+        }
 #ifdef DOCDIR
        if (strlen(hreq->path) >= 5 && strlen(hreq->path) < 80 &&
                         !memcmp(hreq->path, "/doc/", 5))
index 0c32d71..33a643e 100644 (file)
@@ -1,23 +1,8 @@
 /*
- * Copyright (c) 1997-2001, Index Data.
+ * Copyright (c) 1997-2003, Index Data.
  * See the file LICENSE for details.
  *
- * $Log: nmemsdup.c,v $
- * Revision 1.5  2001-03-25 21:55:13  adam
- * Added odr_intdup. Ztest server returns TaskPackage for ItemUpdate.
- *
- * Revision 1.4  2000/02/29 13:44:55  adam
- * Check for config.h (currently not generated).
- *
- * Revision 1.3  1999/11/30 13:47:12  adam
- * Improved installation. Moved header files to include/yaz.
- *
- * Revision 1.2  1998/02/11 11:53:36  adam
- * Changed code so that it compiles as C++.
- *
- * Revision 1.1  1997/09/17 12:10:42  adam
- * YAZ version 1.4.
- *
+ * $Id: nmemsdup.c,v 1.6 2003-03-18 13:34:37 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
@@ -33,6 +18,14 @@ char *nmem_strdup (NMEM mem, const char *src)
     return dst;
 }
 
+char *nmem_strdupn (NMEM mem, const char *src, size_t n)
+{
+    char *dst = (char *)nmem_malloc (mem, n+1);
+    memcpy (dst, src, n);
+    dst[n] = '\0';
+    return dst;
+}
+
 int *nmem_intdup(NMEM mem, int v)
 {
     int *dst = (int*) nmem_malloc (mem, sizeof(int));
index d848cf9..0b34cdb 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 2002-2003, Index Data.
  * See the file LICENSE for details.
  *
- * $Id: soap.c,v 1.6 2003-03-11 11:09:17 adam Exp $
+ * $Id: soap.c,v 1.7 2003-03-18 13:34:37 adam Exp $
  */
 
 #include <yaz/soap.h>
@@ -184,8 +184,6 @@ int z_soap_codec_enc(ODR o, Z_SOAP **pp,
         Z_SOAP *p = *pp;
         xmlNsPtr ns_env;
         xmlNodePtr envelope_ptr, body_ptr;
-        xmlChar *buf_out;
-        int len_out;
 
         xmlDocPtr doc = xmlNewDoc("1.0");
 
@@ -215,14 +213,23 @@ int z_soap_codec_enc(ODR o, Z_SOAP **pp,
             if (ret)
                 return ret;
         }
-       if (encoding)
-            xmlDocDumpMemoryEnc(doc, &buf_out, &len_out, encoding);
-       else
-            xmlDocDumpMemory(doc, &buf_out, &len_out);
-        *content_buf = (char *) odr_malloc(o, len_out);
-        *content_len = len_out;
-        memcpy(*content_buf, buf_out, len_out);
-        xmlFree(buf_out);
+        if (p->which == Z_SOAP_generic && !strcmp(p->ns, "SRU"))
+        {
+            xmlDocSetRootElement(doc, body_ptr->children);
+        }
+        if (1)
+        {
+            xmlChar *buf_out;
+            int len_out;
+            if (encoding)
+                xmlDocDumpMemoryEnc(doc, &buf_out, &len_out, encoding);
+            else
+                xmlDocDumpMemory(doc, &buf_out, &len_out);
+            *content_buf = (char *) odr_malloc(o, len_out);
+            *content_len = len_out;
+            memcpy(*content_buf, buf_out, len_out);
+            xmlFree(buf_out);
+        }
         xmlFreeDoc(doc);
         return 0;
     }
index 813908d..2078563 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 2002-2003, Index Data.
  * See the file LICENSE for details.
  *
- * $Id: srw.c,v 1.8 2003-03-03 19:57:37 adam Exp $
+ * $Id: srw.c,v 1.9 2003-03-18 13:34:37 adam Exp $
  */
 
 #include <yaz/srw.h>
@@ -333,7 +333,6 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
                                            &res->nextRecordPosition))
                     ;
             }
-
         }
         else
             return -1;
@@ -345,9 +344,12 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
         if ((*p)->which == Z_SRW_searchRetrieve_request)
         {
             Z_SRW_searchRetrieveRequest *req = (*p)->u.request;
-            xmlNsPtr ns_srw = xmlNewNs(pptr, ns, "zs");
-            xmlNodePtr ptr = xmlNewChild(pptr, ns_srw,
+            xmlNodePtr ptr = xmlNewChild(pptr, 0,
                                          "searchRetrieveRequest", 0);
+            xmlNsPtr ns_srw = xmlNewNs(ptr, ns, "zs");
+
+            xmlSetNs(ptr, ns_srw);
+
             switch(req->query_type)
             {
             case Z_SRW_query_type_cql:
@@ -380,10 +382,11 @@ int yaz_srw_codec(ODR o, void * vptr, Z_SRW_PDU **handler_data,
         else if ((*p)->which == Z_SRW_searchRetrieve_response)
         {
             Z_SRW_searchRetrieveResponse *res = (*p)->u.response;
-            xmlNsPtr ns_srw = xmlNewNs(pptr, ns, "zs");
-            xmlNodePtr ptr = xmlNewChild(pptr, ns_srw,
+            xmlNodePtr ptr = xmlNewChild(pptr, 0,
                                          "searchRetrieveResponse", 0);
+            xmlNsPtr ns_srw = xmlNewNs(ptr, ns, "zs");
 
+            xmlSetNs(ptr, ns_srw);
             add_xsd_integer(ptr, "numberOfRecords", res->numberOfRecords);
             add_xsd_string(ptr, "resultSetId", res->resultSetId);
             add_xsd_integer(ptr, "resultSetIdleTime", res->resultSetIdleTime);