cookie: introduce yaz_cookies_reset
[yaz-moved-to-github.git] / client / client.c
index 56178da..6fea730 100644 (file)
@@ -1,5 +1,5 @@
 /* This file is part of the YAZ toolkit.
- * Copyright (C) 1995-2013 Index Data
+ * Copyright (C) Index Data
  * See the file LICENSE for details.
  */
 /** \file client.c
@@ -64,6 +64,7 @@
 #include <yaz/cql.h>
 #include <yaz/log.h>
 #include <yaz/facet.h>
+#include <yaz/cookie.h>
 
 #if HAVE_READLINE_READLINE_H
 #include <readline/readline.h>
@@ -103,9 +104,9 @@ char *databaseNames[128];
 int num_databaseNames = 0;
 static Z_External *record_last = 0;
 static int setnumber = -1;              /* current result set number */
-static int smallSetUpperBound = 0;
-static int largeSetLowerBound = 1;
-static int mediumSetPresentNumber = 0;
+static Odr_int smallSetUpperBound = 0;
+static Odr_int largeSetLowerBound = 1;
+static Odr_int mediumSetPresentNumber = 0;
 static Z_ElementSetNames *elementSetNames = 0;
 static Z_FacetList *facet_list = 0;
 static ODR facet_odr = 0;
@@ -149,6 +150,7 @@ static char cur_host[200];
 static Odr_int last_hit_count = 0;
 static int pretty_xml = 0;
 static Odr_int sru_maximumRecords = 0;
+static yaz_cookies_t yaz_cookies = 0;
 
 typedef enum {
     QueryType_Prefix,
@@ -253,9 +255,12 @@ static void add_otherInfos(Z_APDU *a)
     Z_OtherInformation **oi;
     int i;
 
-    yaz_oi_APDU(a, &oi);
-    if (facet_list)
+    if (facet_list && a->which == Z_APDU_searchRequest)
+    {
+        oi = &a->u.searchRequest->additionalSearchInfo;
         yaz_oi_set_facetlist(oi, out, facet_list);
+    }
+    yaz_oi_APDU(a, &oi);
     for (i = 0; i < maxOtherInfosSupported; ++i)
     {
         if (oid_oidlen(extraOtherInfos[i].oid) > 0)
@@ -739,6 +744,9 @@ static int session_connect(const char *arg)
     int r;
     const char *basep = 0;
 
+    yaz_cookies_destroy(yaz_cookies);
+    yaz_cookies = yaz_cookies_create();
+
     r = session_connect_base(arg, &basep);
     if (basep && *basep)
         set_base(basep);
@@ -838,6 +846,50 @@ static void print_record(const char *buf, size_t len)
         printf("\n");
 }
 
+static void print_mab_record(const char *buf, size_t len)
+{
+    size_t i;
+    size_t last_linebreak = 0;
+    size_t last_subfield  = 0;
+    for (i = 0; i < len; i++)
+    {
+        // line break after header
+        if ( i == 24 )
+        {
+            printf("\n");
+            last_linebreak = i - 1;
+        }
+
+        // space between field and content
+        if ( i > 24 && i - last_linebreak == 5 )
+            printf(" ");
+
+        // space after subfield
+        if ( last_subfield != 0 && i - last_subfield == 2 )
+            printf(" ");
+
+        if ((buf[i] <= 126 && buf[i] >= 32) || strchr("\n\r\t\f", buf[i]))
+            printf("%c", buf[i]);
+        else if ( buf[i] == 29 ) // record separator
+            printf("\n");
+        else if ( buf[i] == 30 ) // field separator
+        {
+            printf("\n");
+            last_linebreak = i;
+        }
+        else if ( buf[i] == 31 ) // subfield
+        {
+            // space before subfields; except first one
+            if ( i > 24 && i - last_linebreak > 5 )
+                printf(" ");
+            printf("$");
+            last_subfield = i;
+        }
+        else
+            printf("\\X%02X", ((const unsigned char *)buf)[i]);
+    }
+}
+
 static void print_xml_record(const char *buf, size_t len)
 {
     int has_printed = 0;
@@ -926,7 +978,7 @@ static void display_record(Z_External *r)
         }
         else if (!oid_oidcmp(oid, yaz_oid_recsyn_mab))
         {
-            print_record(octet_buf, octet_len);
+            print_mab_record(octet_buf, octet_len);
         }
         else
         {
@@ -1314,43 +1366,17 @@ static int send_srw(Z_SRW_PDU *sr)
     return send_srw_host_path(sr, cur_host, path);
 }
 
-static int send_SRW_redirect(const char *uri, Z_HTTP_Response *cookie_hres)
+static int send_SRW_redirect(const char *uri)
 {
     const char *username = 0;
     const char *password = 0;
-    struct Z_HTTP_Header *h;
-    char *combined_cookies = 0;
-    int combined_cookies_len = 0;
     Z_GDU *gdu = get_HTTP_Request_url(out, uri);
 
     gdu->u.HTTP_Request->method = odr_strdup(out, "GET");
     z_HTTP_header_add(out, &gdu->u.HTTP_Request->headers, "Accept",
                       "text/xml");
 
-    for (h = cookie_hres->headers; h; h = h->next)
-    {
-        if (!strcmp(h->name, "Set-Cookie"))
-        {
-            char *cp;
-
-            if (!(cp = strchr(h->value, ';')))
-                cp = h->value + strlen(h->value);
-            if (cp - h->value >= 1)
-            {
-                combined_cookies = xrealloc(combined_cookies, combined_cookies_len + cp - h->value + 3);
-                memcpy(combined_cookies+combined_cookies_len, h->value, cp - h->value);
-                combined_cookies[combined_cookies_len + cp - h->value] = '\0';
-                strcat(combined_cookies,"; ");
-                combined_cookies_len = strlen(combined_cookies);
-            }
-        }
-    }
-    if (combined_cookies_len)
-    {
-        z_HTTP_header_add(out, &gdu->u.HTTP_Request->headers, "Cookie", combined_cookies);
-        xfree(combined_cookies);
-    }
-
+    yaz_cookies_request(yaz_cookies, out, gdu->u.HTTP_Request);
     if (auth)
     {
         if (auth->which == Z_IdAuthentication_open)
@@ -1477,8 +1503,7 @@ static int send_SRW_searchRequest(const char *arg)
     sru_maximumRecords = 0;
     sr->u.request->maximumRecords = odr_intdup(out, 0);
     sr->u.request->facetList = facet_list;
-    if (record_schema)
-        sr->u.request->recordSchema = record_schema;
+    sr->u.request->recordSchema = record_schema;
     if (recordsyntax_size == 1 && !yaz_matchstr(recordsyntax_list[0], "xml"))
         sr->u.request->recordPacking = "xml";
     return send_srw(sr);
@@ -2632,7 +2657,7 @@ static int cmd_explain(const char *arg)
         setno = 1;
 
         /* save this for later .. when fetching individual records */
-        sr = yaz_srw_get(out, Z_SRW_explain_request);
+        sr = yaz_srw_get_pdu(out, Z_SRW_explain_request, sru_version);
         if (recordsyntax_size == 1
             && !yaz_matchstr(recordsyntax_list[0], "xml"))
             sr->u.explain_request->recordPacking = "xml";
@@ -2903,30 +2928,30 @@ static int cmd_delete(const char *arg)
 
 static int cmd_ssub(const char *arg)
 {
-    if (!(smallSetUpperBound = atoi(arg)))
-        return 0;
+    smallSetUpperBound = odr_strtol(arg, 0, 10);
     return 1;
 }
 
 static int cmd_lslb(const char *arg)
 {
-    if (!(largeSetLowerBound = atoi(arg)))
-        return 0;
+    largeSetLowerBound = odr_strtol(arg, 0, 10);
     return 1;
 }
 
 static int cmd_mspn(const char *arg)
 {
-    if (!(mediumSetPresentNumber = atoi(arg)))
-        return 0;
+    mediumSetPresentNumber = odr_strtol(arg, 0, 10);
     return 1;
 }
 
 static int cmd_status(const char *arg)
 {
-    printf("smallSetUpperBound: %d\n", smallSetUpperBound);
-    printf("largeSetLowerBound: %d\n", largeSetLowerBound);
-    printf("mediumSetPresentNumber: %d\n", mediumSetPresentNumber);
+    printf("smallSetUpperBound: " ODR_INT_PRINTF "\n",
+           smallSetUpperBound);
+    printf("largeSetLowerBound: " ODR_INT_PRINTF "\n",
+           largeSetLowerBound);
+    printf("mediumSetPresentNumber: " ODR_INT_PRINTF "\n",
+           mediumSetPresentNumber);
     return 1;
 }
 
@@ -3138,8 +3163,7 @@ static int send_SRW_presentRequest(const char *arg)
     sr->u.request->startRecord = odr_intdup(out, setno);
     sru_maximumRecords = nos;
     sr->u.request->maximumRecords = odr_intdup(out, nos);
-    if (record_schema)
-        sr->u.request->recordSchema = record_schema;
+    sr->u.request->recordSchema = record_schema;
     if (recordsyntax_size == 1 && !yaz_matchstr(recordsyntax_list[0], "xml"))
         sr->u.request->recordPacking = "xml";
     return send_srw(sr);
@@ -3220,6 +3244,7 @@ static int cmd_show(const char *arg)
 
 static void exit_client(int code)
 {
+    yaz_cookies_destroy(yaz_cookies);
     file_history_save(file_history);
     file_history_destroy(&file_history);
     nmem_destroy(nmem_auth);
@@ -4283,10 +4308,7 @@ struct timeval tv_start;
 static void handle_srw_record(Z_SRW_record *rec)
 {
     if (rec->recordPosition)
-    {
         printf("pos=" ODR_INT_PRINTF, *rec->recordPosition);
-        setno = *rec->recordPosition + 1;
-    }
     if (rec->recordSchema)
         printf(" schema=%s", rec->recordSchema);
     printf("\n");
@@ -4340,6 +4362,7 @@ static void handle_srw_response(Z_SRW_searchRetrieveResponse *res)
         }
         handle_srw_record(res->records + i);
     }
+    setno += res->num_records;
 }
 
 static void handle_srw_scan_term(Z_SRW_scanTerm *term)
@@ -4423,6 +4446,7 @@ static void http_response(Z_HTTP_Response *hres)
                 {YAZ_XMLNS_SRU_v2_mask, 0, (Z_SOAP_fun) yaz_srw_codec},
                 {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
                 {YAZ_XMLNS_SRU_v1_response, 0, (Z_SOAP_fun) yaz_srw_codec},
+                {"searchRetrieveResponse", 0, (Z_SOAP_fun) yaz_srw_codec},
                 {0, 0, 0}
             };
             ret = z_soap_codec(o, &soap_package,
@@ -4485,7 +4509,7 @@ static void http_response(Z_HTTP_Response *hres)
 }
 #endif
 
-#define max_HTTP_redirects 2
+#define max_HTTP_redirects 3
 
 static void wait_and_handle_response(int one_response_only)
 {
@@ -4622,17 +4646,37 @@ static void wait_and_handle_response(int one_response_only)
             Z_HTTP_Response *hres = gdu->u.HTTP_Response;
             int code = hres->code;
             const char *location = 0;
+
+            yaz_cookies_response(yaz_cookies, hres);
             if ((code == 301 || code == 302)
                 && no_redirects < max_HTTP_redirects
                 && !yaz_matchstr(sru_method, "get")
                 && (location = z_HTTP_header_lookup(hres->headers, "Location")))
             {
                 const char *base_tmp;
-                session_connect_base(location, &base_tmp);
+
+                if (*location == '/')
+                {
+                    char *args = 0;
+                    char *nlocation = odr_malloc(in, strlen(location)
+                                                 + strlen(cur_host) + 3);
+                    strcpy(nlocation, cur_host);
+                    cs_get_host_args(nlocation, (const char **) &args);
+                    if (!args || !*args)
+                        args = nlocation + strlen(nlocation);
+                    else
+                        args--;
+                    strcpy(args, location);
+                    location = nlocation;
+                }
+                else
+                {
+                    session_connect_base(location, &base_tmp);
+                }
                 no_redirects++;
                 if (conn)
                 {
-                    if (send_SRW_redirect(location, hres) == 2)
+                    if (send_SRW_redirect(location) == 2)
                         continue;
                 }
                 printf("Redirect failed\n");
@@ -4852,7 +4896,9 @@ static int cmd_list_all(const char* args)
     printf("Named Result Sets    : %s\n",setnumber==-1?"off":"on");
 
     /* piggy back options */
-    printf("ssub/lslb/mspn       : %d/%d/%d\n",smallSetUpperBound,largeSetLowerBound,mediumSetPresentNumber);
+    printf("ssub/lslb/mspn       : " ODR_INT_PRINTF "/" ODR_INT_PRINTF "/"
+           ODR_INT_PRINTF "\n",
+           smallSetUpperBound, largeSetLowerBound, mediumSetPresentNumber);
 
     /* print present related options */
     if (recordsyntax_size > 0)