Remove unused local member wrbuf_opac
[yaz-moved-to-github.git] / src / zoom-c.c
index bea723f..6f6856e 100644 (file)
@@ -1,5 +1,5 @@
 /* This file is part of the YAZ toolkit.
- * Copyright (C) 1995-2008 Index Data
+ * Copyright (C) 1995-2009 Index Data
  * See the file LICENSE for details.
  */
 /**
@@ -41,6 +41,23 @@ static zoom_ret ZOOM_connection_send_init(ZOOM_connection c);
 static zoom_ret do_write_ex(ZOOM_connection c, char *buf_out, int len_out);
 static char *cql2pqf(ZOOM_connection c, const char *cql);
 
+ZOOM_API(const char *) ZOOM_get_event_str(int event)
+{
+    static const char *ar[] = {
+        "NONE",
+        "CONNECT",
+        "SEND_DATA",
+        "RECV_DATA",
+        "TIMEOUT",
+        "UNKNOWN",
+        "SEND_APDU",
+        "RECV_APDU",
+        "RECV_RECORD",
+        "RECV_SEARCH",
+        "END"
+    };
+    return ar[event];
+}
 
 /*
  * This wrapper is just for logging failed lookups.  It would be nicer
@@ -244,7 +261,7 @@ void ZOOM_connection_show_task(ZOOM_task task)
         yaz_log(YLOG_LOG, "connect p=%p", task);
         break;
     case ZOOM_TASK_SCAN:
-        yaz_log(YLOG_LOG, "scant p=%p", task);
+        yaz_log(YLOG_LOG, "scan p=%p", task);
         break;
     }
 }
@@ -462,6 +479,14 @@ ZOOM_API(void)
     set_ZOOM_error(c, ZOOM_ERROR_NONE, 0);
     ZOOM_connection_remove_tasks(c);
 
+    if (ZOOM_options_get_bool(c->options, "apdulog", 0))
+    {
+        c->odr_print = odr_createmem(ODR_PRINT);
+        odr_setprint(c->odr_print, yaz_log_file());
+    }
+    else
+        c->odr_print = 0;
+
     if (c->cs)
     {
         yaz_log(log_details, "%p ZOOM_connection_connect reconnect ok", c);
@@ -596,13 +621,6 @@ ZOOM_API(void)
         ZOOM_options_get_int(c->options, "preferredMessageSize", 1024*1024);
 
     c->async = ZOOM_options_get_bool(c->options, "async", 0);
-    if (ZOOM_options_get_bool(c->options, "apdulog", 0))
-    {
-        c->odr_print = odr_createmem(ODR_PRINT);
-        odr_setprint(c->odr_print, yaz_log_file());
-    }
-    else
-        c->odr_print = 0;
     yaz_log(log_details, "%p ZOOM_connection_connect async=%d", c, c->async);
  
     task = ZOOM_connection_add_task(c, ZOOM_TASK_CONNECT);
@@ -912,6 +930,7 @@ ZOOM_API(ZOOM_resultset)
     task->u.search.resultset = r;
     task->u.search.start = start;
     task->u.search.count = count;
+    task->u.search.recv_search_fired = 0;
 
     syntax = ZOOM_options_get(r->options, "preferredRecordSyntax"); 
     task->u.search.syntax = syntax ? xstrdup(syntax) : 0;
@@ -999,8 +1018,6 @@ ZOOM_API(void)
                 wrbuf_destroy(rc->rec.wrbuf_marc);
             if (rc->rec.wrbuf_iconv)
                 wrbuf_destroy(rc->rec.wrbuf_iconv);
-            if (rc->rec.wrbuf_opac)
-                wrbuf_destroy(rc->rec.wrbuf_opac);
         }
         r->record_hash[i] = 0;
     }
@@ -1343,7 +1360,6 @@ static zoom_ret ZOOM_connection_send_init(ZOOM_connection c)
     Z_InitRequest *ireq = apdu->u.initRequest;
     Z_IdAuthentication *auth = (Z_IdAuthentication *)
         odr_malloc(c->odr_out, sizeof(*auth));
-    char *version;
 
     ODR_MASK_SET(ireq->options, Z_Options_search);
     ODR_MASK_SET(ireq->options, Z_Options_present);
@@ -1356,11 +1372,10 @@ static zoom_ret ZOOM_connection_send_init(ZOOM_connection c)
     ODR_MASK_SET(ireq->protocolVersion, Z_ProtocolVersion_2);
     ODR_MASK_SET(ireq->protocolVersion, Z_ProtocolVersion_3);
     
-    /* Index Data's Z39.50 Implementor Id is 81 */
     ireq->implementationId =
         odr_prepend(c->odr_out,
                     ZOOM_options_get(c->options, "implementationId"),
-                    odr_prepend(c->odr_out, "81", ireq->implementationId));
+                    ireq->implementationId);
     
     ireq->implementationName = 
         odr_prepend(c->odr_out,
@@ -1368,14 +1383,10 @@ static zoom_ret ZOOM_connection_send_init(ZOOM_connection c)
                     odr_prepend(c->odr_out, "ZOOM-C",
                                 ireq->implementationName));
     
-    version = odr_strdup(c->odr_out, "$Revision: 1.154 $");
-    if (strlen(version) > 10)   /* check for unexpanded CVS strings */
-        version[strlen(version)-2] = '\0';
     ireq->implementationVersion = 
         odr_prepend(c->odr_out,
                     ZOOM_options_get(c->options, "implementationVersion"),
-                    odr_prepend(c->odr_out, &version[11],
-                                ireq->implementationVersion));
+                                ireq->implementationVersion);
     
     *ireq->maximumRecordSize = c->maximum_record_size;
     *ireq->preferredMessageSize = c->preferred_message_size;
@@ -1426,8 +1437,17 @@ static zoom_ret send_srw(ZOOM_connection c, Z_SRW_PDU *sr)
 {
     Z_GDU *gdu;
     ZOOM_Event event;
-
-    gdu = z_get_HTTP_Request_host_path(c->odr_out, c->host_port, c->path);
+    const char *database =  ZOOM_options_get(c->options, "databaseName");
+    char *fdatabase = 0;
+    
+    if (database)
+    {
+        fdatabase = (char *) odr_malloc(c->odr_out, strlen(database)+2);
+        strcpy(fdatabase, "/");
+        strcat(fdatabase, database);
+    }
+    gdu = z_get_HTTP_Request_host_path(c->odr_out, c->host_port,
+                                       fdatabase ? fdatabase : c->path);
 
     if (c->sru_mode == zoom_sru_get)
     {
@@ -1454,13 +1474,15 @@ static zoom_ret send_srw(ZOOM_connection c, Z_SRW_PDU *sr)
 }
 #endif
 
-
-static Z_SRW_PDU *ZOOM_srw_get_pdu(ZOOM_connection c, int type) {
+#if YAZ_HAVE_XML2
+static Z_SRW_PDU *ZOOM_srw_get_pdu(ZOOM_connection c, int type)
+{
     Z_SRW_PDU *sr = yaz_srw_get_pdu(c->odr_out, type, c->sru_version);
     sr->username = c->user;
     sr->password = c->password;
     return sr;
 }
+#endif
 
 #if YAZ_HAVE_XML2
 static zoom_ret ZOOM_connection_srw_send_search(ZOOM_connection c)
@@ -1478,7 +1500,8 @@ static zoom_ret ZOOM_connection_srw_send_search(ZOOM_connection c)
     {
     case ZOOM_TASK_SEARCH:
         resultset = c->tasks->u.search.resultset;
-        resultset->setname = xstrdup("default");
+        if (!resultset->setname)
+            resultset->setname = xstrdup("default");
         ZOOM_options_set(resultset->options, "setname", resultset->setname);
         start = &c->tasks->u.search.start;
         count = &c->tasks->u.search.count;
@@ -1488,7 +1511,7 @@ static zoom_ret ZOOM_connection_srw_send_search(ZOOM_connection c)
 
         start = &c->tasks->u.retrieve.start;
         count = &c->tasks->u.retrieve.count;
-        
+
         if (*start >= resultset->size)
             return zoom_complete;
         if (*start + *count > resultset->size)
@@ -1539,7 +1562,8 @@ static zoom_ret ZOOM_connection_srw_send_search(ZOOM_connection c)
     }
     sr->u.request->startRecord = odr_intdup(c->odr_out, *start + 1);
     sr->u.request->maximumRecords = odr_intdup(
-        c->odr_out, resultset->step>0 ? resultset->step : *count);
+        c->odr_out, (resultset->step > 0 && resultset->step < *count) ? 
+        resultset->step : *count);
     sr->u.request->recordSchema = resultset->schema;
     
     option_val = ZOOM_resultset_option_get(resultset, "recordPacking");
@@ -1750,7 +1774,6 @@ ZOOM_API(ZOOM_record)
     nrec->odr = odr_createmem(ODR_DECODE);
     nrec->wrbuf_marc = 0;
     nrec->wrbuf_iconv = 0;
-    nrec->wrbuf_opac = 0;
     odr_setbuf(nrec->odr, buf, size, 0);
     z_NamePlusRecord(nrec->odr, &nrec->npr, 0, 0);
     
@@ -1804,21 +1827,16 @@ ZOOM_API(void)
         wrbuf_destroy(rec->wrbuf_marc);
     if (rec->wrbuf_iconv)
         wrbuf_destroy(rec->wrbuf_iconv);
-    if (rec->wrbuf_opac)
-        wrbuf_destroy(rec->wrbuf_opac);
     odr_destroy(rec->odr);
     xfree(rec);
 }
 
-static const char *marc_iconv_return(ZOOM_record rec, int marc_type,
-                                     int *len,
-                                     const char *buf, int sz,
-                                     const char *record_charset)
+
+static yaz_iconv_t iconv_create_charset(const char *record_charset)
 {
     char to[40];
     char from[40];
     yaz_iconv_t cd = 0;
-    yaz_marc_t mt = yaz_marc_create();
 
     *from = '\0';
     strcpy(to, "UTF-8");
@@ -1840,63 +1858,71 @@ static const char *marc_iconv_return(ZOOM_record rec, int marc_type,
             strncpy(from, record_charset, clen);
         from[clen] = '\0';
     }
-
     if (*from && *to)
-    {
         cd = yaz_iconv_open(to, from);
-        yaz_marc_iconv(mt, cd);
-    }
+    return cd;
+}
+
+static const char *return_marc_record(ZOOM_record rec, int marc_type,
+                                      int *len,
+                                      const char *buf, int sz,
+                                      const char *record_charset)
+{
+    yaz_iconv_t cd = iconv_create_charset(record_charset);
+    yaz_marc_t mt = yaz_marc_create();
+    const char *ret_string = 0;
 
+    if (cd)
+        yaz_marc_iconv(mt, cd);
     yaz_marc_xml(mt, marc_type);
     if (!rec->wrbuf_marc)
         rec->wrbuf_marc = wrbuf_alloc();
     wrbuf_rewind(rec->wrbuf_marc);
     if (yaz_marc_decode_wrbuf(mt, buf, sz, rec->wrbuf_marc) > 0)
     {
-        yaz_marc_destroy(mt);
-        if (cd)
-            yaz_iconv_close(cd);
         if (len)
             *len = wrbuf_len(rec->wrbuf_marc);
-        return wrbuf_cstr(rec->wrbuf_marc);
+        ret_string = wrbuf_cstr(rec->wrbuf_marc);
     }
     yaz_marc_destroy(mt);
     if (cd)
         yaz_iconv_close(cd);
-    return 0;
+    return ret_string;
 }
 
-static const char *record_iconv_return(ZOOM_record rec, int *len,
-                                       const char *buf, int sz,
-                                       const char *record_charset)
+static const char *return_opac_record(ZOOM_record rec, int marc_type,
+                                      int *len,
+                                      Z_OPACRecord *opac_rec,
+                                      const char *record_charset)
 {
-    char to[40];
-    char from[40];
-    yaz_iconv_t cd = 0;
+    yaz_iconv_t cd = iconv_create_charset(record_charset);
+    yaz_marc_t mt = yaz_marc_create();
 
-    *from = '\0';
-    strcpy(to, "UTF-8");
+    if (cd)
+        yaz_marc_iconv(mt, cd);
+    yaz_marc_xml(mt, marc_type);
 
-    if (record_charset && *record_charset)
-    {
-        /* Use "from,to" or just "from" */
-        const char *cp = strchr(record_charset, ',');
-        int clen = strlen(record_charset);
-        if (cp && cp[1])
-        {
-            strncpy( to, cp+1, sizeof(to)-1);
-            to[sizeof(to)-1] = '\0';
-            clen = cp - record_charset;
-        }
-        if (clen > sizeof(from)-1)
-            clen = sizeof(from)-1;
-        
-        if (clen)
-            strncpy(from, record_charset, clen);
-        from[clen] = '\0';
-    }
+    if (!rec->wrbuf_marc)
+        rec->wrbuf_marc = wrbuf_alloc();
+    wrbuf_rewind(rec->wrbuf_marc);
+
+    yaz_opac_decode_wrbuf(mt, opac_rec, rec->wrbuf_marc);
+    yaz_marc_destroy(mt);
 
-    if (*from && *to && (cd = yaz_iconv_open(to, from)))
+    if (cd)
+        yaz_iconv_close(cd);
+    if (len)
+        *len = wrbuf_len(rec->wrbuf_marc);
+    return wrbuf_cstr(rec->wrbuf_marc);
+}
+
+static const char *return_string_record(ZOOM_record rec, int *len,
+                                        const char *buf, int sz,
+                                        const char *record_charset)
+{
+    yaz_iconv_t cd = iconv_create_charset(record_charset);
+
+    if (cd)
     {
         if (!rec->wrbuf_iconv)
             rec->wrbuf_iconv = wrbuf_alloc();
@@ -1915,6 +1941,55 @@ static const char *record_iconv_return(ZOOM_record rec, int *len,
     return buf;
 }
 
+static const char *return_record(ZOOM_record rec, int *len,
+                                 Z_NamePlusRecord *npr,
+                                 int marctype, const char *charset)
+{
+    Z_External *r = (Z_External *) npr->u.databaseRecord;
+    const Odr_oid *oid = r->direct_reference;
+    
+    /* render bibliographic record .. */
+    if (r->which == Z_External_OPAC)
+    {
+        return return_opac_record(rec, marctype, len,
+                                  r->u.opac, charset);
+    }
+    if (r->which == Z_External_sutrs)
+        return return_string_record(rec, len,
+                                    (char*) r->u.sutrs->buf,
+                                    r->u.sutrs->len,
+                                    charset);
+    else if (r->which == Z_External_octet)
+    {
+        if (yaz_oid_is_iso2709(oid))
+        {
+            const char *ret_buf = return_marc_record(
+                rec, marctype, len,
+                (const char *) r->u.octet_aligned->buf,
+                r->u.octet_aligned->len,
+                charset);
+            if (ret_buf)
+                return ret_buf;
+        }
+        return return_string_record(rec, len,
+                                    (const char *) r->u.octet_aligned->buf,
+                                    r->u.octet_aligned->len,
+                                    charset);
+    }
+    else if (r->which == Z_External_grs1)
+    {
+        if (!rec->wrbuf_marc)
+            rec->wrbuf_marc = wrbuf_alloc();
+        wrbuf_rewind(rec->wrbuf_marc);
+        yaz_display_grs1(rec->wrbuf_marc, r->u.grs1, 0);
+        return return_string_record(rec, len,
+                                    wrbuf_buf(rec->wrbuf_marc),
+                                    wrbuf_len(rec->wrbuf_marc),
+                                    charset);
+    }
+    return 0;
+}
+    
 
 ZOOM_API(int)
     ZOOM_record_error(ZOOM_record rec, const char **cp,
@@ -2064,116 +2139,15 @@ ZOOM_API(const char *)
     /* from now on - we have a database record .. */
     if (!strcmp(type, "render"))
     {
-        Z_External *r = (Z_External *) npr->u.databaseRecord;
-        const Odr_oid *oid = r->direct_reference;
-
-        /* render bibliographic record .. */
-        if (r->which == Z_External_OPAC)
-        {
-            r = r->u.opac->bibliographicRecord;
-            if (!r)
-                return 0;
-            oid = r->direct_reference;
-        }
-        if (r->which == Z_External_sutrs)
-            return record_iconv_return(rec, len,
-                                       (char*) r->u.sutrs->buf,
-                                       r->u.sutrs->len,
-                                       charset);
-        else if (r->which == Z_External_octet)
-        {
-            if (yaz_oid_is_iso2709(oid))
-            {
-                const char *ret_buf = marc_iconv_return(
-                    rec, YAZ_MARC_LINE, len,
-                    (const char *) r->u.octet_aligned->buf,
-                    r->u.octet_aligned->len,
-                    charset);
-                if (ret_buf)
-                    return ret_buf;
-            }
-            return record_iconv_return(rec, len,
-                                       (const char *) r->u.octet_aligned->buf,
-                                       r->u.octet_aligned->len,
-                                       charset);
-        }
-        else if (r->which == Z_External_grs1)
-        {
-            if (!rec->wrbuf_marc)
-                rec->wrbuf_marc = wrbuf_alloc();
-            wrbuf_rewind(rec->wrbuf_marc);
-            yaz_display_grs1(rec->wrbuf_marc, r->u.grs1, 0);
-            return record_iconv_return(rec, len,
-                                       wrbuf_buf(rec->wrbuf_marc),
-                                       wrbuf_len(rec->wrbuf_marc),
-                                       charset);
-        }
-        return 0;
+        return return_record(rec, len, npr, YAZ_MARC_LINE, charset);
     }
     else if (!strcmp(type, "xml"))
     {
-        Z_External *r = (Z_External *) npr->u.databaseRecord;
-        const Odr_oid *oid = r->direct_reference;
-
-        /* render bibliographic record .. */
-        if (r->which == Z_External_OPAC)
-        {
-            r = r->u.opac->bibliographicRecord;
-            if (!r)
-                return 0;
-            oid = r->direct_reference;
-        }
-        
-        if (r->which == Z_External_sutrs)
-            return record_iconv_return(rec, len,
-                                       (const char *) r->u.sutrs->buf,
-                                       r->u.sutrs->len,
-                                       charset);
-        else if (r->which == Z_External_octet)
-        {
-            int marc_decode_type = YAZ_MARC_MARCXML;
-            if (yaz_oid_is_iso2709(oid))
-            {
-                const char *ret_buf = marc_iconv_return(
-                    rec, marc_decode_type, len,
-                    (const char *) r->u.octet_aligned->buf,
-                    r->u.octet_aligned->len,
-                    charset);
-                if (ret_buf)
-                    return ret_buf;
-            }
-            return record_iconv_return(rec, len,
-                                       (const char *) r->u.octet_aligned->buf,
-                                       r->u.octet_aligned->len,
-                                       charset);
-        }
-        else if (r->which == Z_External_grs1)
-        {
-            if (len) *len = 5;
-            return "GRS-1";
-        }
-        return 0;
+        return return_record(rec, len, npr, YAZ_MARC_MARCXML, charset);
     }
     else if (!strcmp(type, "raw"))
     {
-        Z_External *r = (Z_External *) npr->u.databaseRecord;
-        
-        if (r->which == Z_External_sutrs)
-        {
-            if (len) *len = r->u.sutrs->len;
-            return (const char *) r->u.sutrs->buf;
-        }
-        else if (r->which == Z_External_octet)
-        {
-            if (len) *len = r->u.octet_aligned->len;
-            return (const char *) r->u.octet_aligned->buf;
-        }
-        else /* grs-1, explain, OPAC, ... */
-        {
-            if (len) *len = -1;
-            return (const char *) npr->u.databaseRecord;
-        }
-        return 0;
+        return return_record(rec, len, npr, YAZ_MARC_ISO2709, charset);
     }
     else if (!strcmp (type, "ext"))
     {
@@ -2181,20 +2155,8 @@ ZOOM_API(const char *)
         return (const char *) npr->u.databaseRecord;
     }
     else if (!strcmp (type, "opac"))
-             
     {
-        Z_External *r = (Z_External *) npr->u.databaseRecord;
-        if (r->which == Z_External_OPAC)
-        {
-            if (!rec->wrbuf_opac)
-                rec->wrbuf_opac = wrbuf_alloc();
-            wrbuf_rewind(rec->wrbuf_opac);
-            yaz_display_OPAC(rec->wrbuf_opac, r->u.opac, 0);
-            return record_iconv_return(rec, len,
-                                       wrbuf_buf(rec->wrbuf_opac),
-                                       wrbuf_len(rec->wrbuf_opac),
-                                       charset);
-        }
+        return return_record(rec, len, npr, YAZ_MARC_MARCXML, charset);
     }
     return 0;
 }
@@ -2240,7 +2202,6 @@ static void record_cache_add(ZOOM_resultset r, Z_NamePlusRecord *npr,
         rc->rec.odr = 0;
         rc->rec.wrbuf_marc = 0;
         rc->rec.wrbuf_iconv = 0;
-        rc->rec.wrbuf_opac = 0;
         rc->elementSetName = odr_strdup_null(r->odr, elementSetName);
         
         rc->syntax = odr_strdup_null(r->odr, syntax);
@@ -3942,38 +3903,45 @@ static void recv_apdu(ZOOM_connection c, Z_APDU *apdu)
 }
 
 #if YAZ_HAVE_XML2
-static void handle_srw_response(ZOOM_connection c,
-                                Z_SRW_searchRetrieveResponse *res)
+static zoom_ret handle_srw_response(ZOOM_connection c,
+                                    Z_SRW_searchRetrieveResponse *res)
 {
     ZOOM_resultset resultset = 0;
     int i;
     NMEM nmem;
     ZOOM_Event event;
-    int *start;
+    int *start, *count;
     const char *syntax, *elementSetName;
 
     if (!c->tasks)
-        return;
+        return zoom_complete;
 
     switch(c->tasks->which)
     {
     case ZOOM_TASK_SEARCH:
         resultset = c->tasks->u.search.resultset;
         start = &c->tasks->u.search.start;
+        count = &c->tasks->u.search.count;
         syntax = c->tasks->u.search.syntax;
         elementSetName = c->tasks->u.search.elementSetName;        
+
+        if (!c->tasks->u.search.recv_search_fired)
+        {
+            event = ZOOM_Event_create(ZOOM_EVENT_RECV_SEARCH);
+            ZOOM_connection_put_event(c, event);
+            c->tasks->u.search.recv_search_fired = 1;
+        }
         break;
     case ZOOM_TASK_RETRIEVE:
         resultset = c->tasks->u.retrieve.resultset;
         start = &c->tasks->u.retrieve.start;
+        count = &c->tasks->u.retrieve.count;
         syntax = c->tasks->u.retrieve.syntax;
         elementSetName = c->tasks->u.retrieve.elementSetName;
         break;
     default:
-        return;
+        return zoom_complete;
     }
-    event = ZOOM_Event_create(ZOOM_EVENT_RECV_SEARCH);
-    ZOOM_connection_put_event(c, event);
 
     resultset->size = 0;
 
@@ -3981,62 +3949,77 @@ static void handle_srw_response(ZOOM_connection c,
         ZOOM_resultset_option_set(resultset, "resultSetId", res->resultSetId);
 
     yaz_log(log_details, "%p handle_srw_response got SRW response OK", c);
-    
-    if (res->numberOfRecords)
-        resultset->size = *res->numberOfRecords;
 
-    for (i = 0; i<res->num_records; i++)
+    if (res->num_diagnostics > 0)
     {
-        int pos;
-        Z_SRW_record *sru_rec;
-        Z_SRW_diagnostic *diag = 0;
-        int num_diag;
-        Z_NamePlusRecord *npr = (Z_NamePlusRecord *)
-            odr_malloc(c->odr_in, sizeof(Z_NamePlusRecord));
-
-        if (res->records[i].recordPosition && 
-            *res->records[i].recordPosition > 0)
-            pos = *res->records[i].recordPosition - 1;
-        else
-            pos = *start + i;
-        
-        sru_rec = &res->records[i];
-
-        npr->databaseName = 0;
-        npr->which = Z_NamePlusRecord_databaseRecord;
-        npr->u.databaseRecord = (Z_External *)
-            odr_malloc(c->odr_in, sizeof(Z_External));
-        npr->u.databaseRecord->descriptor = 0;
-        npr->u.databaseRecord->direct_reference =
-            odr_oiddup(c->odr_in, yaz_oid_recsyn_xml);
-        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 = (unsigned char*)
-            sru_rec->recordData_buf;
-        npr->u.databaseRecord->u.octet_aligned->len = 
-            npr->u.databaseRecord->u.octet_aligned->size = 
-            sru_rec->recordData_len;
-        
-        if (sru_rec->recordSchema 
-            && !strcmp(sru_rec->recordSchema,
-                       "info:srw/schema/1/diagnostics-v1.1"))
+        set_SRU_error(c, &res->diagnostics[0]);
+    }
+    else
+    {
+        if (res->numberOfRecords)
+            resultset->size = *res->numberOfRecords;
+        for (i = 0; i<res->num_records; i++)
         {
-            sru_decode_surrogate_diagnostics(sru_rec->recordData_buf,
-                                             sru_rec->recordData_len,
-                                             &diag, &num_diag,
-                                             resultset->odr);
+            int pos;
+            Z_SRW_record *sru_rec;
+            Z_SRW_diagnostic *diag = 0;
+            int num_diag;
+            
+            Z_NamePlusRecord *npr = (Z_NamePlusRecord *)
+                odr_malloc(c->odr_in, sizeof(Z_NamePlusRecord));
+            
+            if (res->records[i].recordPosition && 
+                *res->records[i].recordPosition > 0)
+                pos = *res->records[i].recordPosition - 1;
+            else
+                pos = *start + i;
+            
+            sru_rec = &res->records[i];
+            
+            npr->databaseName = 0;
+            npr->which = Z_NamePlusRecord_databaseRecord;
+            npr->u.databaseRecord = (Z_External *)
+                odr_malloc(c->odr_in, sizeof(Z_External));
+            npr->u.databaseRecord->descriptor = 0;
+            npr->u.databaseRecord->direct_reference =
+                odr_oiddup(c->odr_in, yaz_oid_recsyn_xml);
+            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 = (unsigned char*)
+                sru_rec->recordData_buf;
+            npr->u.databaseRecord->u.octet_aligned->len = 
+                npr->u.databaseRecord->u.octet_aligned->size = 
+                sru_rec->recordData_len;
+            
+            if (sru_rec->recordSchema 
+                && !strcmp(sru_rec->recordSchema,
+                           "info:srw/schema/1/diagnostics-v1.1"))
+            {
+                sru_decode_surrogate_diagnostics(sru_rec->recordData_buf,
+                                                 sru_rec->recordData_len,
+                                                 &diag, &num_diag,
+                                                 resultset->odr);
+            }
+            record_cache_add(resultset, npr, pos, syntax, elementSetName,
+                             sru_rec->recordSchema, diag);
         }
-        record_cache_add(resultset, npr, pos, syntax, elementSetName,
-                         sru_rec->recordSchema, diag);
+        *count -= i;
+        *start += i;
+        if (*count + *start > resultset->size)
+            *count = resultset->size - *start;
+        if (*count < 0)
+            *count = 0;
+        
+        nmem = odr_extract_mem(c->odr_in);
+        nmem_transfer(odr_getmem(resultset->odr), nmem);
+        nmem_destroy(nmem);
+
+        if (*count > 0)
+            return ZOOM_connection_srw_send_search(c);
     }
-    if (res->num_diagnostics > 0)
-        set_SRU_error(c, &res->diagnostics[0]);
-    nmem = odr_extract_mem(c->odr_in);
-    nmem_transfer(odr_getmem(resultset->odr), nmem);
-    nmem_destroy(nmem);
+    return zoom_complete;
 }
 #endif
 
@@ -4066,6 +4049,7 @@ static void handle_srw_scan_response(ZOOM_connection c,
 #if YAZ_HAVE_XML2
 static void handle_http(ZOOM_connection c, Z_HTTP_Response *hres)
 {
+    zoom_ret cret = zoom_complete;
     int ret = -1;
     const char *addinfo = 0;
     const char *connection_head = z_HTTP_header_lookup(hres->headers,
@@ -4093,7 +4077,7 @@ static void handle_http(ZOOM_connection c, Z_HTTP_Response *hres)
 
             ZOOM_options_set(c->options, "sru_version", sr->srw_version);
             if (sr->which == Z_SRW_searchRetrieve_response)
-                handle_srw_response(c, sr->u.response);
+                cret = handle_srw_response(c, sr->u.response);
             else if (sr->which == Z_SRW_scan_response)
                 handle_srw_scan_response(c, sr->u.scan_response);
             else
@@ -4117,7 +4101,8 @@ static void handle_http(ZOOM_connection c, Z_HTTP_Response *hres)
             set_ZOOM_error(c, ZOOM_ERROR_DECODE, addinfo);
         do_close(c);
     }
-    ZOOM_connection_remove_task(c);
+    if (cret == zoom_complete)
+        ZOOM_connection_remove_task(c);
     if (!strcmp(hres->version, "1.0"))
     {
         /* HTTP 1.0: only if Keep-Alive we stay alive.. */
@@ -4630,6 +4615,7 @@ ZOOM_API(int) ZOOM_connection_get_timeout(ZOOM_connection c)
 /*
  * Local variables:
  * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
  * indent-tabs-mode: nil
  * End:
  * vim: shiftwidth=4 tabstop=8 expandtab