Changed include/yaz/diagbib1.h and added include/yaz/diagsrw.h with
[yaz-moved-to-github.git] / src / seshigh.c
index 4a3766f..88dc833 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1995-2005, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: seshigh.c,v 1.48 2005-03-01 20:37:01 adam Exp $
+ * $Id: seshigh.c,v 1.53 2005-04-22 08:27:58 adam Exp $
  */
 /**
  * \file seshigh.c
 #include <unistd.h>
 #endif
 
+#if HAVE_XML2
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#endif
+
 #include <yaz/yconfig.h>
 #include <yaz/xmalloc.h>
 #include <yaz/comstack.h>
@@ -178,6 +183,7 @@ association *create_association(IOCHAN channel, COMSTACK link,
     request_initq(&anew->outgoing);
     anew->proto = cs_getproto(link);
     anew->cql_transform = 0;
+    anew->server_node_ptr = 0;
     return anew;
 }
 
@@ -500,7 +506,8 @@ static int srw_bend_init(association *assoc, Z_SRW_diagnostic **d, int *num)
        if (!(binitres = (*cb->bend_init)(assoc->init)))
        {
            assoc->state = ASSOC_DEAD;
-           yaz_add_srw_diagnostic(assoc->encode, d, num, 3, 0);
+           yaz_add_srw_diagnostic(assoc->encode, d, num,
+                           YAZ_SRW_AUTHENTICATION_ERROR, 0);
            return 0;
        }
        assoc->backend = binitres->handle;
@@ -708,7 +715,8 @@ static void srw_bend_search(association *assoc, request *req,
     srw_bend_init(assoc, &srw_res->diagnostics, &srw_res->num_diagnostics);
     if (srw_req->sort_type != Z_SRW_sort_type_none)
        yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics,
-                              &srw_res->num_diagnostics, 80, 0);
+                              &srw_res->num_diagnostics,
+                              YAZ_SRW_SORT_UNSUPP, 0);
     else if (srw_res->num_diagnostics == 0 && assoc->init)
     {
        bend_search_rr rr;
@@ -766,7 +774,7 @@ static void srw_bend_search(association *assoc, request *req,
                int code = yaz_pqf_error (pqf_parser, &pqf_msg, &off);
                yaz_log(log_requestdetail, "Parse error %d %s near offset %d",
                        code, pqf_msg, off);
-               srw_error = 10;
+               srw_error = YAZ_SRW_QUERY_SYNTAX_ERROR;
            }
            
            rr.query->which = Z_Query_type_1;
@@ -777,7 +785,8 @@ static void srw_bend_search(association *assoc, request *req,
        else
        {
            yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics,
-                                  &srw_res->num_diagnostics, 11, 0);
+                                  &srw_res->num_diagnostics,
+                                  YAZ_SRW_UNSUPP_QUERY_TYPE, 0);
        }
        if (rr.query->u.type_1)
        {
@@ -796,7 +805,7 @@ static void srw_bend_search(association *assoc, request *req,
            (assoc->init->bend_search)(assoc->backend, &rr);
            if (rr.errcode)
            {
-               if (rr.errcode == 109) /* database unavailable */
+               if (rr.errcode == YAZ_BIB1_DATABASE_UNAVAILABLE)
                {
                    *http_code = 404;
                }
@@ -826,7 +835,7 @@ static void srw_bend_search(association *assoc, request *req,
                    {
                        yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics,
                                               &srw_res->num_diagnostics,
-                                              61, 0);
+                                              YAZ_SRW_FIRST_RECORD_POSITION_OUT_OF_RANGE, 0);
                    }
                    else
                    {
@@ -908,6 +917,42 @@ static void srw_bend_search(association *assoc, request *req,
     }
 }
 
+static char *srw_bend_explain_default(void *handle, bend_explain_rr *rr)
+{
+#if HAVE_XML2
+    xmlNodePtr ptr = rr->server_node_ptr;
+    if (!ptr)
+       return 0;
+    for (ptr = ptr->children; ptr; ptr = ptr->next)
+    {
+       if (ptr->type != XML_ELEMENT_NODE)
+           continue;
+       if (!strcmp((const char *) ptr->name, "explain"))
+       {
+           int len;
+           xmlDocPtr doc = xmlNewDoc("1.0");
+           xmlChar *buf_out;
+           char *content;
+
+           ptr = xmlCopyNode(ptr, 1);
+        
+           xmlDocSetRootElement(doc, ptr);
+           
+           xmlDocDumpMemory(doc, &buf_out, &len);
+           content = (char*) odr_malloc(rr->stream, 1+len);
+           memcpy(content, buf_out, len);
+           content[len] = '\0';
+           
+           xmlFree(buf_out);
+           xmlFreeDoc(doc);
+           rr->explain_buf = content;
+           return 0;
+       }
+    }
+#endif
+    return 0;
+}
+
 static void srw_bend_explain(association *assoc, request *req,
                              Z_SRW_explainRequest *srw_req,
                              Z_SRW_explainResponse *srw_res,
@@ -916,30 +961,35 @@ static void srw_bend_explain(association *assoc, request *req,
     yaz_log(log_requestdetail, "Got SRW ExplainRequest");
     *http_code = 404;
     srw_bend_init(assoc, &srw_res->diagnostics, &srw_res->num_diagnostics);
-    if (assoc->init && assoc->init->bend_explain)
-    {
-        bend_explain_rr rr;
-
-        rr.stream = assoc->encode;
-        rr.decode = assoc->decode;
-        rr.print = assoc->print;
-        rr.explain_buf = 0;
-        rr.database = srw_req->database;
-        rr.schema = "http://explain.z3950.org/dtd/2.0/";
-        (*assoc->init->bend_explain)(assoc->backend, &rr);
-        if (rr.explain_buf)
-        {
-            int packing = Z_SRW_recordPacking_string;
-            if (srw_req->recordPacking && 
-                !strcmp(srw_req->recordPacking, "xml"))
-                packing = Z_SRW_recordPacking_XML;
-            srw_res->record.recordSchema = rr.schema;
-            srw_res->record.recordPacking = packing;
-            srw_res->record.recordData_buf = rr.explain_buf;
-            srw_res->record.recordData_len = strlen(rr.explain_buf);
-            srw_res->record.recordPosition = 0;
-            *http_code = 200;
-        }
+    if (assoc->init)
+    {
+       bend_explain_rr rr;
+       
+       rr.stream = assoc->encode;
+       rr.decode = assoc->decode;
+       rr.print = assoc->print;
+       rr.explain_buf = 0;
+       rr.database = srw_req->database;
+       rr.server_node_ptr = assoc->server_node_ptr;
+       rr.schema = "http://explain.z3950.org/dtd/2.0/";
+       if (assoc->init->bend_explain)
+           (*assoc->init->bend_explain)(assoc->backend, &rr);
+       else
+           srw_bend_explain_default(assoc->backend, &rr);
+
+       if (rr.explain_buf)
+       {
+           int packing = Z_SRW_recordPacking_string;
+           if (srw_req->recordPacking && 
+               !strcmp(srw_req->recordPacking, "xml"))
+               packing = Z_SRW_recordPacking_XML;
+           srw_res->record.recordSchema = rr.schema;
+           srw_res->record.recordPacking = packing;
+           srw_res->record.recordData_buf = rr.explain_buf;
+           srw_res->record.recordData_len = strlen(rr.explain_buf);
+           srw_res->record.recordPosition = 0;
+           *http_code = 200;
+       }
     }
 }
 
@@ -1017,10 +1067,11 @@ static void srw_bend_scan(association *assoc, request *req,
        {
            if (assoc->cql_transform)
            {
+               int srw_error;
                bsrr->scanClause = 0;
                bsrr->attributeset = VAL_NONE;
                bsrr->term = odr_malloc(assoc->decode, sizeof(*bsrr->term));
-               int srw_error = cql2pqf_scan(assoc->encode,
+               srw_error = cql2pqf_scan(assoc->encode,
                                             srw_req->scanClause.cql,
                                             assoc->cql_transform,
                                             bsrr->term);
@@ -1046,12 +1097,13 @@ static void srw_bend_scan(association *assoc, request *req,
        else
        {
            yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics,
-                                  &srw_res->num_diagnostics, 4, "scan");
+                                  &srw_res->num_diagnostics,
+                                  YAZ_SRW_UNSUPP_OPERATION, "scan");
        }
        if (bsrr->errcode)
        {
            int srw_error;
-           if (bsrr->errcode == 109) /* database unavailable */
+           if (bsrr->errcode == YAZ_BIB1_DATABASE_UNAVAILABLE)
            {
                *http_code = 404;
                return;
@@ -1591,8 +1643,8 @@ static Z_APDU *process_initRequest(association *assoc, request *reqb)
        /* no backend. return error */
        binitres = odr_malloc(assoc->encode, sizeof(*binitres));
        binitres->errstring = 0;
-       binitres->errcode = 1;
-        iochan_settimeout(assoc->client_chan, 10);
+       binitres->errcode = YAZ_BIB1_PERMANENT_SYSTEM_ERROR;
+       iochan_settimeout(assoc->client_chan, 10);
     }
     if ((assoc->init->bend_sort))
        yaz_log (YLOG_DEBUG, "Sort handler installed");
@@ -1712,7 +1764,7 @@ static Z_APDU *process_initRequest(association *assoc, request *reqb)
                 assoc->init->implementation_name,
                 odr_prepend(assoc->encode, "GFS", resp->implementationName));
 
-    version = odr_strdup(assoc->encode, "$Revision: 1.48 $");
+    version = odr_strdup(assoc->encode, "$Revision: 1.53 $");
     if (strlen(version) > 10)   /* check for unexpanded CVS strings */
         version[strlen(version)-2] = '\0';
     resp->implementationVersion = odr_prepend(assoc->encode,
@@ -1855,7 +1907,8 @@ static Z_Records *pack_records(association *a, char *setname, int start,
                 *pres = Z_PresentStatus_failure;
                 /* for 'present request out of range',
                    set addinfo to record position if not set */
-                if (freq.errcode == 13 && freq.errstring == 0)
+                if (freq.errcode == YAZ_BIB1_PRESENT_REQUEST_OUT_OF_RANGE  && 
+                               freq.errstring == 0)
                 {
                     sprintf (s, "%d", recno);
                     freq.errstring = s;
@@ -1918,10 +1971,10 @@ static Z_Records *pack_records(association *a, char *setname, int start,
         if (!(thisrec = (Z_NamePlusRecord *)
               odr_malloc(a->encode, sizeof(*thisrec))))
             return 0;
-        if (!(thisrec->databaseName = (char *)odr_malloc(a->encode,
-            strlen(freq.basename) + 1)))
-            return 0;
-        strcpy(thisrec->databaseName, freq.basename);
+       if (freq.basename)
+           thisrec->databaseName = odr_strdup(a->encode, freq.basename);
+       else
+           thisrec->databaseName = 0;
         thisrec->which = Z_NamePlusRecord_databaseRecord;
 
         if (freq.output_format_raw)