Bump year
[yaz-moved-to-github.git] / src / zoom-c.c
index 6078c93..6b43ad6 100644 (file)
@@ -1,11 +1,14 @@
 /*
- * Copyright (c) 2000-2004, Index Data
+ * Copyright (C) 1995-2005, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: zoom-c.c,v 1.24 2004-02-14 15:58:42 adam Exp $
- *
- * ZOOM layer for C, connections, result sets, queries.
+ * $Id: zoom-c.c,v 1.35 2005-01-15 19:47:15 adam Exp $
+ */
+/**
+ * \file zoom-c.c
+ * \brief Implements ZOOM C interface.
  */
+
 #include <assert.h>
 #include <string.h>
 #include "zoom-p.h"
@@ -25,6 +28,9 @@
 #include <sys/poll.h>
 #endif
 
+static int log_level=0;
+static int log_level_initialized=0;
+
 typedef enum {
     zoom_pending,
     zoom_complete
@@ -91,6 +97,12 @@ static void set_dset_error (ZOOM_connection c, int error,
                             const char *addinfo, const char *addinfo2)
 {
     char *cp;
+    if (!log_level_initialized)
+    {
+        log_level=yaz_log_module_level("zoom");
+        log_level_initialized=1;
+    }
+
     xfree (c->addinfo);
     c->addinfo = 0;
     c->error = error;
@@ -104,14 +116,14 @@ static void set_dset_error (ZOOM_connection c, int error,
     }
     if (addinfo && addinfo2)
     {
-        c->addinfo = xmalloc(strlen(addinfo) + strlen(addinfo2) + 2);
+        c->addinfo = (char*) xmalloc(strlen(addinfo) + strlen(addinfo2) + 2);
         strcpy(c->addinfo, addinfo);
         strcat(c->addinfo, addinfo2);
     }
     else if (addinfo)
         c->addinfo = xstrdup(addinfo);
     if (error)
-        yaz_log(LOG_DEBUG, "Error %s %s:%d %s %s",
+        yaz_log(log_level, "Error %s %s:%d %s %s",
                 c->host_port ? c->host_port : "<>", dset, error,
                 addinfo ? addinfo : "",
                 addinfo2 ? addinfo2 : "");
@@ -185,7 +197,6 @@ void ZOOM_connection_remove_task (ZOOM_connection c)
        switch (task->which)
        {
        case ZOOM_TASK_SEARCH:
-
            ZOOM_resultset_destroy (task->u.search.resultset);
            break;
        case ZOOM_TASK_RETRIEVE:
@@ -199,6 +210,10 @@ void ZOOM_connection_remove_task (ZOOM_connection c)
         case ZOOM_TASK_PACKAGE:
             ZOOM_package_destroy (task->u.package);
             break;
+       case ZOOM_TASK_SORT:
+           ZOOM_resultset_destroy (task->u.sort.resultset);
+           ZOOM_query_destroy(task->u.sort.q);
+           break;
        default:
            assert (0);
        }
@@ -221,6 +236,12 @@ ZOOM_connection_create (ZOOM_options options)
 {
     ZOOM_connection c = (ZOOM_connection) xmalloc (sizeof(*c));
 
+    if (!log_level_initialized)
+    {
+        log_level=yaz_log_module_level("zoom");
+        log_level_initialized=1;
+    }
+
     c->proto = PROTO_Z3950;
     c->cs = 0;
     c->mask = 0;
@@ -333,13 +354,19 @@ ZOOM_connection_connect(ZOOM_connection c,
     const char *val;
     ZOOM_task task;
 
+    if (!log_level_initialized)
+    {
+        log_level=yaz_log_module_level("zoom");
+        log_level_initialized=1;
+    }
+
     if (c->cs)
     {
-        yaz_log (LOG_DEBUG, "reconnect");
+        yaz_log (log_level, "reconnect");
         c->reconnect_ok = 1;
         return;
     }
-    yaz_log(LOG_DEBUG, "connect");
+    yaz_log(log_level, "connect");
     xfree (c->proxy);
     val = ZOOM_options_get (c->options, "proxy");
     if (val && *val)
@@ -415,7 +442,7 @@ ZOOM_query_destroy(ZOOM_query s)
        return;
 
     (s->refcount)--;
-    yaz_log (LOG_DEBUG, "ZOOM_query_destroy count=%d", s->refcount);
+    yaz_log (log_level, "ZOOM_query_destroy count=%d", s->refcount);
     if (s->refcount == 0)
     {
        odr_destroy (s->odr);
@@ -504,15 +531,22 @@ void ZOOM_resultset_addref (ZOOM_resultset r)
     if (r)
     {
        (r->refcount)++;
-        yaz_log (LOG_DEBUG, "ZOOM_resultset_addref r=%p count=%d",
+        yaz_log (log_level, "ZOOM_resultset_addref r=%p count=%d",
                  r, r->refcount);
     }
 }
+
 ZOOM_resultset ZOOM_resultset_create ()
 {
     ZOOM_resultset r = (ZOOM_resultset) xmalloc (sizeof(*r));
 
-    yaz_log (LOG_DEBUG, "ZOOM_resultset_create r = %p", r);
+    if (!log_level_initialized)
+    {
+        log_level=yaz_log_module_level("zoom");
+        log_level_initialized=1;
+    }
+
+    yaz_log (log_level, "ZOOM_resultset_create r = %p", r);
     r->refcount = 1;
     r->size = 0;
     r->odr = odr_createmem (ODR_ENCODE);
@@ -580,12 +614,12 @@ ZOOM_connection_search(ZOOM_connection c, ZOOM_query q)
     {
         if (!c->cs)
         {
-            yaz_log(LOG_DEBUG, "NO COMSTACK");
+            yaz_log(log_level, "NO COMSTACK");
             ZOOM_connection_add_task(c, ZOOM_TASK_CONNECT);
         }
         else
         {
-            yaz_log(LOG_DEBUG, "PREPARE FOR RECONNECT");
+            yaz_log(log_level, "PREPARE FOR RECONNECT");
             c->reconnect_ok = 1;
         }
     }
@@ -605,26 +639,73 @@ ZOOM_connection_search(ZOOM_connection c, ZOOM_query q)
 }
 
 ZOOM_API(void)
+    ZOOM_resultset_sort(ZOOM_resultset r,
+                       const char *sort_type, const char *sort_spec)
+{
+    ZOOM_connection c = r->connection;
+    ZOOM_task task;
+
+    if (!c)
+       return;
+
+    if (c->host_port && c->proto == PROTO_HTTP)
+    {
+        if (!c->cs)
+        {
+            yaz_log(log_level, "NO COMSTACK");
+            ZOOM_connection_add_task(c, ZOOM_TASK_CONNECT);
+        }
+        else
+        {
+            yaz_log(log_level, "PREPARE FOR RECONNECT");
+            c->reconnect_ok = 1;
+        }
+    }
+    
+    ZOOM_resultset_cache_reset(r);
+    task = ZOOM_connection_add_task (c, ZOOM_TASK_SORT);
+    task->u.sort.resultset = r;
+    task->u.sort.q = ZOOM_query_create();
+    ZOOM_query_sortby(task->u.sort.q, sort_spec);
+
+    ZOOM_resultset_addref (r);  
+
+    if (!c->async)
+    {
+       while (ZOOM_event (1, &c))
+           ;
+    }
+}
+
+ZOOM_API(void)
+    ZOOM_resultset_cache_reset(ZOOM_resultset r)
+{
+    ZOOM_record_cache rc;
+    
+    for (rc = r->record_cache; rc; rc = rc->next)
+    {
+       if (rc->rec.wrbuf_marc)
+           wrbuf_free (rc->rec.wrbuf_marc, 1);
+       if (rc->rec.wrbuf_iconv)
+           wrbuf_free (rc->rec.wrbuf_iconv, 1);
+       if (rc->rec.wrbuf_opac)
+           wrbuf_free (rc->rec.wrbuf_opac, 1);
+    }
+    r->record_cache = 0;
+}
+
+ZOOM_API(void)
 ZOOM_resultset_destroy(ZOOM_resultset r)
 {
     if (!r)
         return;
     (r->refcount)--;
-    yaz_log (LOG_DEBUG, "ZOOM_resultset_destroy r = %p count=%d",
+    yaz_log (log_level, "ZOOM_resultset_destroy r = %p count=%d",
              r, r->refcount);
     if (r->refcount == 0)
     {
-        ZOOM_record_cache rc;
+       ZOOM_resultset_cache_reset(r);
 
-        for (rc = r->record_cache; rc; rc = rc->next)
-       {
-            if (rc->rec.wrbuf_marc)
-                wrbuf_free (rc->rec.wrbuf_marc, 1);
-            if (rc->rec.wrbuf_iconv)
-                wrbuf_free (rc->rec.wrbuf_iconv, 1);
-            if (rc->rec.wrbuf_opac)
-                wrbuf_free (rc->rec.wrbuf_opac, 1);
-       }
        if (r->connection)
        {
            /* remove ourselves from the resultsets in connection */
@@ -681,12 +762,12 @@ static void ZOOM_resultset_retrieve (ZOOM_resultset r,
     {
         if (!c->cs)
         {
-            yaz_log(LOG_DEBUG, "NO COMSTACK");
+            yaz_log(log_level, "NO COMSTACK");
             ZOOM_connection_add_task(c, ZOOM_TASK_CONNECT);
         }
         else
         {
-            yaz_log(LOG_DEBUG, "PREPARE FOR RECONNECT");
+            yaz_log(log_level, "PREPARE FOR RECONNECT");
             c->reconnect_ok = 1;
         }
     }
@@ -731,19 +812,39 @@ ZOOM_resultset_records (ZOOM_resultset r, ZOOM_record *recs,
     }
 }
 
+static void get_cert(ZOOM_connection c)
+{
+    char *cert_buf;
+    int cert_len;
+    
+    if (cs_get_peer_certificate_x509(c->cs, &cert_buf, &cert_len))
+    {
+        ZOOM_connection_option_setl(c, "sslPeerCert",
+                                   cert_buf, cert_len);
+       xfree(cert_buf);
+    }
+}
+
 static zoom_ret do_connect (ZOOM_connection c)
 {
     void *add;
     const char *effective_host;
+    if (!log_level_initialized)
+    {
+        log_level=yaz_log_module_level("zoom");
+        log_level_initialized=1;
+    }
+
 
     if (c->proxy)
        effective_host = c->proxy;
     else
        effective_host = c->host_port;
 
-    yaz_log (LOG_DEBUG, "do_connect host=%s", effective_host);
+    yaz_log (log_level, "do_connect host=%s", effective_host);
 
-    assert (!c->cs);
+    if (c->cs)
+       cs_close(c->cs);
     c->cs = cs_create_host (effective_host, 0, &add);
 
     if (c->cs && c->cs->protocol == PROTO_HTTP)
@@ -754,7 +855,7 @@ static zoom_ret do_connect (ZOOM_connection c)
         c->proto = PROTO_HTTP;
         cs_get_host_args(c->host_port, &path);
         xfree(c->path);
-        c->path = xmalloc(strlen(path)+2);
+        c->path = (char*) xmalloc(strlen(path)+2);
         c->path[0] = '/';
         strcpy (c->path+1, path);
 #else
@@ -770,6 +871,7 @@ static zoom_ret do_connect (ZOOM_connection c)
         {
             ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_CONNECT);
             ZOOM_connection_put_event(c, event);
+           get_cert(c);
             if (c->proto == PROTO_Z3950)
                 ZOOM_connection_send_init(c);
             else
@@ -873,7 +975,7 @@ static int encode_APDU(ZOOM_connection c, Z_APDU *a, ODR out)
            z_APDU(odr_pr, &a, 0, 0);
            odr_destroy(odr_pr);
        }
-        yaz_log (LOG_DEBUG, "encoding failed");
+        yaz_log (log_level, "encoding failed");
         set_ZOOM_error(c, ZOOM_ERROR_ENCODE, 0);
        odr_reset(out);
        return -1;
@@ -888,7 +990,7 @@ static zoom_ret send_APDU (ZOOM_connection c, Z_APDU *a)
     assert (a);
     if (encode_APDU(c, a, c->odr_out))
        return zoom_complete;
-    yaz_log(LOG_DEBUG, "send APDU type=%d", a->which);
+    yaz_log(log_level, "send APDU type=%d", a->which);
     c->buf_out = odr_getbuf(c->odr_out, &c->len_out, 0);
     event = ZOOM_Event_create (ZOOM_EVENT_SEND_APDU);
     ZOOM_connection_put_event (c, event);
@@ -935,7 +1037,7 @@ static zoom_ret ZOOM_connection_send_init (ZOOM_connection c)
        ZOOM_options_get(c->options, "implementationName"),
        odr_prepend(c->odr_out, "ZOOM-C", ireq->implementationName));
 
-    version = odr_strdup(c->odr_out, "$Revision: 1.24 $");
+    version = odr_strdup(c->odr_out, "$Revision: 1.35 $");
     if (strlen(version) > 10)  /* check for unexpanded CVS strings */
        version[strlen(version)-2] = '\0';
     ireq->implementationVersion = odr_prepend(c->odr_out,
@@ -1026,7 +1128,7 @@ static zoom_ret send_srw (ZOOM_connection c, Z_SRW_PDU *sr)
     };
     ODR o = odr_createmem(ODR_ENCODE);
     int ret;
-    Z_SOAP *p = odr_malloc(o, sizeof(*p));
+    Z_SOAP *p = (Z_SOAP*) odr_malloc(o, sizeof(*p));
     Z_GDU *gdu;
     ZOOM_Event event;
 
@@ -1048,7 +1150,7 @@ static zoom_ret send_srw (ZOOM_connection c, Z_SRW_PDU *sr)
 
         if (cp0 && cp1)
         {
-            char *h = odr_malloc(c->odr_out, cp1 - cp0 + 1);
+            char *h = (char*) odr_malloc(c->odr_out, cp1 - cp0 + 1);
             memcpy (h, cp0, cp1 - cp0);
             h[cp1-cp0] = '\0';
             z_HTTP_header_add(c->odr_out, &gdu->u.HTTP_Request->headers,
@@ -1067,7 +1169,7 @@ static zoom_ret send_srw (ZOOM_connection c, Z_SRW_PDU *sr)
     z_HTTP_header_add(c->odr_out, &gdu->u.HTTP_Request->headers,
                       "SOAPAction", "\"\"");
     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 = 0;
     p->u.generic->ns = 0;
     p->u.generic->p = sr;
@@ -1283,7 +1385,7 @@ static zoom_ret ZOOM_connection_send_search (ZOOM_connection c)
                     break;
             }
             r->setname = xstrdup (setname);
-            yaz_log (LOG_DEBUG, "allocating set %s", r->setname);
+            yaz_log (log_level, "allocating set %s", r->setname);
         }
         else
             r->setname = xstrdup ("default");
@@ -1537,21 +1639,23 @@ ZOOM_record_get (ZOOM_record rec, const char *type_spec, int *len)
            i++;
        if (!strncmp(type_spec+i, "charset=", 8))
        {
-           cp = type_spec+i+8;
-           for (i = 0; cp[i] && i < sizeof(charset)-1; i++)
+           int j = 0;
+           i = i + 8; /* skip charset= */
+           for (j = 0; type_spec[i]  && j < sizeof(charset)-1; i++, j++)
            {
-               if (cp[i] == ';' || cp[i] == ' ')
+               if (type_spec[i] == ';' || type_spec[i] == ' ')
                    break;
-               charset[i] = cp[i];
+               charset[j] = cp[i];
            }
-           charset[i] = '\0';
+           charset[j] = '\0';
        }
        else if (!strncmp(type_spec+i, "xpath=", 6))
        {
-           cp = type_spec+i+6;
-           for (i = 0; cp[i] && i < sizeof(xpath)-1; i++)
-               xpath[i] = cp[i];
-           xpath[i] = '\0';
+           int j = 0; 
+           i = i + 6;
+           for (j = 0; type_spec[i] && j < sizeof(xpath)-1; i++, j++)
+               xpath[j] = cp[i];
+           xpath[j] = '\0';
        } 
        while (type_spec[i] == ' ')
            i++;
@@ -1597,7 +1701,8 @@ ZOOM_record_get (ZOOM_record rec, const char *type_spec, int *len)
        }
         if (r->which == Z_External_sutrs)
            return record_iconv_return(rec, len,
-                                      r->u.sutrs->buf, r->u.sutrs->len,
+                                      (char*) r->u.sutrs->buf,
+                                      r->u.sutrs->len,
                                       charset);
         else if (r->which == Z_External_octet)
         {
@@ -1882,13 +1987,21 @@ static void handle_records (ZOOM_connection c, Z_Records *sr,
            if (present_phase && p->num_records == 0)
            {
                /* present response and we didn't get any records! */
-                set_ZOOM_error(c, ZOOM_ERROR_DECODE, 0);
+               Z_NamePlusRecord *myrec = 
+                   zget_surrogateDiagRec(resultset->odr, 0, 14, 0);
+               record_cache_add(resultset, myrec, resultset->start);
+               yaz_log(YLOG_LOG, "pseudo record 1, at pos %d",
+                       resultset->start);
            }
        }
        else if (present_phase)
        {
            /* present response and we didn't get any records! */
-            set_ZOOM_error(c, ZOOM_ERROR_DECODE, 0);
+           Z_NamePlusRecord *myrec = 
+               zget_surrogateDiagRec(resultset->odr, 0, 14, 0);
+           record_cache_add(resultset, myrec, resultset->start);
+           yaz_log(YLOG_LOG, "pseudo record 1, at pos %d",
+                   resultset->start);
        }
     }
 }
@@ -1903,7 +2016,7 @@ static void handle_search_response (ZOOM_connection c, Z_SearchResponse *sr)
     ZOOM_resultset resultset;
     ZOOM_Event event;
     
-    yaz_log (LOG_DEBUG, "got search response");
+    yaz_log (log_level, "got search response");
     
     if (!c->tasks || c->tasks->which != ZOOM_TASK_SEARCH)
        return ;
@@ -1949,20 +2062,11 @@ static int scan_response (ZOOM_connection c, Z_ScanResponse *res)
     return 1;
 }
 
-static zoom_ret send_sort (ZOOM_connection c)
+static zoom_ret send_sort (ZOOM_connection c,
+                          ZOOM_resultset resultset)
 {
-    ZOOM_resultset  resultset;
-
-    if (!c->tasks || c->tasks->which != ZOOM_TASK_SEARCH)
-       return zoom_complete;
-
-    resultset = c->tasks->u.search.resultset;
-
     if (c->error)
-    {
        resultset->r_sort_spec = 0;
-       return zoom_complete;
-    }
     if (resultset->r_sort_spec)
     {
        Z_APDU *apdu = zget_APDU(c->odr_out, Z_APDU_sortRequest);
@@ -2554,7 +2658,7 @@ static Z_APDU *create_update_package(ZOOM_package p)
                odr_malloc (p->odr_out, sizeof(Odr_oct));
            notToKeep->elements[0]->u.opaque->size =
                notToKeep->elements[0]->u.opaque->len = strlen(recordIdOpaque);
-           notToKeep->elements[0]->u.opaque->buf =
+           notToKeep->elements[0]->u.opaque->buf = (unsigned char*)
                odr_strdup(p->odr_out, recordIdOpaque);
        }
        else if (recordIdNumber)
@@ -2611,17 +2715,22 @@ ZOOM_API(void)
             apdu->u.extendedServicesRequest->taskSpecificParameters = r;
         }
     }
-    if (!strcmp(type, "create"))  /* create database */
+    else if (!strcmp(type, "create"))  /* create database */
     {
        apdu = create_admin_package(p, Z_ESAdminOriginPartToKeep_create,
                                    0, 0);
     }  
-    if (!strcmp(type, "drop"))  /* drop database */
+    else if (!strcmp(type, "drop"))  /* drop database */
     {
        apdu = create_admin_package(p, Z_ESAdminOriginPartToKeep_drop,
                                    0, 0);
     }
-    if (!strcmp(type, "update")) /* update record(s) */
+    else if (!strcmp(type, "commit"))  /* commit changes */
+    {
+       apdu = create_admin_package(p, Z_ESAdminOriginPartToKeep_commit,
+                                   0, 0);
+    }
+    else if (!strcmp(type, "update")) /* update record(s) */
     {
        apdu = create_update_package(p);
     }
@@ -2698,20 +2807,20 @@ static int ZOOM_connection_exec_task (ZOOM_connection c)
 
     if (!task)
     {
-        yaz_log (LOG_DEBUG, "ZOOM_connection_exec_task task=<null>");
+        yaz_log (log_level, "ZOOM_connection_exec_task task=<null>");
        return 0;
     }
-    yaz_log (LOG_DEBUG, "ZOOM_connection_exec_task type=%d run=%d",
+    yaz_log (log_level, "ZOOM_connection_exec_task type=%d run=%d",
              task->which, task->running);
     if (c->error != ZOOM_ERROR_NONE)
     {
-        yaz_log (LOG_DEBUG, "remove tasks because of error = %d", c->error);
+        yaz_log (log_level, "remove tasks because of error = %d", c->error);
         ZOOM_connection_remove_tasks (c);
         return 0;
     }
     if (task->running)
     {
-        yaz_log (LOG_DEBUG, "task already running");
+        yaz_log (log_level, "task already running");
        return 0;
     }
     task->running = 1;
@@ -2740,27 +2849,35 @@ static int ZOOM_connection_exec_task (ZOOM_connection c)
             break;
         case ZOOM_TASK_PACKAGE:
             ret = send_package(c);
+           break;
+       case ZOOM_TASK_SORT:
+           c->tasks->u.sort.resultset->r_sort_spec = 
+               c->tasks->u.sort.q->sort_spec;
+           ret = send_sort(c, c->tasks->u.sort.resultset);
             break;
         }
     }
     else
     {
-        yaz_log (LOG_DEBUG, "remove tasks because no connection exist");
+        yaz_log (log_level, "remove tasks because no connection exist");
         ZOOM_connection_remove_tasks (c);
     }
     if (ret == zoom_complete)
     {
-        yaz_log (LOG_DEBUG, "task removed (complete)");
+        yaz_log (log_level, "task removed (complete)");
         ZOOM_connection_remove_task (c);
         return 0;
     }
-    yaz_log (LOG_DEBUG, "task pending");
+    yaz_log (log_level, "task pending");
     return 1;
 }
 
 static zoom_ret send_sort_present (ZOOM_connection c)
 {
-    zoom_ret r = send_sort (c);
+    zoom_ret r = zoom_complete;
+
+    if (c->tasks && c->tasks->which == ZOOM_TASK_SEARCH)
+       r = send_sort (c, c->tasks->u.search.resultset);
     if (r == zoom_complete)
        r = send_present (c);
     return r;
@@ -2792,7 +2909,7 @@ static void handle_apdu (ZOOM_connection c, Z_APDU *apdu)
     Z_InitResponse *initrs;
     
     c->mask = 0;
-    yaz_log (LOG_DEBUG, "recv APDU type=%d", apdu->which);
+    yaz_log (log_level, "recv APDU type=%d", apdu->which);
     switch(apdu->which)
     {
     case Z_APDU_initResponse:
@@ -2851,7 +2968,7 @@ static void handle_apdu (ZOOM_connection c, Z_APDU *apdu)
                 int sel;
                 
                 yaz_get_response_charneg(tmpmem, p, &charset, &lang, &sel);
-                yaz_log(LOG_DEBUG, "Target accepted: charset %s, "
+                yaz_log(log_level, "Target accepted: charset %s, "
                         "language %s, select %d",
                         charset ? charset : "none", lang ? lang : "none", sel);
                 if (charset)
@@ -2930,7 +3047,7 @@ static void handle_srw_response(ZOOM_connection c,
 
     resultset->size = 0;
 
-    yaz_log(LOG_DEBUG, "got SRW response OK");
+    yaz_log(log_level, "got SRW response OK");
     
     if (res->numberOfRecords)
         resultset->size = *res->numberOfRecords;
@@ -2958,7 +3075,7 @@ static void handle_srw_response(ZOOM_connection c,
         npr->u.databaseRecord->which = Z_External_octet;
         npr->u.databaseRecord->u.octet_aligned = (Odr_oct *)
             odr_malloc(c->odr_in, sizeof(Odr_oct));
-        npr->u.databaseRecord->u.octet_aligned->buf = 
+        npr->u.databaseRecord->u.octet_aligned->buf = (unsigned char*)
             res->records[i].recordData_buf;
         npr->u.databaseRecord->u.octet_aligned->len = 
             npr->u.databaseRecord->u.octet_aligned->size = 
@@ -2993,7 +3110,7 @@ static void handle_http(ZOOM_connection c, Z_HTTP_Response *hres)
     const char *connection_head = z_HTTP_header_lookup(hres->headers,
                                                        "Connection");
     c->mask = 0;
-    yaz_log (LOG_DEBUG, "handle_http");
+    yaz_log (log_level, "handle_http");
 
     if (content_type && !yaz_strcmp_del("text/xml", content_type, "; "))
     {
@@ -3010,7 +3127,7 @@ static void handle_http(ZOOM_connection c, Z_HTTP_Response *hres)
         if (!ret && soap_package->which == Z_SOAP_generic &&
             soap_package->u.generic->no == 0)
         {
-            Z_SRW_PDU *sr = soap_package->u.generic->p;
+            Z_SRW_PDU *sr = (Z_SRW_PDU*) soap_package->u.generic->p;
             if (sr->which == Z_SRW_searchRetrieve_response)
                 handle_srw_response(c, sr->u.response);
             else
@@ -3060,7 +3177,7 @@ static int do_read (ZOOM_connection c)
     
     r = cs_get (c->cs, &c->buf_in, &c->len_in);
     more = cs_more(c->cs);
-    yaz_log (LOG_DEBUG, "do_read len=%d more=%d", r, more);
+    yaz_log (log_level, "do_read len=%d more=%d", r, more);
     if (r == 1)
        return 0;
     if (r <= 0)
@@ -3069,7 +3186,7 @@ static int do_read (ZOOM_connection c)
         {
             do_close (c);
             c->reconnect_ok = 0;
-            yaz_log (LOG_DEBUG, "reconnect read");
+            yaz_log (log_level, "reconnect read");
             c->tasks->running = 0;
             ZOOM_connection_insert_task (c, ZOOM_TASK_CONNECT);
         }
@@ -3124,14 +3241,14 @@ static zoom_ret do_write_ex (ZOOM_connection c, char *buf_out, int len_out)
     event = ZOOM_Event_create(ZOOM_EVENT_SEND_DATA);
     ZOOM_connection_put_event (c, event);
 
-    yaz_log (LOG_DEBUG, "do_write_ex len=%d", len_out);
+    yaz_log (log_level, "do_write_ex len=%d", len_out);
     if ((r=cs_put (c->cs, buf_out, len_out)) < 0)
     {
         if (c->reconnect_ok)
         {
             do_close (c);
             c->reconnect_ok = 0;
-            yaz_log (LOG_DEBUG, "reconnect write");
+            yaz_log (log_level, "reconnect write");
             c->tasks->running = 0;
             ZOOM_connection_insert_task (c, ZOOM_TASK_CONNECT);
             return zoom_pending;
@@ -3150,12 +3267,12 @@ static zoom_ret do_write_ex (ZOOM_connection c, char *buf_out, int len_out)
             c->mask += ZOOM_SELECT_WRITE;
         if (c->cs->io_pending & CS_WANT_READ)
             c->mask += ZOOM_SELECT_READ;
-        yaz_log (LOG_DEBUG, "do_write_ex 1 mask=%d", c->mask);
+        yaz_log (log_level, "do_write_ex 1 mask=%d", c->mask);
     }
     else
     {
         c->mask = ZOOM_SELECT_READ|ZOOM_SELECT_EXCEPT;
-        yaz_log (LOG_DEBUG, "do_write_ex 2 mask=%d", c->mask);
+        yaz_log (log_level, "do_write_ex 2 mask=%d", c->mask);
     }
     return zoom_pending;
 }
@@ -3174,11 +3291,18 @@ ZOOM_connection_option_get (ZOOM_connection c, const char *key)
 
 ZOOM_API(void)
 ZOOM_connection_option_set (ZOOM_connection c, const char *key,
-                                  const char *val)
+                           const char *val)
 {
     ZOOM_options_set (c->options, key, val);
 }
 
+ZOOM_API(void)
+ZOOM_connection_option_setl (ZOOM_connection c, const char *key,
+                            const char *val, int len)
+{
+    ZOOM_options_setl (c->options, key, val, len);
+}
+
 ZOOM_API(const char *)
 ZOOM_resultset_option_get (ZOOM_resultset r, const char *key)
 {
@@ -3285,7 +3409,7 @@ static int ZOOM_connection_do_io(ZOOM_connection c, int mask)
 {
     ZOOM_Event event = 0;
     int r = cs_look(c->cs);
-    yaz_log (LOG_DEBUG, "ZOOM_connection_do_io c=%p mask=%d cs_look=%d",
+    yaz_log (log_level, "ZOOM_connection_do_io c=%p mask=%d cs_look=%d",
             c, mask, r);
     
     if (r == CS_NONE)
@@ -3301,7 +3425,7 @@ static int ZOOM_connection_do_io(ZOOM_connection c, int mask)
         event = ZOOM_Event_create (ZOOM_EVENT_CONNECT);
 
         ret = cs_rcvconnect (c->cs);
-        yaz_log (LOG_DEBUG, "cs_rcvconnect returned %d", ret);
+        yaz_log (log_level, "cs_rcvconnect returned %d", ret);
         if (ret == 1)
         {
             c->mask = ZOOM_SELECT_EXCEPT;
@@ -3314,6 +3438,7 @@ static int ZOOM_connection_do_io(ZOOM_connection c, int mask)
         else if (ret == 0)
         {
             ZOOM_connection_put_event (c, event);
+           get_cert(c);
             if (c->proto == PROTO_Z3950)
                 ZOOM_connection_send_init(c);
             else
@@ -3485,9 +3610,9 @@ ZOOM_event (int no, ZOOM_connection *cs)
 #else
     tv.tv_sec = timeout;
     tv.tv_usec = 0;
-    yaz_log (LOG_DEBUG, "select start");
+    yaz_log (log_level, "select start");
     r = select (max_fd+1, &input, &output, &except, &tv);
-    yaz_log (LOG_DEBUG, "select stop, returned r=%d", r);
+    yaz_log (log_level, "select stop, returned r=%d", r);
     for (i = 0; i<no; i++)
     {
        ZOOM_connection c = cs[i];
@@ -3515,7 +3640,7 @@ ZOOM_event (int no, ZOOM_connection *cs)
            /* timeout and this connection was waiting */
            set_ZOOM_error(c, ZOOM_ERROR_TIMEOUT, 0);
             do_close (c);
-            yaz_log (LOG_DEBUG, "timeout");
+            yaz_log (log_level, "timeout");
             ZOOM_connection_put_event(c, event);
        }
     }