/* This file is part of the YAZ toolkit.
- * Copyright (C) 1995-2010 Index Data
+ * Copyright (C) 1995-2011 Index Data
* See the file LICENSE for details.
*/
/** \file client.c
* \brief yaz-client program
*/
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
-#include <ctype.h>
#ifndef WIN32
#include <signal.h>
#endif
#include <yaz/comstack.h>
#include <yaz/oid_db.h>
-#define NO_OID 1
#include <yaz/proto.h>
#include <yaz/marcdisp.h>
#include <yaz/diagbib1.h>
static int mediumSetPresentNumber = 0;
static Z_ElementSetNames *elementSetNames = 0;
static Z_FacetList *facet_list = 0;
+static ODR facet_odr = 0;
static Odr_int setno = 1; /* current set offset */
static enum oid_proto protocol = PROTO_Z3950; /* current app protocol */
#define RECORDSYNTAX_MAX 20
static Odr_bitmask z3950_options;
static int z3950_version = 3;
static int scan_stepSize = 0;
-static int scan_position = 1;
+static char scan_position[64];
static int scan_size = 20;
static char cur_host[200];
static Odr_int last_hit_count = 0;
+static int pretty_xml = 0;
typedef enum {
QueryType_Prefix,
buf = odr_getbuf(out, &len, 0);
if (ber_file)
odr_dumpBER(ber_file, buf, len);
- /* printf ("sending APDU of size %d\n", len); */
do_hex_dump(buf, len);
if (cs_put(conn, buf, len) < 0)
{
- fprintf(stderr, "cs_put: %s", cs_errmsg(cs_errno(conn)));
+ fprintf(stderr, "cs_put: %s\n", cs_errmsg(cs_errno(conn)));
close_session();
return 0;
}
strncpy(cur_host, arg, sizeof(cur_host)-1);
cur_host[sizeof(cur_host)-1] = 0;
}
- /* TODO Make facet definition survive the open command without crashing */
- /* TODO Fix deallocation */
- facet_list = 0;
-
set_base("");
r = session_connect(cur_host);
if (conn && conn->protocol == PROTO_HTTP)
printf("\n");
}
+static void print_xml_record(const char *buf, size_t len)
+{
+ int has_printed = 0;
+#if YAZ_HAVE_XML2
+ if (pretty_xml)
+ {
+ xmlDocPtr doc;
+ xmlKeepBlanksDefault(0); /* get get xmlDocFormatMemory to work! */
+ doc = xmlParseMemory(buf, len);
+ if (doc)
+ {
+ xmlChar *xml_mem;
+ int xml_size;
+ xmlDocDumpFormatMemory(doc, &xml_mem, &xml_size, 1);
+ fwrite(xml_mem, 1, xml_size, stdout);
+ xmlFree(xml_mem);
+ xmlFreeDoc(doc);
+ has_printed = 1;
+ }
+ }
+#endif
+ if (!has_printed)
+ fwrite(buf, 1, len, stdout);
+}
+
static void display_record(Z_External *r)
{
const Odr_oid *oid = r->direct_reference;
|| !oid_oidcmp(oid, yaz_oid_recsyn_xml)
|| !oid_oidcmp(oid, yaz_oid_recsyn_html))
{
- fwrite(octet_buf, 1, octet_len, stdout);
+ print_xml_record(octet_buf, octet_len);
+
}
else if (yaz_oid_is_iso2709(oid))
{
{
yaz_sru_soap_encode(gdu->u.HTTP_Request, sr, out, charset);
}
+ else if (!yaz_matchstr(sru_method, "solr"))
+ {
+ yaz_solr_encode_request(gdu->u.HTTP_Request, sr, out, charset);
+ }
+
return send_gdu(gdu);
}
}
-static int send_SRW_scanRequest(const char *arg, int pos, int num)
+static int send_SRW_scanRequest(const char *arg, Odr_int *pos, int num)
{
Z_SRW_PDU *sr = 0;
printf("Only CQL and PQF supported in SRW\n");
return 0;
}
- sr->u.scan_request->responsePosition = odr_intdup(out, pos);
+ sr->u.scan_request->responsePosition = pos;
sr->u.scan_request->maximumTerms = odr_intdup(out, num);
return send_srw(sr);
}
return 0;
}
sr->u.request->maximumRecords = odr_intdup(out, 0);
-
+ sr->u.request->facetList = facet_list;
if (record_schema)
sr->u.request->recordSchema = record_schema;
if (recordsyntax_size == 1 && !yaz_matchstr(recordsyntax_list[0], "xml"))
switch (term->which)
{
case Z_Term_general:
- printf(" %.*s", term->u.general->len, term->u.general->buf);
+ printf("%.*s", term->u.general->len, term->u.general->buf);
break;
case Z_Term_characterString:
- printf(" %s", term->u.characterString);
+ printf("%s", term->u.characterString);
break;
case Z_Term_numeric:
- printf(" " ODR_INT_PRINTF, *term->u.numeric);
+ printf(ODR_INT_PRINTF, *term->u.numeric);
break;
case Z_Term_null:
- printf(" null");
+ printf("null");
break;
}
}
struct yaz_facet_attr attr_values;
attr_values.errcode = 0;
attr_values.limit = -1;
- attr_values.useattr = 0;
+ attr_values.useattr = "NONE";
attr_values.relation = "default";
yaz_facet_attr_get_z_attributes(al, &attr_values);
if (!attr_values.errcode)
{
int term_index;
- printf(" %s (%d): \n", attr_values.useattr, /* attr_values.relation, attr_values.limit, */ facet->num_terms);
+ printf(" %s (%d): \n", attr_values.useattr, facet->num_terms);
for (term_index = 0 ; term_index < facet->num_terms; term_index++)
{
Z_FacetTerm *facetTerm = facet->terms[term_index];
+ printf(" ");
display_term(facetTerm->term);
printf(" (" NMEM_INT_PRINTF ")\n", *facetTerm->count);
}
#if YAZ_HAVE_XML2
if (protocol == PROTO_HTTP)
- return send_SRW_update(action_no, recid_buf, rec_buf, rec_len);
+ return send_SRW_update(action_no, recid, rec_buf, rec_len);
#endif
- return send_Z3950_update(version, action_no, recid_buf, rec_buf, rec_len);
+ return send_Z3950_update(version, action_no, recid, rec_buf, rec_len);
}
#if YAZ_HAVE_XML2
}
else
{
- int r;
- r = sscanf(arg, "%9s %9s", sru_method, sru_version);
+ int r = sscanf(arg, "%9s %9s", sru_method, sru_version);
if (r >= 1)
{
if (!yaz_matchstr(sru_method, "post"))
;
else if (!yaz_matchstr(sru_method, "soap"))
;
+ else if (!yaz_matchstr(sru_method, "solr"))
+ ;
else
{
strcpy(sru_method, "soap");
printf("Unknown SRU method: %s\n", arg);
- printf("Specify one of POST, GET, SOAP\n");
+ printf("Specify one of POST, GET, SOAP, SOLR\n");
}
}
}
static int cmd_facets(const char *arg)
{
- int size = 0;
+ if (!facet_odr)
+ facet_odr = odr_createmem(ODR_ENCODE);
+ odr_reset(facet_odr);
+
if (!*arg)
{
facet_list = 0;
printf("Facets cleared.\n");
return 0;
}
- size = strlen(arg);
- if (only_z3950())
+ facet_list = yaz_pqf_parse_facet_list(facet_odr, arg);
+ if (!facet_list)
{
- printf("Currently only supported for Z39.50.\n");
+ printf("Invalid facet list: %s", arg);
return 0;
}
- else
- {
- /* TODO Wrong odr. Loosing memory */
- ODR odr = odr_createmem(ODR_ENCODE);
- facet_list = yaz_pqf_parse_facet_list(odr, arg);
-
- if (!facet_list)
- {
- printf("Invalid facet list: %s", arg);
- return 0;
- }
- return 1;
- }
- return 2;
+ return 1;
}
-
static int cmd_delete(const char *arg)
{
if (only_z3950())
/* PRESENT SERVICE ----------------------------- */
+size_t check_token(const char *haystack, const char *token)
+{
+ size_t len = strlen(token);
+ size_t extra;
+ if (strncmp(haystack, token, len))
+ return 0;
+ for (extra = 0; haystack[extra + len] != '\0'; extra++)
+ if (!strchr(" \r\n\t", haystack[extra + len]))
+ {
+ if (extra)
+ break;
+ else
+ return 0; /* no whitespace after token */
+ }
+ return extra + len;
+}
+
static int parse_show_args(const char *arg_c, char *setstring,
Odr_int *start, Odr_int *number)
{
char *end_ptr;
Odr_int start_position;
+ size_t token_len;
if (setnumber >= 0)
sprintf(setstring, "%d", setnumber);
else
*setstring = '\0';
+
+ token_len = check_token(arg_c, "format");
+ if (token_len)
+ {
+ pretty_xml = 1;
+ arg_c += token_len;
+ }
+ else
+ pretty_xml = 0;
- if (!strcmp(arg_c, "all"))
+ token_len = check_token(arg_c, "all");
+ if (token_len)
{
*number = last_hit_count;
*start = 1;
+ return 1;
}
start_position = odr_strtol(arg_c, &end_ptr, 10);
if (end_ptr == arg_c)
*start = start_position;
if (*end_ptr == '\0')
return 1;
- while (isspace(*(unsigned char *)end_ptr))
+ while (yaz_isspace(*end_ptr))
end_ptr++;
if (*end_ptr != '+')
{
}
if (*end_ptr == '\0')
return 1;
- while (isspace(*(unsigned char *)end_ptr))
+ while (yaz_isspace(*end_ptr))
end_ptr++;
if (*end_ptr != '+')
{
}
static int send_Z3950_scanrequest(const char *set, const char *query,
- Odr_int pp, Odr_int num, const char *term)
+ Odr_int *pos, Odr_int num, const char *term)
{
Z_APDU *apdu = zget_APDU(out, Z_APDU_scanRequest);
Z_ScanRequest *req = apdu->u.scanRequest;
if (only_z3950())
return 0;
+ printf("query: %s\n", query);
if (queryType == QueryType_CCL2RPN)
{
int error, pos;
req->num_databaseNames = num_databaseNames;
req->databaseNames = databaseNames;
req->numberOfTermsRequested = #
- req->preferredPositionInResponse = &pp;
+ req->preferredPositionInResponse = pos;
req->stepSize = odr_intdup(out, scan_stepSize);
if (set)
static int cmd_scanpos(const char *arg)
{
- int r = sscanf(arg, "%d", &scan_position);
- if (r == 0)
- scan_position = 1;
+ if (!strcmp(arg, "none"))
+ strcpy(scan_position, "none");
+ else
+ {
+ int dummy;
+ int r = sscanf(arg, "%d", &dummy);
+ if (r == 1 && strlen(arg) < sizeof(scan_position)-1)
+ strcpy(scan_position, arg);
+ else
+ printf("specify number of none for scanpos\n");
+ }
return 0;
}
static int cmd_scan_common(const char *set, const char *arg)
{
+ Odr_int pos, *pos_p = 0;
+ const char *scan_term = 0;
+ const char *scan_query = 0;
+
+ if (!*arg)
+ {
+ pos = 1;
+ pos_p = &pos;
+ scan_query = last_scan_query;
+ scan_term = last_scan_line;
+ }
+ else
+ {
+ strcpy(last_scan_query, arg);
+ scan_query = arg;
+ if (strcmp(scan_position, "none"))
+ {
+ pos = odr_atoi(scan_position);
+ pos_p = &pos;
+ }
+ }
+
if (protocol == PROTO_HTTP)
{
#if YAZ_HAVE_XML2
session_connect(cur_host);
if (!conn)
return 0;
- if (*arg)
- {
- if (send_SRW_scanRequest(arg, scan_position, scan_size) < 0)
- return 0;
- }
- else
- {
- if (send_SRW_scanRequest(last_scan_line, 1, scan_size) < 0)
- return 0;
- }
+ if (send_SRW_scanRequest(scan_query, pos_p, scan_size) < 0)
+ return 0;
return 2;
#else
return 0;
printf("Target doesn't support scan\n");
return 0;
}
- if (*arg)
- {
- strcpy(last_scan_query, arg);
- if (send_Z3950_scanrequest(set, arg,
- scan_position, scan_size, 0) < 0)
- return 0;
- }
- else
- {
- if (send_Z3950_scanrequest(set, last_scan_query,
- 1, scan_size, last_scan_line) < 0)
- return 0;
- }
+ if (send_Z3950_scanrequest(set, scan_query, pos_p,
+ scan_size, scan_term) < 0)
+ return 0;
return 2;
}
}
exit(1);
}
+ strcpy(scan_position, "1");
+
setvbuf(stdout, 0, _IONBF, 0);
if (apdu_file)
odr_setprint(print, apdu_file);
printf("\n");
if (rec->recordData_buf && rec->recordData_len)
{
- printf("%.*s", rec->recordData_len, rec->recordData_buf);
+ print_xml_record(rec->recordData_buf, rec->recordData_len);
marc_file_write(rec->recordData_buf, rec->recordData_len);
}
else
}
if (res->numberOfRecords)
printf("Number of hits: " ODR_INT_PRINTF "\n", *res->numberOfRecords);
+ if (res->facetList)
+ display_facets(res->facetList);
+ if (res->suggestions)
+ printf("Suggestions:\n%s\n", res->suggestions);
for (i = 0; i<res->num_records; i++)
handle_srw_record(res->records + i);
}
int ret = -1;
const char *connection_head = z_HTTP_header_lookup(hres->headers,
"Connection");
-
if (hres->code != 200)
{
printf("HTTP Error Status=%d\n", hres->code);
printf("Content type does not appear to be XML\n");
else
{
- Z_SOAP *soap_package = 0;
- ODR o = odr_createmem(ODR_DECODE);
- 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)
+ if (!yaz_matchstr(sru_method, "solr"))
{
- Z_SRW_PDU *sr = (Z_SRW_PDU *) soap_package->u.generic->p;
- if (sr->which == Z_SRW_searchRetrieve_response)
+ Z_SRW_PDU *sr = 0;
+ ODR o = odr_createmem(ODR_DECODE);
+ ret = yaz_solr_decode_response(o, hres, &sr);
+
+ if (ret == 0 && sr->which == Z_SRW_searchRetrieve_response)
handle_srw_response(sr->u.response);
- else if (sr->which == Z_SRW_explain_response)
- 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
{
- printf("Decoding of SRW package failed\n");
+ printf("Decoding of SOLR package failed\n");
ret = -1;
}
- }
- else if (soap_package && (soap_package->which == Z_SOAP_fault
- || soap_package->which == Z_SOAP_error))
- {
- printf("SOAP Fault code %s\n",
- soap_package->u.fault->fault_code);
- printf("SOAP Fault string %s\n",
- soap_package->u.fault->fault_string);
- if (soap_package->u.fault->details)
- printf("SOAP Details %s\n",
- soap_package->u.fault->details);
+ odr_destroy(o);
}
else
{
- printf("z_soap_codec failed. (no SOAP error)\n");
- ret = -1;
+ Z_SOAP *soap_package = 0;
+ ODR o = odr_createmem(ODR_DECODE);
+ 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)
+ {
+ Z_SRW_PDU *sr = (Z_SRW_PDU *) soap_package->u.generic->p;
+ if (sr->which == Z_SRW_searchRetrieve_response)
+ handle_srw_response(sr->u.response);
+ else if (sr->which == Z_SRW_explain_response)
+ 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
+ {
+ printf("Decoding of SRW package failed\n");
+ ret = -1;
+ }
+ }
+ else if (soap_package && (soap_package->which == Z_SOAP_fault
+ || soap_package->which == Z_SOAP_error))
+ {
+ printf("SOAP Fault code %s\n",
+ soap_package->u.fault->fault_code);
+ printf("SOAP Fault string %s\n",
+ soap_package->u.fault->fault_string);
+ if (soap_package->u.fault->details)
+ printf("SOAP Details %s\n",
+ soap_package->u.fault->details);
+ }
+ else
+ {
+ printf("z_soap_codec failed. (no SOAP error)\n");
+ ret = -1;
+ }
+ odr_destroy(o);
}
- odr_destroy(o);
}
if (ret)
close_session(); /* close session on error */
for (; *p; ++p)
{
- if (!isspace(*(unsigned char *) p))
+ if (!yaz_isspace(*p))
lastnonspace = p;
}
if (lastnonspace)