Fixed bug #831: New yaz-client command: 'source'.
[yaz-moved-to-github.git] / client / client.c
index 2204574..39c1078 100644 (file)
@@ -1,8 +1,8 @@
 /* 
- * Copyright (C) 1995-2006, Index Data ApS
+ * Copyright (C) 1995-2007, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: client.c,v 1.310 2006-06-02 13:12:53 adam Exp $
+ * $Id: client.c,v 1.324 2007-01-24 09:54:04 adam Exp $
  */
 /** \file client.c
  *  \brief yaz-client program
@@ -86,7 +86,7 @@ static char *codeset = 0;               /* character set for output */
 static int hex_dump = 0;
 static char *dump_file_prefix = 0;
 static ODR out, in, print;              /* encoding and decoding streams */
-#if HAVE_XML2
+#if YAZ_HAVE_XML2
 static ODR srw_sr_odr_out = 0;
 static Z_SRW_PDU *srw_sr = 0;
 #endif
@@ -180,7 +180,7 @@ int cmd_register_tab(const char* arg);
 
 static void close_session (void);
 
-ODR getODROutputStream()
+ODR getODROutputStream(void)
 {
     return out;
 }
@@ -686,10 +686,10 @@ int session_connect(const char *arg)
         conn = cs_create_host(arg, 1, &add);
     if (!conn)
     {
-        printf ("Couldn't create comstack\n");
+        printf ("Could not resolve address %s\n", arg);
         return 0;
     }
-#if HAVE_XML2
+#if YAZ_HAVE_XML2
     if (conn->protocol == PROTO_HTTP)
         queryType = QueryType_CQL;
 #else
@@ -711,12 +711,6 @@ int session_connect(const char *arg)
     if (cs_connect(conn, add) < 0)
     {
         printf ("error = %s\n", cs_strerror(conn));
-        if (conn->cerrno == CSYSERR)
-        {
-            char msg[256];
-            yaz_strerror(msg, sizeof(msg));
-            printf ("%s\n", msg);
-        }
         cs_close(conn);
         conn = 0;
         return 0;
@@ -766,7 +760,7 @@ int cmd_open(const char *arg)
     return session_connect(cur_host);
 }
 
-void try_reconnect() 
+void try_reconnect(void)
 {
     char* open_command;
         
@@ -1257,7 +1251,7 @@ static int send_deleteResultSetRequest(const char *arg)
     return 2;
 }
 
-#if HAVE_XML2
+#if YAZ_HAVE_XML2
 static int send_srw(Z_SRW_PDU *sr)
 {
     const char *charset = negotiationCharset;
@@ -1311,7 +1305,7 @@ static int send_srw(Z_SRW_PDU *sr)
 }
 #endif
 
-#if HAVE_XML2
+#if YAZ_HAVE_XML2
 static char *encode_SRW_term(ODR o, const char *q)
 {
     const char *in_charset = "ISO-8859-1";
@@ -1410,7 +1404,7 @@ static int send_SRW_searchRequest(const char *arg)
     if (record_schema)
         sr->u.request->recordSchema = record_schema;
     if (recordsyntax_size == 1 && recordsyntax_list[0] == VAL_TEXT_XML)
-        sr->u.explain_request->recordPacking = "xml";
+        sr->u.request->recordPacking = "xml";
     return send_srw(sr);
 }
 #endif
@@ -1639,7 +1633,25 @@ static int process_searchResponse(Z_SearchResponse *res)
     last_hit_count = *res->resultCount;
     if (setnumber >= 0)
         printf (", setno %d", setnumber);
-    printf ("\n");
+    putchar('\n');
+    if (res->resultSetStatus)
+    {
+        printf("Result Set Status: ");
+        switch(*res->resultSetStatus)
+        {
+        case Z_SearchResponse_subset:
+            printf("subset"); break;
+        case Z_SearchResponse_interim:
+            printf("interim"); break;
+        case Z_SearchResponse_none:
+            printf("none"); break;
+        case Z_SearchResponse_estimate:
+            printf("estimate"); break;
+        default:
+            printf("%d", *res->resultSetStatus);
+        }            
+        putchar('\n');
+    }
     display_searchResult (res->additionalSearchInfo);
     printf("records returned: %d\n",
            *res->numberOfRecordsReturned);
@@ -1891,7 +1903,7 @@ const char *get_ill_element (void *clientData, const char *element)
     return 0;
 }
 
-static Z_External *create_external_itemRequest()
+static Z_External *create_external_itemRequest(void)
 {
     struct ill_get_ctl ctl;
     ILL_ItemRequest *req;
@@ -2087,6 +2099,9 @@ static int send_itemorder(const char *type, int itemno)
     Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest;
     oident ItemOrderRequest;
 
+
+    req->referenceId = set_refid (out);
+
     ItemOrderRequest.proto = PROTO_Z3950;
     ItemOrderRequest.oclass = CLASS_EXTSERV;
     ItemOrderRequest.value = VAL_ITEMORDER;
@@ -2099,7 +2114,7 @@ static int send_itemorder(const char *type, int itemno)
     return 0;
 }
 
-static int only_z3950()
+static int only_z3950(void)
 {
     if (!conn)
     {
@@ -2126,20 +2141,20 @@ static int cmd_update0(const char *arg)
     return cmd_update_common(arg, 0);
 }
 
+static int cmd_update_Z3950(int version, int action_no, const char *recid,
+                            char *rec_buf, int rec_len);
+
+static int cmd_update_SRW(int action_no, const char *recid,
+                          char *rec_buf, int rec_len);
+
 static int cmd_update_common(const char *arg, int version)
 {
-    Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest );
-    Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest;
-    Z_External *r;
     char action[20], recid[20];
     char *rec_buf;
     int rec_len;
     int action_no;
     int noread = 0;
-    Z_External *record_this = 0;
 
-    if (only_z3950())
-        return 1;
     *action = 0;
     *recid = 0;
     sscanf (arg, "%19s %19s%n", action, recid, &noread);
@@ -2170,6 +2185,60 @@ static int cmd_update_common(const char *arg, int version)
     if (parse_cmd_doc(&arg, out, &rec_buf, &rec_len, 1) == 0)
         return 0;
 
+#if YAZ_HAVE_XML2
+    if (protocol == PROTO_HTTP)
+        return cmd_update_SRW(action_no, recid, rec_buf, rec_len);
+#endif
+    return cmd_update_Z3950(version, action_no, recid, rec_buf, rec_len);
+}
+
+#if YAZ_HAVE_XML2
+static int cmd_update_SRW(int action_no, const char *recid,
+                          char *rec_buf, int rec_len)
+{
+    if (!conn)
+        cmd_open(0);
+    if (!conn)
+        return 0;
+    else
+    {
+        Z_SRW_PDU *srw = yaz_srw_get(out, Z_SRW_update_request);
+        Z_SRW_updateRequest *sr = srw->u.update_request;
+
+        switch(action_no)
+        {
+        case Z_IUOriginPartToKeep_recordInsert:
+            sr->operation = "info:srw/action/1/create";
+            break;
+        case Z_IUOriginPartToKeep_recordReplace:
+            sr->operation = "info:srw/action/1/replace";
+            break;
+        case Z_IUOriginPartToKeep_recordDelete:
+            sr->operation = "info:srw/action/1/delete";
+            break;
+        }
+        if (rec_buf)
+        {
+            sr->record = yaz_srw_get_record(out);
+            sr->record->recordData_buf = rec_buf;
+            sr->record->recordData_len = rec_len;
+            sr->record->recordSchema = record_schema;
+        }
+        if (recid)
+            sr->recordId = odr_strdup(out, recid);
+        return send_srw(srw);
+    }
+}
+#endif
+                          
+static int cmd_update_Z3950(int version, int action_no, const char *recid,
+                            char *rec_buf, int rec_len)
+{
+    Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest );
+    Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest;
+    Z_External *r;
+    Z_External *record_this = 0;
+
     if (rec_buf)
         record_this = z_ext_record (out, VAL_TEXT_XML, rec_buf, rec_len);
     else
@@ -2223,7 +2292,7 @@ static int cmd_update_common(const char *arg, int version)
         notToKeep->elements[0] = (Z_IU0SuppliedRecords_elem *)
             odr_malloc(out, sizeof(**notToKeep->elements));
         notToKeep->elements[0]->which = Z_IUSuppliedRecords_elem_opaque;
-        if (*recid)
+        if (*recid && strcmp(recid, "none"))
         {
             notToKeep->elements[0]->u.opaque = (Odr_oct *)
                 odr_malloc (out, sizeof(Odr_oct));
@@ -2291,14 +2360,17 @@ static int cmd_xmles(const char *arg)
         return 1;
     else
     {
+        char *asn_buf = 0;
         int noread = 0;
         char oid_str[51];
         int oid_value_xmles = VAL_XMLES;
         Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest);
         Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest;
         
+
         Z_External *ext = (Z_External *) odr_malloc(out, sizeof(*ext));
         
+        req->referenceId = set_refid (out);
         req->taskSpecificParameters = ext;
         ext->indirect_reference = 0;
         ext->descriptor = 0;
@@ -2317,10 +2389,13 @@ static int cmd_xmles(const char *arg)
             printf("Bad OID: %s\n", oid_str);
             return 0;
         }
-        
-        if (parse_cmd_doc(&arg, out, (char **) &ext->u.single_ASN1_type->buf,
+
+        if (parse_cmd_doc(&arg, out, &asn_buf,
                           &ext->u.single_ASN1_type->len, 0) == 0)
             return 0;
+
+        ext->u.single_ASN1_type->buf = (unsigned char *) asn_buf;
+
         req->packageType = yaz_oidval_to_z3950oid(out, CLASS_EXTSERV,
                                                   oid_value_xmles);
         
@@ -2384,7 +2459,7 @@ static int cmd_explain(const char *arg)
 {
     if (protocol != PROTO_HTTP)
         return 0;
-#if HAVE_XML2
+#if YAZ_HAVE_XML2
     if (!conn)
         cmd_open(0);
     if (conn)
@@ -2425,11 +2500,11 @@ static int cmd_sru(const char *arg)
     }
     else
     {
-        if (yaz_matchstr(arg, "post"))
+        if (!yaz_matchstr(arg, "post"))
             sru_method = "post";
-        else if (yaz_matchstr(arg, "get"))
+        else if (!yaz_matchstr(arg, "get"))
             sru_method = "get";
-        else if (yaz_matchstr(arg, "soap"))
+        else if (!yaz_matchstr(arg, "soap"))
             sru_method = "soap";
         else
         {
@@ -2449,7 +2524,7 @@ static int cmd_find(const char *arg)
     }
     if (protocol == PROTO_HTTP)
     {
-#if HAVE_XML2
+#if YAZ_HAVE_XML2
         if (!conn)
             cmd_open(0);
         if (!conn)
@@ -2657,7 +2732,7 @@ static int send_presentRequest(const char *arg)
     return 2;
 }
 
-#if HAVE_XML2
+#if YAZ_HAVE_XML2
 static int send_SRW_presentRequest(const char *arg)
 {
     char setstring[100];
@@ -2725,7 +2800,7 @@ static int cmd_show(const char *arg)
 {
     if (protocol == PROTO_HTTP)
     {
-#if HAVE_XML2
+#if YAZ_HAVE_XML2
         if (!conn)
             cmd_open(0);
         if (!conn)
@@ -3046,7 +3121,7 @@ int cmd_scan(const char *arg)
 {
     if (protocol == PROTO_HTTP)
     {
-#if HAVE_XML2
+#if YAZ_HAVE_XML2
         if (!conn)
             cmd_open(0);
         if (!conn)
@@ -3633,7 +3708,7 @@ int cmd_push_command(const char* arg)
     return 1;
 }
 
-void source_rcfile() 
+void source_rcfile(void)
 {
     /*  Look for a $HOME/.yazclientrc and source it if it exists */
     struct stat statbuf;
@@ -3700,7 +3775,7 @@ static void initialize(void)
 struct timeval tv_start;
 #endif
 
-#if HAVE_XML2
+#if YAZ_HAVE_XML2
 static void handle_srw_record(Z_SRW_record *rec)
 {
     if (rec->recordPosition)
@@ -3804,16 +3879,15 @@ static void http_response(Z_HTTP_Response *hres)
     {
         Z_SOAP *soap_package = 0;
         ODR o = odr_createmem(ODR_DECODE);
-        Z_SOAP_Handler soap_handlers[2] = {
-            {"http://www.loc.gov/zing/srw/", 0,
-             (Z_SOAP_fun) yaz_srw_codec},
+        Z_SOAP_Handler soap_handlers[3] = {
+            {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec},
+            {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec},
             {0, 0, 0}
         };
         ret = z_soap_codec(o, &soap_package,
                            &hres->content_buf, &hres->content_len,
                            soap_handlers);
-        if (!ret && soap_package->which == Z_SOAP_generic &&
-            soap_package->u.generic->no == 0)
+        if (!ret && soap_package->which == Z_SOAP_generic)
         {
             Z_SRW_PDU *sr = soap_package->u.generic->p;
             if (sr->which == Z_SRW_searchRetrieve_response)
@@ -3822,11 +3896,14 @@ static void http_response(Z_HTTP_Response *hres)
                 handle_srw_explain_response(sr->u.explain_response);
             else if (sr->which == Z_SRW_scan_response)
                 handle_srw_scan_response(sr->u.scan_response);
+            else if (sr->which == Z_SRW_update_response)
+                printf("Got update response. Status: %s\n",
+                       sr->u.update_response->operationStatus);
             else
                 ret = -1;
         }
         else if (soap_package && (soap_package->which == Z_SOAP_fault
-                          || soap_package->which == Z_SOAP_error))
+                                  || soap_package->which == Z_SOAP_error))
         {
             printf ("HTTP Error Status=%d\n", hres->code);
             printf ("SOAP Fault code %s\n",
@@ -3838,7 +3915,10 @@ static void http_response(Z_HTTP_Response *hres)
                         soap_package->u.fault->details);
         }
         else
+        {
+            printf("z_soap_codec failed. (no SOAP error)\n");
             ret = -1;
+        }
         odr_destroy(o);
     }
     if (ret)
@@ -3999,7 +4079,7 @@ void wait_and_handle_response(int one_response_only)
                 close_session ();
             }
         }
-#if HAVE_XML2
+#if YAZ_HAVE_XML2
         else if (gdu->which == Z_GDU_HTTP_Response)
         {
             http_response(gdu->u.HTTP_Response);
@@ -4307,7 +4387,7 @@ static struct {
     {"attributeset", cmd_attributeset, "<attrset>",complete_attributeset,0,NULL},
     {"querytype", cmd_querytype, "<type>",complete_querytype,0,NULL},
     {"refid", cmd_refid, "<id>",NULL,0,NULL},
-    {"itemorder", cmd_itemorder, "ill|item <itemno>",NULL,0,NULL},
+    {"itemorder", cmd_itemorder, "ill|item|xml <itemno>",NULL,0,NULL},
     {"update", cmd_update, "<action> <recid> [<doc>]",NULL,0,NULL},
     {"update0", cmd_update0, "<action> <recid> [<doc>]",NULL,0,NULL},
     {"xmles", cmd_xmles, "<OID> <doc>",NULL,0,NULL},
@@ -4318,6 +4398,7 @@ static struct {
     {"displaycharset", cmd_displaycharset, "<output_charset>",NULL,0,NULL},
     {"marccharset", cmd_marccharset, "<charset_name>",NULL,0,NULL},
     {"lang", cmd_lang, "<language_code>",NULL,0,NULL},
+    {"source", cmd_source_echo, "<filename>",NULL,1,NULL},
     {".", cmd_source_echo, "<filename>",NULL,1,NULL},
     {"!", cmd_subshell, "Subshell command",NULL,1,NULL},
     {"set_apdufile", cmd_set_apdufile, "<filename>",NULL,1,NULL},