Updated source file headers with new year and no CVS Id.
[pazpar2-moved-to-github.git] / src / client.c
index 02419ce..ad9d237 100644 (file)
@@ -1,7 +1,5 @@
-/* $Id: client.c,v 1.25 2007-09-20 09:22:37 adam Exp $
-   Copyright (c) 2006-2007, Index Data.
-
-This file is part of Pazpar2.
+/* This file is part of Pazpar2.
+   Copyright (C) 2006-2008 Index Data
 
 Pazpar2 is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
@@ -14,10 +12,10 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with Pazpar2; see the file LICENSE.  If not, write to the
-Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.
- */
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+*/
 
 /** \file client.c
     \brief Z39.50 client 
@@ -84,11 +82,13 @@ struct client {
 struct show_raw {
     int active; // whether this request has been sent to the server
     int position;
+    int binary;
     char *syntax;
     char *esn;
     void (*error_handler)(void *data, const char *addinfo);
     void (*record_handler)(void *data, const char *buf, size_t sz);
     void *data;
+    struct show_raw *next;
 };
 
 static const char *client_states[] = {
@@ -236,26 +236,37 @@ int client_show_raw_begin(struct client *cl, int position,
                           void *data,
                           void (*error_handler)(void *data, const char *addinfo),
                           void (*record_handler)(void *data, const char *buf,
-                                                 size_t sz))
+                                                 size_t sz),
+                          void **data2,
+                          int binary)
 {
-    if (cl->show_raw)
+    struct show_raw *rr, **rrp;
+    if (!cl->connection)
+    {   /* the client has no connection */
         return -1;
-    cl->show_raw = xmalloc(sizeof(*cl->show_raw));
-    cl->show_raw->position = position;
-    cl->show_raw->active = 0;
-    cl->show_raw->data = data;
-    cl->show_raw->error_handler = error_handler;
-    cl->show_raw->record_handler = record_handler;
+    }
+    rr = xmalloc(sizeof(*rr));
+    *data2 = rr;
+    rr->position = position;
+    rr->active = 0;
+    rr->data = data;
+    rr->error_handler = error_handler;
+    rr->record_handler = record_handler;
+    rr->binary = binary;
     if (syntax)
-        cl->show_raw->syntax = xstrdup(syntax);
+        rr->syntax = xstrdup(syntax);
     else
-        cl->show_raw->syntax = 0;
+        rr->syntax = 0;
     if (esn)
-        cl->show_raw->esn = xstrdup(esn);
+        rr->esn = xstrdup(esn);
     else
-        cl->show_raw->esn = 0;
+        rr->esn = 0;
+    rr->next = 0;
+    
+    for (rrp = &cl->show_raw; *rrp; rrp = &(*rrp)->next)
+        ;
+    *rrp = rr;
     
-
     if (cl->state == Client_Failed)
     {
         client_show_raw_error(cl, "client failed");
@@ -271,27 +282,42 @@ int client_show_raw_begin(struct client *cl, int position,
     return 0;
 }
 
-void client_show_raw_reset(struct client *cl)
+void client_show_raw_remove(struct client *cl, void *data)
+{
+    struct show_raw *rr = data;
+    struct show_raw **rrp = &cl->show_raw;
+    while (*rrp != rr)
+        rrp = &(*rrp)->next;
+    if (*rrp)
+    {
+        *rrp = rr->next;
+        xfree(rr);
+    }
+}
+
+void client_show_raw_dequeue(struct client *cl)
 {
-    xfree(cl->show_raw);
-    cl->show_raw = 0;
+    struct show_raw *rr = cl->show_raw;
+
+    cl->show_raw = rr->next;
+    xfree(rr);
 }
 
 static void client_show_raw_error(struct client *cl, const char *addinfo)
 {
-    if (cl->show_raw)
+    while (cl->show_raw)
     {
         cl->show_raw->error_handler(cl->show_raw->data, addinfo);
-        client_show_raw_reset(cl);
+        client_show_raw_dequeue(cl);
     }
 }
 
 static void client_show_raw_cancel(struct client *cl)
 {
-    if (cl->show_raw)
+    while (cl->show_raw)
     {
         cl->show_raw->error_handler(cl->show_raw->data, "cancel");
-        client_show_raw_reset(cl);
+        client_show_raw_dequeue(cl);
     }
 }
 
@@ -539,6 +565,21 @@ static void ingest_raw_records(struct client *cl, Z_Records *r)
         return;
     }
 
+    if (cl->show_raw && cl->show_raw->binary)
+    {
+        Z_External *rec = npr->u.databaseRecord;
+        if (rec->which == Z_External_octet)
+        {
+            cl->show_raw->record_handler(cl->show_raw->data,
+                                         (const char *)
+                                         rec->u.octet_aligned->buf,
+                                         rec->u.octet_aligned->len);
+            client_show_raw_dequeue(cl);
+        }
+        else
+            client_show_raw_error(cl, "no records");
+    }
+
     doc = record_to_xml(client_get_database(cl), npr->u.databaseRecord);
     if (!doc)
     {
@@ -549,12 +590,13 @@ static void ingest_raw_records(struct client *cl, Z_Records *r)
     xmlDocDumpMemory(doc, &buf_out, &len_out);
     xmlFreeDoc(doc);
 
-    cl->show_raw->record_handler(cl->show_raw->data,
-                                 (const char *) buf_out, len_out);
-    
+    if (cl->show_raw)
+    {
+        cl->show_raw->record_handler(cl->show_raw->data,
+                                     (const char *) buf_out, len_out);
+        client_show_raw_dequeue(cl);
+    }
     xmlFree(buf_out);
-    xfree(cl->show_raw);
-    cl->show_raw = 0;
 }
 
 static void ingest_records(struct client *cl, Z_Records *r)
@@ -893,7 +935,7 @@ void client_set_connection(struct client *cl, struct connection *con)
 void client_disconnect(struct client *cl)
 {
     if (cl->state != Client_Idle)
-        cl->state = Client_Disconnected;
+        client_set_state(cl, Client_Disconnected);
     client_set_connection(cl, 0);
 }