* Copyright (c) 1995-2003, Index Data
* See the file LICENSE for details.
*
- * $Id: client.c,v 1.188 2003-04-29 21:13:08 adam Exp $
+ * $Id: client.c,v 1.197 2003-05-22 23:55:19 mike Exp $
*/
#include <stdio.h>
#include <yaz/ill.h>
#include <yaz/srw.h>
#include <yaz/yaz-ccl.h>
+#include <yaz/cql.h>
#if HAVE_READLINE_READLINE_H
#include <readline/readline.h>
static char *codeset = 0; /* character set for output */
static ODR out, in, print; /* encoding and decoding streams */
+#ifdef THESE_ARE_NOT_USED
static ODR srw_sr_odr_out = 0;
static Z_SRW_PDU *srw_sr = 0;
+#endif /*THESE_ARE_NOT_USED*/
static FILE *apdu_file = 0;
static FILE *ber_file = 0;
static COMSTACK conn = 0; /* our z-association */
static int setno = 1; /* current set offset */
static enum oid_proto protocol = PROTO_Z3950; /* current app protocol */
static enum oid_value recordsyntax = VAL_USMARC;
-//static enum oid_value schema = VAL_NONE;
static char *schema = 0;
static int sent_close = 0;
static NMEM session_mem = NULL; /* memory handle for init-response */
static char last_scan_line[512] = "0";
static char last_scan_query[512] = "0";
static char ccl_fields[512] = "default.bib";
-static char* esPackageName = 0;
-static char* yazProxy = 0;
+/* ### How can I set this path to use wherever YAZ is installed? */
+static char cql_fields[512] = "/usr/local/share/yaz/etc/pqf.properties";
+static char *esPackageName = 0;
+static char *yazProxy = 0;
static int kilobytes = 1024;
-static char* yazCharset = 0;
+static char *negotiationCharset = 0;
+static char *outputCharset = 0;
+static char *marcCharset = 0;
static char* yazLang = 0;
static char last_cmd[32] = "?";
QueryType_Prefix,
QueryType_CCL,
QueryType_CCL2RPN,
- QueryType_CQL
+ QueryType_CQL,
+ QueryType_CQL2RPN
} QueryType;
static QueryType queryType = QueryType_Prefix;
static CCL_bibset bibset; /* CCL bibset handle */
+static cql_transform_t cqltrans; /* CQL qualifier-set handle */
#if HAVE_READLINE_COMPLETION_OVER
case QueryType_CCL: return "CCL (CCL sent to server) ";
case QueryType_CCL2RPN: return "CCL -> RPN (RPN sent to server)";
case QueryType_CQL: return "CQL (CQL sent to server)";
+ case QueryType_CQL2RPN: return "CQL -> RPN (RPN sent to server)";
default:
return "unknown Query type internal yaz-client error";
}
}
}
-void send_apdu(Z_APDU *a)
+int send_apdu(Z_APDU *a)
{
char *buf;
int len;
{
odr_perror(out, "Encoding APDU");
close_session();
- return;
+ return 0;
}
buf = odr_getbuf(out, &len, 0);
if (ber_file)
{
fprintf(stderr, "cs_put: %s", cs_errmsg(cs_errno(conn)));
close_session();
- return;
+ return 0;
}
do_hex_dump(buf,len);
odr_reset(out); /* release the APDU structure */
+ return 1;
}
static void print_stringn(const unsigned char *buf, size_t len)
yaz_oi_set_string_oidval(&req->otherInfo, out, VAL_PROXY,
1, type_and_host);
- if (yazCharset || yazLang) {
+ if (negotiationCharset || yazLang) {
Z_OtherInformation **p;
Z_OtherInformationUnit *p0;
p0->which = Z_OtherInfo_externallyDefinedInfo;
p0->information.externallyDefinedInfo =
- yaz_set_proposal_charneg(out,
- (const char**)&yazCharset, (yazCharset)?1:0,
- (const char**)&yazLang, (yazLang)?1:0, 1);
+ yaz_set_proposal_charneg(
+ out,
+ (const char**)&negotiationCharset,
+ negotiationCharset ? 1 : 0,
+ (const char**)&yazLang, yazLang ? 1 : 0, 1);
}
}
- send_apdu(apdu);
- printf("Sent initrequest.\n");
+ if (send_apdu(apdu))
+ printf("Sent initrequest.\n");
}
static int process_initResponse(Z_InitResponse *res)
return 0;
}
-static int cmd_base(const char *arg)
+static int set_base(const char *arg)
{
int i;
const char *cp;
- if (!*arg)
- {
- printf("Usage: base <database> <database> ...\n");
- return 0;
- }
for (i = 0; i<num_databaseNames; i++)
xfree (databaseNames[i]);
num_databaseNames = 0;
break;
arg = cp+1;
}
+ if (num_databaseNames == 0)
+ {
+ num_databaseNames = 1;
+ databaseNames[0] = xstrdup("");
+ }
return 1;
}
-void cmd_open_remember_last_open_command(const char* arg, char* new_open_command)
+static int cmd_base(const char *arg)
{
- if(last_open_command != arg)
+ if (!*arg)
{
- if(last_open_command) xfree(last_open_command);
- last_open_command = xstrdup(new_open_command);
+ printf("Usage: base <database> <database> ...\n");
+ return 0;
}
+ return set_base(arg);
}
-int cmd_open(const char *arg)
+void cmd_open_remember_last_open_command(const char* arg, char* new_open_command)
{
- static char cur_host[200];
- if (arg)
+ if(last_open_command != arg)
{
- strncpy (cur_host, arg, sizeof(cur_host)-1);
- cur_host[sizeof(cur_host)-1] = 0;
+ if(last_open_command) xfree(last_open_command);
+ last_open_command = xstrdup(new_open_command);
}
- return session_connect(cur_host);
}
int session_connect(const char *arg)
const char *basep = 0;
if (conn)
{
- printf("Already connected.\n");
-
cs_close (conn);
conn = NULL;
if (session_mem)
}
#if HAVE_XML2
#else
- if (conn->protocol == PROTO_Z3950)
+ if (conn->protocol == PROTO_HTTP)
{
- printf ("SRW not enabled in this YAZ\n");
+ printf ("SRW/HTTP not enabled in this YAZ\n");
cs_close(conn);
conn = 0;
return 0;
}
#endif
+ protocol = conn->protocol;
+ if (conn->protocol == PROTO_HTTP)
+ set_base("");
+ else
+ set_base("Default");
printf("Connecting...");
fflush(stdout);
if (cs_connect(conn, add) < 0)
}
printf("OK.\n");
if (basep && *basep)
- cmd_base (basep);
- if (conn->protocol == PROTO_Z3950)
+ set_base (basep);
+ if (protocol == PROTO_Z3950)
{
send_initRequest(type_and_host);
return 2;
return 0;
}
+int cmd_open(const char *arg)
+{
+ static char cur_host[200];
+ if (arg)
+ {
+ strncpy (cur_host, arg, sizeof(cur_host)-1);
+ cur_host[sizeof(cur_host)-1] = 0;
+ }
+ return session_connect(cur_host);
+}
+
void try_reconnect()
{
char* open_command;
&result, &rlen)> 0)
{
char *from = 0;
- if (ent->value == VAL_USMARC)
+ if (marcCharset && strcmp(marcCharset, "auto"))
+ from = marcCharset;
+ else
{
- if (octet_buf[9] == 'a')
- from = "UTF-8";
+ if (ent->value == VAL_USMARC)
+ {
+ if (octet_buf[9] == 'a')
+ from = "UTF-8";
+ else
+ from = "MARC8";
+ }
else
- from = "MARC8";
+ from = "ISO-8859-1";
}
- else
- from = "ISO-8859-1";
-
- if (codeset && from)
+ if (outputCharset && from)
{
- printf ("convert from %s to %s\n", from, codeset);
- cd = yaz_iconv_open(codeset, from);
+ printf ("convert from %s to %s\n", from,
+ outputCharset);
+ cd = yaz_iconv_open(outputCharset, from);
}
if (!cd)
fwrite (result, 1, rlen, stdout);
#if HAVE_XML2
static int send_srw(Z_SRW_PDU *sr)
{
- const char *charset = 0;
+ const char *charset = negotiationCharset;
const char *host_port = 0;
- const char *path = "/";
+ char *path = 0;
char ctype[50];
Z_SOAP_Handler h[2] = {
{"http://www.loc.gov/zing/srw/v1.0/", 0, (Z_SOAP_fun) yaz_srw_codec},
Z_SOAP *p = odr_malloc(o, sizeof(*p));
Z_GDU *gdu;
+ path = odr_malloc(out, strlen(databaseNames[0])+2);
+ *path = '/';
+ strcpy(path+1, databaseNames[0]);
gdu = z_get_HTTP_Request(out);
gdu->u.HTTP_Request->path = odr_strdup(out, path);
}
odr_reset(srw_sr_odr_out);
+ setno = 1;
+
/* save this for later .. when fetching individual records */
srw_sr = sr = yaz_srw_get(srw_sr_odr_out, Z_SRW_searchRetrieve_request);
sr->u.request->query_type = Z_SRW_query_type_cql;
Odr_oct ccl_query;
YAZ_PQF_Parser pqf_parser;
Z_External *ext;
+ QueryType myQueryType = queryType;
+ char pqfbuf[512];
- if (queryType == QueryType_CCL2RPN)
+ if (myQueryType == QueryType_CCL2RPN)
{
rpn = ccl_find_str(bibset, arg, &error, &pos);
if (error)
printf("CCL ERROR: %s\n", ccl_err_msg(error));
return 0;
}
+ } else if (myQueryType == QueryType_CQL2RPN) {
+ /* ### All this code should be wrapped in a utility function */
+ CQL_parser parser;
+ struct cql_node *node;
+ const char *addinfo;
+ if (cqltrans == 0) {
+ printf("Can't use CQL: no translation file. Try set_cqlfile\n");
+ return 0;
+ }
+ parser = cql_parser_create();
+ if ((error = cql_parser_string(parser, arg)) != 0) {
+ /* ### must do better with the reporting here */
+ printf("CQL ERROR %d: presumably a syntax error?\n", error);
+ return 0;
+ }
+ node = cql_parser_result(parser);
+ if ((error = cql_transform_buf(cqltrans, node, pqfbuf,
+ sizeof pqfbuf)) != 0) {
+ error = cql_transform_error(cqltrans, &addinfo);
+ printf ("Couldn't convert CQL to PQF: error #%d (addinfo=%s)\n",
+ error, addinfo);
+ return 0;
+ }
+ arg = pqfbuf;
+ myQueryType = QueryType_Prefix;
}
+
req->referenceId = set_refid (out);
if (!strcmp(arg, "@big")) /* strictly for troublemaking */
{
req->query = &query;
- switch (queryType)
+ switch (myQueryType)
{
case QueryType_Prefix:
query.which = Z_Query_type_1;
printf ("Unsupported query type\n");
return 0;
}
- send_apdu(apdu);
+ if (send_apdu(apdu))
+ printf("Sent searchRequest.\n");
setno = 1;
- printf("Sent searchRequest.\n");
return 2;
}
static int only_z3950()
{
- if (conn && conn->protocol == PROTO_HTTP)
+ if (protocol == PROTO_HTTP)
{
printf ("Not supported by SRW\n");
return 1;
printf("Find what?\n");
return 0;
}
- if (!conn)
- {
- try_reconnect();
-
- if (!conn) {
- printf("Not connected yet\n");
- return 0;
- }
- }
- if (conn->protocol == PROTO_HTTP)
+ if (protocol == PROTO_HTTP)
{
#if HAVE_XML2
+ if (!conn)
+ cmd_open(0);
if (!send_SRW_searchRequest(arg))
return 0;
#else
}
else
{
+ if (!conn)
+ {
+ try_reconnect();
+
+ if (!conn) {
+ printf("Not connected yet\n");
+ return 0;
+ }
+ }
if (!send_searchRequest(arg))
return 0;
}
oident prefsyn;
int nos = 1;
int oid[OID_SIZE];
- char *p;
char setstring[100];
req->referenceId = set_refid (out);
static void close_session (void)
{
- cs_close (conn);
+ if (conn)
+ cs_close (conn);
conn = 0;
if (session_mem)
{
nmem_destroy (session_mem);
session_mem = NULL;
}
- if (srw_sr)
- {
- odr_destroy(srw_sr_odr_out);
- srw_sr_odr_out = 0;
- srw_sr = 0;
- }
- assert (srw_sr_odr_out == 0);
sent_close = 0;
odr_reset(out);
odr_reset(in);
static int cmd_show(const char *arg)
{
- if (!conn)
- {
- printf("Not connected yet\n");
- return 0;
- }
- if (conn->protocol == PROTO_HTTP)
+ if (protocol == PROTO_HTTP)
{
#if HAVE_XML2
+ if (!conn)
+ cmd_open(0);
if (!send_SRW_presentRequest(arg))
return 0;
#else
}
else
{
+ if (!conn)
+ {
+ printf("Not connected yet\n");
+ return 0;
+ }
if (!send_presentRequest(arg))
return 0;
}
queryType = QueryType_CCL2RPN;
else if (!strcmp(arg, "cql"))
queryType = QueryType_CQL;
+ else if (!strcmp (arg, "cql2rpn") || !strcmp (arg, "cqlrpn"))
+ queryType = QueryType_CQL2RPN;
else
{
printf ("Querytype must be one of:\n");
printf (" ccl - CCL query\n");
printf (" ccl2rpn - CCL query converted to RPN\n");
printf (" cql - CQL\n");
+ printf (" cql2rpn - CQL query converted to RPN\n");
return 0;
}
return 1;
xfree (esPackageName);
esPackageName = NULL;
if (*arg)
- {
- esPackageName = (char *) xmalloc (strlen(arg)+1);
- strcpy (esPackageName, arg);
- }
+ esPackageName = xstrdup(arg);
return 1;
}
int cmd_proxy(const char* arg)
{
- if (*arg == '\0') {
- xfree (yazProxy);
- yazProxy = NULL;
-
- }
xfree (yazProxy);
yazProxy = NULL;
if (*arg)
- {
- yazProxy = (char *) xmalloc (strlen(arg)+1);
- strcpy (yazProxy, arg);
- }
+ yazProxy = xstrdup (arg);
+ return 1;
+}
+
+int cmd_marccharset(const char *arg)
+{
+ char l1[30];
+
+ *l1 = 0;
+ if (sscanf(arg, "%29s", l1) < 1)
+ return 1;
+ xfree (marcCharset);
+ marcCharset = 0;
+ if (strcmp(l1, "-"))
+ marcCharset = xstrdup(l1);
return 1;
}
*l1 = *l2 = 0;
if (sscanf(arg, "%29s %29s", l1, l2) < 1)
{
- printf("Current character set is `%s'\n", (yazCharset) ? yazCharset:NULL);
+ printf("Current negotiation character set is `%s'\n",
+ negotiationCharset ? negotiationCharset: "none");
+ printf("Current output character set is `%s'\n",
+ outputCharset ? outputCharset: "none");
return 1;
}
- xfree (yazCharset);
- yazCharset = NULL;
- if (*l1)
- yazCharset = xstrdup(l1);
+ xfree (negotiationCharset);
+ negotiationCharset = NULL;
+ if (*l1 && strcmp(l1, "-"))
+ {
+ negotiationCharset = xstrdup(l1);
+ printf ("Character set negotiation : %s\n", negotiationCharset);
+ }
+ else
+ printf ("Character set negotiation disabled\n");
if (*l2)
{
- odr_set_charset (out, l1, l2);
- odr_set_charset (in, l2, l1);
+ xfree (outputCharset);
+ outputCharset = 0;
+ if (!strcmp(l2, "auto") && codeset)
+ {
+ if (codeset)
+ {
+ printf ("output charset: %s\n", codeset);
+ outputCharset = xstrdup(codeset);
+
+
+ }
+ else
+ printf ("No codeset found on this system\n");
+ }
+ else if (strcmp(l2, "-"))
+ outputCharset = xstrdup(l2);
+ else
+ printf ("Output charset conversion disabled\n");
+ }
+ if (outputCharset && negotiationCharset)
+ {
+ odr_set_charset (out, negotiationCharset, outputCharset);
+ odr_set_charset (in, outputCharset, negotiationCharset);
+ }
+ else
+ {
+ odr_set_charset (out, 0, 0);
+ odr_set_charset (in, 0, 0);
}
return 1;
}
return 0;
}
+int cmd_set_cqlfile(const char* arg)
+{
+ cql_transform_t newcqltrans;
+
+ if ((newcqltrans = cql_transform_open_fname(arg)) == 0) {
+ perror("unable to open CQL file");
+ return 0;
+ }
+ if (cqltrans != 0)
+ cql_transform_close(cqltrans);
+
+ cqltrans = newcqltrans;
+ strcpy(cql_fields, arg);
+ return 0;
+}
+
int cmd_set_auto_reconnect(const char* arg)
{
if(strlen(arg)==0) {
ccl_qual_file (bibset, inf);
fclose (inf);
}
- cmd_base("Default");
+
+ cqltrans = cql_transform_open_fname(cql_fields);
+ /* If this fails, no problem: we detect cqltrans == 0 later */
#if HAVE_READLINE_READLINE_H
rl_attempted_completion_function = (CPPFunction*)readline_completer;
{
int i;
- printf ("Received SRW SearchRetrieveResponse\n");
+ printf ("Received SRW SearchRetrieve Response\n");
for (i = 0; i<res->num_diagnostics; i++)
{
- printf ("SRW diagnostic %d %s\nDetails: %s\n",
+ printf ("SRW diagnostic %d %s\n",
*res->diagnostics[i].code,
- yaz_diag_srw_str(*res->diagnostics[i].code),
- res->diagnostics[i].details);
+ yaz_diag_srw_str(*res->diagnostics[i].code));
+
+ if (res->diagnostics[i].details)
+ printf ("Details: %s\n", res->diagnostics[i].details);
}
if (res->numberOfRecords)
printf ("Number of hits: %d\n", *res->numberOfRecords);
for (i = 0; i<res->num_records; i++)
{
- int pos;
Z_SRW_record *rec = res->records + i;
if (rec->recordPosition)
setno = *rec->recordPosition + 1;
}
if (rec->recordSchema)
- printf (" scheam=%d", *rec->recordSchema);
+ printf (" schema=%s", rec->recordSchema);
printf ("\n");
if (rec->recordData_buf && rec->recordData_len)
{
}
}
-static void set_HTTP_error (int error,
- const char *addinfo, const char *addinfo2)
-{
-
-
-}
-
-
static void http_response(Z_HTTP_Response *hres)
{
int ret = -1;
"Content-Type");
const char *connection_head = z_HTTP_header_lookup(hres->headers,
"Connection");
- yaz_log (LOG_LOG, "http_response");
-
if (content_type && !yaz_strcmp_del("text/xml", content_type, "; "))
{
Z_SOAP *soap_package = 0;
if (ret)
{
if (hres->code != 200)
- set_HTTP_error(hres->code, 0, 0);
+ {
+ printf ("HTTP Error Status=%d\n", hres->code);
+ }
else
{
- printf ("decoding of SRW package failed\n");
+ printf ("Decoding of SRW package failed\n");
}
close_session();
}
while(conn)
{
- printf ("cs_get....\n");
res = cs_get(conn, &netbuffer, &netbufferlen);
- if (reconnect_ok && res <= 0 && conn->protocol == PROTO_HTTP)
+ if (reconnect_ok && res <= 0 && protocol == PROTO_HTTP)
{
cs_close(conn);
conn = 0;
record_last = 0;
odr_setbuf(in, netbuffer, res, 0);
- printf ("got input packet %d bytes\n", res);
if (!z_GDU(in, &gdu, 0, 0))
{
FILE *f = ber_file ? ber_file : stdout;
printf("Authentication : Unknown\n");
}
}
- if ( yazCharset ) printf("Character set : `%s'\n", (yazCharset) ? yazCharset:NULL);
+ if (negotiationCharset)
+ printf("Neg. Character set : `%s'\n", negotiationCharset);
/* bases */
printf("Bases : ");
/* Query options */
printf("CCL file : %s\n",ccl_fields);
+ printf("CQL file : %s\n",cql_fields);
printf("Query type : %s\n",query_type_as_string(queryType));
printf("Named Result Sets : %s\n",setnumber==-1?"off":"on");
{"update", cmd_update, "<action> <recid> [<file>]",NULL,0,NULL},
{"packagename", cmd_packagename, "<packagename>",NULL,0,NULL},
{"proxy", cmd_proxy, "[('tcp'|'ssl')]<host>[':'<port>]",NULL,0,NULL},
- {"charset", cmd_charset, "<charset_name>",NULL,0,NULL},
+ {"charset", cmd_charset, "<nego_charset> <output_charset>",NULL,0,NULL},
+ {"marccharset", cmd_marccharset, "<charset_name>",NULL,0,NULL},
{"lang", cmd_lang, "<language_code>",NULL,0,NULL},
{".", cmd_source, "<filename>",NULL,1,NULL},
{"!", cmd_subshell, "Subshell command",NULL,1,NULL},
{"set_berfile", cmd_set_berfile, "<filename>",NULL,1,NULL},
{"set_marcdump", cmd_set_marcdump," <filename>",NULL,1,NULL},
{"set_cclfile", cmd_set_cclfile," <filename>",NULL,1,NULL},
+ {"set_cqlfile", cmd_set_cqlfile," <filename>",NULL,1,NULL},
{"set_auto_reconnect", cmd_set_auto_reconnect," on|off",complete_auto_reconnect,1,NULL},
{"set_otherinfo", cmd_set_otherinfo,"<otherinfoinddex> <oid> <string>",NULL,0,NULL},
{"register_oid", cmd_register_oid,"<name> <class> <oid>",NULL,0,NULL},
}
}
+static void show_version(void)
+{
+ char vstr[20];
+
+ yaz_version(vstr, 0);
+ printf ("YAZ version: %s\n", YAZ_VERSION);
+ if (strcmp(vstr, YAZ_VERSION))
+ printf ("YAZ DLL/SO: %s\n", vstr);
+ exit(0);
+}
+
int main(int argc, char **argv)
{
char *prog = *argv;
#endif
#endif
- while ((ret = options("k:c:a:b:m:v:p:u:t:", argv, argc, &arg)) != -2)
+ while ((ret = options("k:c:q:a:b:m:v:p:u:t:V", argv, argc, &arg)) != -2)
{
switch (ret)
{
}
break;
case 't':
- codeset = arg;
+ outputCharset = xstrdup(arg);
break;
case 'c':
strncpy (ccl_fields, arg, sizeof(ccl_fields)-1);
ccl_fields[sizeof(ccl_fields)-1] = '\0';
break;
+ case 'q':
+ strncpy (cql_fields, arg, sizeof(cql_fields)-1);
+ cql_fields[sizeof(cql_fields)-1] = '\0';
+ break;
case 'b':
if (!strcmp(arg, "-"))
ber_file=stderr;
}
break;
case 'v':
- yaz_log_init (yaz_log_mask_str(arg), "", NULL);
+ yaz_log_init(yaz_log_mask_str(arg), "", 0);
+ break;
+ case 'V':
+ show_version();
break;
default:
fprintf (stderr, "Usage: %s [-m <marclog>] [ -a <apdulog>] "
- "[-b berdump] [-c cclfields]\n [-p <proxy-addr>] [-u <auth>] "
- "[-k size] [<server-addr>]\n",
+ "[-b berdump] [-c cclfields] \n"
+ "[-q cqlfields] [-p <proxy-addr>] [-u <auth>] "
+ "[-k size] [-V] [<server-addr>]\n",
prog);
exit (1);
}